|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T
Length: 12129 (0x2f61) Types: TextFile Names: »TabularView.c«
└─⟦8648bda34⟧ Bits:30007244 EUUGD5_II: X11R5 └─⟦87c3ac0e0⟧ »./contrib-3/contrib-3.00« └─⟦de8ce1454⟧ └─⟦this⟧ »contrib/lib/iv/src/bin/doc/TabularView.c«
/* * Copyright (c) 1991 Stanford University * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Stanford not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Stanford makes no representations about * the suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * TabularView */ #include "TabularView.h" #include "DocViewer.h" #include "TabularItem.h" #include "TextItem.h" #include "properties.h" #include <InterViews/aggr.h> #include <InterViews/box.h> #include <InterViews/center.h> #include <InterViews/group.h> #include <InterViews/hit.h> #include <InterViews/listener.h> #include <InterViews/margin.h> #include <InterViews/patch.h> #include <InterViews/rule.h> #include <InterViews/target.h> #include <InterViews/world.h> #include <InterViews/xymarker.h> #include <OS/math.h> #include <string.h> const Coord CELL_MARGIN = 4; const Coord TABULAR_MARGIN = 3; TabularView::TabularView ( DocumentViewer* viewer, ItemView* parent, TabularItem* tabular ) : ItemView(viewer, parent) { _tabular = tabular; _tabular->ref(); _tabular->attach(this); _cells = nil; _rows = nil; _row_patch = nil; _columns = nil; _column_patch = nil; _table = nil; _patch = new Patch(nil); Color* overlay; Color* underlay; _viewer->highlight_colors(SELECT_HIGHLIGHT_COLOR, overlay, underlay); _marker = new XYMarker(_patch, overlay, underlay); _listener->body(new Margin(_marker, TABULAR_MARGIN)); _listener->button(true, Event::left); _active = false; dot(0, 0); } TabularView::~TabularView () { if (_active) { _viewer->focus(nil); } if (_cells != nil) { _cells->unref(); } if (_rows != nil) { _rows->unref(); } if (_row_patch != nil) { _row_patch->unref(); } if (_columns != nil) { _columns->unref(); } if (_column_patch != nil) { _column_patch->unref(); } if (_table != nil) { _table->unref(); } _tabular->detach(this); _tabular->unref(); } void TabularView::dot (long row, long column) { if (row >= 0L) { _row_dot = Math::min(Math::max(row, 0L), _tabular->row_count()); _row_mark = _row_dot; } if (column >= 0) { _column_dot = Math::min( Math::max(column, 0L), _tabular->column_count() ); _column_mark = _column_dot; } } void TabularView::mark (long row, long column) { if (row >= 0L) { _row_mark = Math::min(Math::max(row, 0L), _tabular->row_count()); } if (column >= 0L) { _column_mark = Math::min( Math::max(column, 0L), _tabular->column_count() ); } } void TabularView::repair () { _tabular->notify(); } void TabularView::update () { mark_selection(); } void TabularView::mark_selection () { if (_active) { long cd = Math::min(_column_dot, _column_mark); long cm = Math::max(_column_dot, _column_mark); long rd = Math::min(_row_dot, _row_mark); long rm = Math::max(_row_dot, _row_mark); Allotment cdx, cmx, rmy, rdy; _columns->allotment(cd*2, Dimension_X, cdx); _columns->allotment(cm*2, Dimension_X, cmx); _rows->allotment(rm*2, Dimension_Y, rmy); _rows->allotment(rd*2, Dimension_Y, rdy); Coord l = cdx.begin(); Coord r = cmx.end(); Coord b = rmy.begin(); Coord t = rdy.end(); _marker->mark(l, b, r, t); } else { _marker->unmark(); } } void TabularView::rebuild () { long rows = _tabular->row_count(); long columns = _tabular->column_count(); if (_cells != nil) { _cells->unref(); } _cells = new Aggregate(rows * columns); _cells->ref(); if (_columns != nil) { _columns->unref(); } _columns = new LRBox(); _columns->ref(); if (_column_patch != nil) { _column_patch->unref(); } _column_patch = new Patch(_columns); _column_patch->ref(); if (_rows != nil) { _rows->unref(); } _rows = new TBBox(); _rows->ref(); if (_row_patch != nil) { _row_patch->unref(); } _row_patch = new Patch(_rows); _row_patch->ref(); if (_table != nil) { _table->unref(); } _table = new Overlay( new VCenter(_column_patch, 0.0), new VCenter(_row_patch, 0.0), _cells ); _table->ref(); long r, c; for (r = 0; r < rows; ++r) { for (c = 0; c < columns; ++c) { Item* item = _tabular->cell(r, c); Glyph* g; if (item != nil) { g = item->view(this, _viewer); switch (_tabular->column_alignment(c)) { case ColumnAlignLeft: g = new HCenter( new HMargin(g, CELL_MARGIN, 0, 0, CELL_MARGIN, fil, 0), 0.0 ); break; case ColumnAlignCenter: g = new HCenter( new HMargin(g, CELL_MARGIN, fil, 0, CELL_MARGIN, fil, 0), 0.5 ); break; case ColumnAlignRight: g = new HCenter( new HMargin(g, CELL_MARGIN, fil, 0, CELL_MARGIN, 0, 0), 1.0 ); break; default: break; } } else { g = nil; } _cells->insert(r * columns + c, g); } } const Color* fg = World::current()->foreground(); for (c = 0; c < columns; ++c) { if (_tabular->column_separator(c) == ColumnSeparatorSingle) { _columns->append(new VRule(fg, 1)); } else { _columns->append(nil); } Group* group = new Group(_cells, Dimension_X); for (r = 0; r < rows; ++r) { group->map(r * columns + c); } _columns->append(new Target(group, TargetCharacterHit)); } if (_tabular->column_separator(c) == ColumnSeparatorSingle) { _columns->append(new VRule(fg, 1)); } else { _columns->append(nil); } for (r = 0; r < rows; ++r) { if (_tabular->row_separator(r) == RowSeparatorSingle) { _rows->append(new HRule(fg, 1)); } else { _rows->append(nil); } Group* group = new Group(_cells, Dimension_Y); for (c = 0; c < columns; ++c) { group->map(r * columns + c); } _rows->append(group); } if (_tabular->row_separator(r) == RowSeparatorSingle) { _rows->append(new HRule(fg, 1)); } else { _rows->append(nil); } _patch->body(_table); mark_selection(); } void TabularView::cell_replaced (long, long) { rebuild(); } void TabularView::cell_changed (long r, long c) { long columns = _tabular->column_count(); _cells->change(r * columns + c); _rows->change(r * 2 + 1); _columns->change(c * 2 + 1); _table->change(0); _table->change(1); _table->change(2); _patch->reallocate(); mark_selection(); } void TabularView::row_inserted (long) { rebuild(); } void TabularView::row_removed (long) { rebuild(); } void TabularView::column_inserted (long) { rebuild(); } void TabularView::column_removed (long) { rebuild(); } void TabularView::row_separator_changed (long) { rebuild(); } void TabularView::column_separator_changed (long) { rebuild(); } void TabularView::activate (boolean active) { if (_active != active) { _active = active; if (_active) { World* w = World::current(); w->flush(); _viewer->menubar(w->property_value(DEFAULT_TABULAR_MENUBAR)); _viewer->keymap(w->property_value(DEFAULT_TABULAR_KEYMAP)); w->flush(); } mark_selection(); } } boolean TabularView::command (const char* command) { if (strcmp(command, "new row") == 0) { _tabular->insert_row(_row_dot, "<Cell>"); dot(_row_dot, 0); mark(_row_dot + 1, _tabular->column_count()); return true; } else if (strcmp(command, "new left column") == 0) { _tabular->insert_column(_column_dot, "<Cell>", ColumnAlignLeft); dot(0, _column_dot); mark(_tabular->row_count(), _column_dot + 1); return true; } else if (strcmp(command, "new center column") == 0) { _tabular->insert_column(_column_dot, "<Cell>", ColumnAlignCenter); dot(0, _column_dot); mark(_tabular->row_count(), _column_dot + 1); return true; } else if (strcmp(command, "new right column") == 0) { _tabular->insert_column(_column_dot, "<Cell>", ColumnAlignRight); dot(0, _column_dot); mark(_tabular->row_count(), _column_dot + 1); return true; } else if (strcmp(command, "hide column separator") == 0) { _tabular->change_column_separator(_column_dot, ColumnSeparatorOff); return true; } else if (strcmp(command, "show column separator") == 0) { _tabular->change_column_separator(_column_dot, ColumnSeparatorSingle); return true; } else if (strcmp(command, "hide row separator") == 0) { _tabular->change_row_separator(_row_dot, RowSeparatorOff); return true; } else if (strcmp(command, "show row separator") == 0) { _tabular->change_row_separator(_row_dot, RowSeparatorSingle); return true; } else if (strncmp(command, "go", 2) == 0) { const char* keyword = command + 3; if (strcmp(keyword, "forward_row") == 0) { dot(_row_dot+1, _column_dot); } else if (strcmp(keyword, "forward_column") == 0) { dot(_row_dot, _column_dot+1); } else if (strcmp(keyword, "backward_row") == 0) { dot(_row_dot-1, _column_dot); } else if (strcmp(keyword, "backward_column") == 0) { dot(_row_dot, _column_dot-1); } mark_selection(); return false; } else { return ItemView::command(command); } } long TabularView::row_hit (Coord x, Coord y) { Hit hit(x, y); _row_patch->repick(0, hit); if (hit.any()) { GlyphIndex result = hit.index(0); if (hit.depth() > 0) { result += hit.index(1); } return result/2; } else { return -1; } } long TabularView::column_hit (Coord x, Coord y) { Hit hit(x, y); _column_patch->repick(0, hit); if (hit.any()) { GlyphIndex result = hit.index(0); if (hit.depth() > 0) { result += hit.index(1); } return result/2; } else { return -1; } } void TabularView::keystroke (Event&) { ; } void TabularView::select (Event& e) { if (!e.shift_is_down()) { dot( row_hit(e.pointer_x(), e.pointer_y()), column_hit(e.pointer_x(), e.pointer_y()) ); } do { if (!e.pending()) { mark( row_hit(e.pointer_x(), e.pointer_y()), column_hit(e.pointer_x(), e.pointer_y()) ); update(); } e.read(); } while (e.type() != Event::up); }