-*- Dictionary: igor -*- Architecture: database:data-object:viewer:pane dataset database-mark controller Database: Represents the state of/interface to the underlying database. Not clear that there's going to be more than one, but there might be. Ensures consistency of multiple data-objects/viewers on the same object by callbacks, concept of current "owner", etc. [Not talking about version control here, though that would be mediated by the Database object too.] Dataset: Represents how we've chosen to view a particular portion of the database, by a search, walking dependencies or code hierarchy, etc. Can explore alternate paths by cloning the dataset or transferring control to a new class of dataset. Database-mark: There needs to be a "database marker" object which remembers locations in the dataset for backtracking history, etc., but which allows viewers to query on a relevant level of detail, e.g. what module, what statement, etc. This allows the controller to coordinate browsing across multiple data-object/viewer setups. Controller: The controller holds the state of a particular instance of the Igor interface. This includes top-level menus and controls, user preference settings, and other state of the interaction that is shared between the other objects. The controller will mediate the creation of new datasets and viewers, and various other random communications been the viewer/database objects. Note that viewers and panes (and maybe DB objects) will also directly communicate with the user w.r.t. their particular concerns (pane scrollbars, etc.) The controller will provide convenient ways to simultaneously create and destroy datasets, viewers and panes in the common case where there is a 1-1 relationship. Data-object: Graph-object buffer (text, ~= hemlock buffer) Control Choice Scalar-Choice Range-Choice Collection-Choice Action (Data object for buttons/commands)? A DATA-OBJECT represents some set of object semantics that we want to view and edit. The data-object <-> viewer protocol probably doesn't have any standard messages, since this communication is based on the object semantics. The database <-> data-object protocol may contain interesting messages for saving and consistency maintenance. A CONTROL is the data-object used to back some simple state value of the user interface which needs to be viewed and altered by the user. Controls can be mapped onto any style of control-viewer (menu, slider, etc.) that seems appropriate. Persistent controls have much the same function as the X resource database. Viewer: Graph-viewer Call-graph-viewer Class-heterarchy-viewer, ... Text-viewer (~= hemlock window, but can be nested) Code-viewer Document-viewer Control-Panel (groups controls and other viewers) Control-viewer: Menu Scrollbar Slider, ... A VIEWER represents some information in a way that directly supports display (via a pane) and efficiently supports semantically meaningful modifications. The state of many viewers is persistent (to support saving the configuration of the user interface.) The viewer itself is not a persistent object per-se, but on demand it will produce a persistent object that retains the interesting state. pane: A pane is a chunk of screen real-estate used to display/alter the state of a viewer. A pane can be nested within another pane (i.e. in a sub-window) to represent a viewer's reference to another viewer. [### The nature of the view <-> pane protocol is a subject of debate. There is agreement that the pane protocol: -- should fairly directly reflect the the drawing operations, widgets and event stream of the underlying window system, and that it -- need not reveal all the capabilities of the underlying window system. We will choose some set of operations from the underlying system which are primitive or are needed to preserve look-and-feel. Programmers that want to use specific capabilities of specific systems can use the foreign interface directly. However, for toolkit operations that are not in the lowest-common-denominator, it is not totally clear whether the Pane or some predefined Viewer is responsible for implementing the functionality. It is also unclear whether the Pane object is really visible to users of the toolkit. It might be an internal object which exists only to map toolkit operations onto implementation-specific primitives. Two design constraints that we would like to satisfy: -- A given "application" (viewer?) should be able to display on different display implementations simultaneously (e.g. over a net connection.) -- We would like to avoid arbitrary distinctions between "primitive" pane operations and potentially-user-implemented viewer operations. The "arbitrary distinction" argument seems to favor hiding the pane layer, but basic drawing operations may be "obviously different". One distinction is that users of the Pane protocol must handle display backing/refresh themselves, whereas even standard "primitive" viewers (menus, etc.) would do redisplay themselves. Misc issues: -- Can a viewer have more than one pane? If so, presumably potentially on different devices. But this would mean that the pane protocol must be totally device-independent, and thus all unimplemented "primitives" must be emulated on the pane side of the protocol. Note that those panes might have different layouts, since the widgets may be different sizes, etc. -- What pane classes are there, and is it meaningful for TK users to subclass them? -- What exactly is "the toolkit"? It seems that the consensus is that it is the core layer, not including complex viwers and data-objects. What do we call the extra stuff? ] Display-list: We will probably want to have a general display-list-viewer which allows the object semantics to specify its display as a collection of graphical objects (lines, strings, etc.) on an infinite drawing area, rather than as drawing operations on a finite pane. In addition to handing scrolling/zooming, we also want to support overlaying via object depth & transparancy. Graph viewers will probably be built on this display-list engine. Graphoids: Graphs are composed of Nodes and Arcs. The Graph-viewer itself is specializable for different kinds of graphs: directed or undirected, acyclic or potentially cyclic. (connected or potentially not? Lattice?) Both manual and automatic layout are supported. Both nodes and arcs can be subclassed to provide internal structure. Both both can contain embedded viewers or controls. Nodes can be moved and resized. Arcs can be stretched into splines or poly-lines. Nodes can have different shapes, and may or may not have a visible outline and background color. We want to support a variety of line styles for arcs, but also need some abstraction on this, since if a pane system doesn't implement e.g. "wide dashed poly-splines", then we probably want to use some other style rather than do it ourselves. Graphs can have multiple active selections displayed using various highlighting styles. The graph data object will provide semantically useful library routines such as finding a collection of all children of a tree node or testing whether two nodes are connected. Textoids: A BUFFER is a text-data-object. It represents a stand-alone chunk of program an actual user-level buffer, a cut buffer, etc. Not all buffers are necessarily intended for display or backed up to the database. A buffer has three parallel levels of structure, each represented as sorted vectors in a buffer-gap representation: 1] Text: the text representation of the stuff being edited. This is pretty much as in a text editor, but automatic indentation and line breaks might not have any corresponding characters. 2] TOKENs & MARKs. Marks are either fixed or moving (moved after insertions.) Line-breaks (automatic or explicit) are represented by moving newline marks. A token is a subtype of fixed mark. Marks just have a position in the text sequence, whereas tokens have a position and count. Tokens do not overlap, so each text position corresponds to at most one token (but tokens can have marks inside them.) This implies that a token always has >= 1 characters. 3] REGIONs of text in a buffer with some semantic affinity: the definition of a single method, a leaf in a document outline hierarchy. Regions are also disjoint. Each region has a prefix token which contains some non-empty but arbitrarily region-specific text such as "section foo" or perhaps ^L. The purpose of the prefix is to allow text character positions to be unambiguously assigned to a region, and to provide a textual way to describe deleting a region seperator (hence merging with the previous region.) Note that the requirement that tokens and regions have some text in them doesn't mean that that text must usually be displayed verbatim. For example, the text associated with an embedded graph could be the caption. Marks, tokens and regions are specializable objects with methods that can exert control over redisplay and handling of mouse-clicks & key-events. For example, tokens and regions can be read-only, and tokens can be displayed in a particular font or color. Also, clicking on a token can cause a particular action such as jumping to the definition of a variable. Textoid modification: Text: Basic editing operations are described in terms of textual insertions and deletions, as in a text editor. The undo history is maintained as these textual modifications. A buffer, string or character may be inserted at a mark. The text between two marks may be deleted, or new buffer can be created by cutting or copying the text. Tokens: When all the text for a token is deleted, cut or copied, that token is deleted, cut or copied. If the text within a token is modified via an insertion or deletion, or a partial token is copied due to a cut or copy, then, CHANGE tokens are created as needed. A CHANGE token holds the changed text and the tokens that previously came before and after the changed subsequence (possibly the same, possibly NIL.) These old adjacent tokens are no longer part of the token sequence, but the tokenizer can examine them to preserve any semantic annotations. An exisiting CHANGE token is extended to include contiguous string or character insertions. Buffer insertions insert the tokens associated with that buffer. Conversion of CHANGE tokens into into actual language syntax tokens is done on demand by a tokenizer associated with the REGION. The region has an automatically updated list of change tokens that need to be tokenized. Redisplay is one form of demand for tokenization, since token type affects display. For efficient implementation of keystroke insertion while supporting completion, etc., an ACTIVE token (of class determined by the region) is created at the gap whenver the gap is moved (after the modification that caused it to be moved.) When the ACTIVE token is created, it can extend itself to include adjacent text. The ACTIVE token is extended & contracted to include subsequent character insertions and deletions, but becomes an ordinary CHANGE token if a buffer is inserted or the gap moves. Each buffer has one ACTIVE token. Because of the semantics of ACTIVE, there is a SET-ACTIVE operation which can move the ACTIVE token without actually doing modification (to make it track the cursor.) REGIONS: REGIONs provide the semantic context for editing. They contain state analogous to EMACS modes (i.e. is this code or documentation.) REGIONS also contain modification information: the CHANGE tokens and a generic function called whenever the region is modified (the default method increments a counter.) Regions control how text is is tokenized (and hence how it is displayed.) Regions also exert influence over command processing by providing local menus and keystroke interpretation. Regions may incorporate arbitrary hierarchical and graph-structured references to other regions and data structures, but the region is responsible for maintaining the consistency of these annorations (by using the modification information.) Misc questions: