From lechner@cs.uml.edu Tue Sep 20 02:30:28 2005
Subject: Thoughts on a bde browser project, and the Fox gui
To: 05f523
Subject: Thoughts on a bde browser project
RJLRef: $PH/COOL-BDE/bdeBrowserAlternatives.htm
[.txt]
[There
are no other hyperlinks below -- RJL]
I. Introduction
II. Diagram browsing alternatives
1. Fix bde2java
2. Use bde(Linux/Unix)
3. Upgrade bde2ht
4. Enhance bde
5. Port bde to FOX API
III. BDE's
display code organizaion
updatedisplaylist()
ReDraw()
GUI-hiding functions
IV. A sample of FOX code
I. Introduction:
----------------
Bde is so large that refactoring
might be
easier if we extract a
display-only capability.
That's consistent with my
goal of removing
pr_init functionaliity from chgen
and separating the input
editing from the output
rendering side of bde's GUI.
Fox is a PI GUI (PIM not PSM
in UML terms).
I invite you if you have
OpenGL experience to
try porting a
display-output-only subset of bde
to Fox as a 05f523 project.
This involves he
contracting the bde user inerface and rendering
bde diagram content, currently done in bde/src/
files display.cc
and draw.cc.
You might first try out the
game of Set at setgame.com.
This shows that a nice
addition to bde would be
a 2Dim OpenGL colored shape
capability.
(Bde
bendpt objects already reserve a byte for
color in the HP attribute
string hsegpattern.)
R Almonte
did a nice project in 04f522 on communication
protocols for the distributed
multi-client setGame.
[RJLRef:
$PH/04f522/04fdsg_raReportR1.{doc,htm}.]
(I added a few footnotes to
his original 04fdsg_raReport.doc.)
At the end I append a sample
of FOX code from a question
to the FOX User Group and
reply from FOX 'guru' Jerouen:
It is enclosed for inspection by those who might
want to consider a bde2FOX
project.
Before that, let's consider
other bde browser
alternatives that are much
further along.
===============================
II. Diagram browsing
alternatives:
1. One way to browse bde diagrams is using bde2java.
This requires removing
current bugs and enabling it
to display any diagram in a
multi-diagram file.
Right now it is limited to
one diagram per file.
bde2java is much farther
along than other alternatives
to bdeUnix,
and could possibly replace it entirely.
------------------------------
2. Another way is to upgrade
bde2ht*; this project has
multiple versions and
converts a bde.dat file to a set
of file pairs <HG#.htm,HG#.gif>, one pair per diagram.
This has the advantage that
it already creates hyperlinks
from diagram nodes to other
diagrams, or to text files
which follow a consistent
labeling standard.
Bd2htm expands multiple
hotspots in a node to either
another diagram or to a text-file#anchor point.
There is a (big but
primitive) demo of this at
$PH/COOL-LCP/JP2html.
----------------------------------------
3. Another way is to use bde (bdeUnix) whose GraphSelect
OOMenu option gives random access to any diagram after
displaying the HG table of
titles. However bde is buggy
and crashes frequently and
does not render a diagram
properly. [Focusing on a
display-only subset of bde
might fix display-side bugs
and help to get rid of
the pr_init
process which is built into fileio.cc
and pr_util/pr_load.c
but deprecated.]
--------------------------------
4. Another way is to enhance
the display-side of bde:
Here is a suggested refactoring process:
(a) Declare that a particular
subdiagram is the
optional expansion of one
node (or more than one).
(b) Enable browsing down and
back up in a LIFO
stack of sub-diagrams and/or
text files like bde2htm.
(c) A placeholder already
exists in 94subdeschema.sch
for node to diagram
expansion: an unused FSid field.
Replace FSid
by HGid2 with is_key = 1 in table HN.
(d) Implement Node-Expand as
Graph-Select
Graph Select currently
responds to a click anywhere
in the canvas widget by
displaying the HG-table
and promping
the user to select a row. It should
be easy to make a mouse click
inside a node use
the HGid2 field of this HN
instead for Graph Selection.
A new user-callable InsertLink method is required.
Irs callback should follow the usual *ops.cc
state model user interface
protocol. After
InsertLink works for Nodes, Caption and Link
should also be enhanced with
this method.
But where to put the 'InsertLink' selection box?
The generic approach would be
to make InsertLink
a Text class method or more generally, emulate
MSword's Insert/Edit/Open/Delete Hyperlink actions.
The challenge is to open a
html browser from inside bde
rather than off-line convert
a bde.dat file to html
as in bde2htm.
------------------------------------------
(5) Another way is to convert
part of bde to the FOX API.
This is valuable only if it
begins an effort to convert
ALL of bde
to FOX.
I hesitate to do this because
I am more interested
in applying the COOL
Framework to its own components
and to other applicaionsa than to learning another GUI.
==========================================
III. BDE's display code organizaion:
What would it take to extract a browser
from bdeUnix
and possibly port it to FOX?
A survey of bde code organization shows that function
updatedisplaylist in fileio.cc converts one
diagram
(one HG-row + components) to
equivalent display list content.
It constructs a polymorphic
list of node hlink and caption
objects without drawing this
content to the canvas window.
Function ReDraw
displays the diagram, by calling <subclass>::Draw
for each object in the list.
::Draw calls GUI-hiding functions
drawtext, draw<shape>, drawline. Currently these are implemented
in bde/src/draw.cc
and they hide calls to the X11 API.
DO NOT UNDER-ESTIMATE THIS
PROJECT:
One major complication is
setting up bde's menus
and converting their X11
callbacks in bde/src/init.cc
from X11 to the FOX API.
[over 1400 refs counted at
$RBGB/src/findX11refs.csh;
setenv RBGB
~lechner/bde2alpha_rl/sandbox/bdeNT050526/bdegen13/bde]
Another complication is
loading a bde.dat file of diagrams
via FILE/OPEN via fileio.cc calls to pr_load.
Retaining the top-line FILE
menu is desirable,
so its conversion options can
be added to the browser.
The left menu Graph Select
command is needed for diagram selection.
One possible option is to add
it (and remove EDIT) on the top menu.
All other left-OO-menu
commands can be disabled for browsing.
To avoid double maintenance,
these would be conditionally
compiled out of bde/src if X11 were the only GUI.
Here is sample code from bde/src:
------------------------------------
void
updatedisplaylist(struct HG
*cHG) /*
updates HGcurr - RJL*/
/*
moved from bdeReplay to fileio.cc
* because DisplayGraph
below calls it regardless of BDELOG flag
* Updatedisplaylist
regenerates the graph object list
* of new HN/outgoing-HL/CG struct ptrs
* after a database update or HG-row selection;
* This list supplies input data for ReDraw.
* The caller is responsible for updating cHG - RJL 020427
* The client also must call ReDraw - RJL 031013
*/
//Pre-condition:
Client must do clearObjects() first.
{EP;
node *lastnode;
hlink *lastlink;
caption *lastcaption;
// last caption Added by 94FBDE
HGcurr = cHG ;// 020427
(void) new graph(HGcurr);
child_loop(HG,HN,HNid,HGid) // depends on HGcurr!
{
//create node and link ptrs on display list
lastnode =
new node(HNcurr);
child_loop(HN,HL,HLid1,HNid1)
//pre-cond:
source of link must be in this HN
{
lastlink
= new hlink(HLcurr);
}
}
child_loop(HG,CG,CGid,HGid)
// Added by 94FBDE
{
//create Caption ptrs on display list
lastcaption =
new caption(CGcurr);
#if
0
//
Added by 96f523 BDECODE Group for XB text class- N/A now - RJL050909
//
I'm not so sure - check again - RJL050919
child_loop(CG,
GX, GXid, CGid) {
if (GXcurr
!= NULL) (void) new captiontext(GXcurr);
}
#endif
}
DP;topobject->Ggroup::doDump();
LP;} // end updatedisplaylist
----------------------------------------------
'grep
ReDraw *.cc|wc' says that ReDraw()
in display.cc
is referenced from about 100
places in bde/src/*.cc.
During list traversal the
generic draw method is over-ridden
based on an object's subclass
(node, hlink or caption).
All the object's properties
are accessible from HN, CG or HL
but the object has only an fkey but not a pointer as a
result of
[over-]encapsulation (too much info-hiding:-)
This enhancement really needs
modeling in bde.sch:
Add tables ListNode LN, ListLink LL and ListCaption LC
with 1:1 or 1:0 associations
from HN, HL and CG
respectively, and remove the
hand-written code that
manages the List graphobjectlist.
BDE's data model would show a 1..1 HN-parent
to optional 0..1 singleton
LN-child associaton
and similar associations from
CG to LC and HL to LL.
Only the diagram selected for
display would have
this LH, LL or LC singleton chld.
Another (OOP) way is to
create a LH subclass of HN,
(and LL for HL and LC for
CG. These subclasses
would automatically get the
0..1 multiplicity.
LN, LL and LC can inherit
database update methods
from HN, HL and CG resp. It might be easier
to ensure that no other
diagram is updated from
the local canvas edit
operations.
In either case, whenever an
LN, LL or LC object
is created by Graph Select
via updatedisplaylist,
or by local edits, pr_add or its gencpcp constructor
automatically generates an HNid_pp parent pointer
in LN from its HNid fkey, and similarly
for HLid_pp
in LL and CGid_pp in LC.
---------------------------
/******************************************************************
* Description:
ReDraw() in display.cc:
*
calls XClearArea and topobject->doDraw()==>subobject::Draw
* Error handling:
*
NONE.
* Side effects:
*
NONE.
**********************************************************************/
void
ReDraw()
{EP;
static int callCount = 0;
Display *display;
display = XtDisplay(toplevel);
XClearArea(display,
XtWindow(canvas), 0, 0, 0, 0, False);
DP;dprintd("\tcall %d to topobject->doDraw()\n",++callCount);
topobject->doDraw(); // ReDraw ---> topobj->doDraw ---> subobject::Draw.
LP;}
// end ReDraw
--------------------------------
Also
in display.cc:
/*******************
node::Draw: display.cc:
231-308 ****************
* Description: Draw the node shape border at
HN* cHN.
* Then draw the HA-children text lines.
* Preconditions: Requires DC in HN and HA;
* Requires valid HNrow
at HN* cHN;
* Error handling:
*
NONE.
* Side effects:
*
Alters HNcurr = cHN,
alters HAcurr. ???-RJL040717
*********************************************************************
...
and
/*********************
hlink::Draw, display.cc:409-581 ******************
These
call GUI-hiding functions drawtext,
draw<shape>, drawline
in display.cc
--------------------------------
=========================================
IV.
A sample of FOX code:
Forwarded
message:
>
From foxgui-users-admin@lists.sourceforge.net
Mon Sep 19 21:16:30 2005
>
Organization: FOX Toolkit
>
To: foxgui-users@lists.sourceforge.net, jamesravan@comcast.net
>
Subject: Re: [Foxgui-users]Silent Canvas...?
>
>
On Monday 19 September 2005 19:52, James Ravan wrote:
>
> Here is a short program that creates a window, and I think should beep
>
> when the mouse is left-clicked inside it. It does nothing. Can anyone
>
> please tell me what I did wrong?
>
>
>
> grateful for *any* help,
>
> -jim
>
>
>
> =============================================
>
> #include "fx.h"
>
>
>
> // my application window
>
> class myMainWindow : public FXMainWindow
>
> {
>
> FXDECLARE( myMainWindow
)
>
>
>
> private:
>
> myMainWindow(
void ) {}
>
>
>
> protected:
>
>
>
> public:
>
> // Message enum
>
> enum
>
> {
>
> ID_QUIT = FXMainWindow::ID_LAST,
>
> ID_LBP,
>
> ID_LAST
>
> };
>
>
>
> // Constructor/Destructor
>
> myMainWindow(
FXApp *a );
>
> virtual ~myMainWindow(
void );
>
>
>
> void create( void );
>
>
>
> // Messages
>
> long onCmdQuit(
FXObject*, FXSelector,
void* );
>
> long onLeftButtonPress(
FXObject*, FXSelector,
void* );
>
> };
>
>
>
> // FOX message map
>
> FXDEFMAP( myMainWindow ) myMainWindowMap[]
=
>
> {
>
> FXMAPFUNC( SEL_LEFTBUTTONPRESS, myMainWindow::ID_LBP,
>
> myMainWindow::onLeftButtonPress ),
>
> FXMAPFUNC( SEL_CLOSE, 0,
>
> myMainWindow::onCmdQuit ),
>
> };
>
>
>
> // FOX standard object implementation
>
> FXIMPLEMENT ( myMainWindow, FXMainWindow,
myMainWindowMap,
>
> ARRAYNUMBER(myMainWindowMap) )
>
>
>
> // Create the main window.
>
> myMainWindow::myMainWindow( FXApp*
a ) : FXMainWindow( a, "mytest",
>
> NULL, NULL, DECOR_ALL )
>
> {
>
> setWidth(
300 );
>
> setHeight(
250 );
>
> }
>
>
>
> // Create and initialize
>
> void myMainWindow::create( void )
>
> {
>
> // Create the window
>
> FXMainWindow::create();
>
>
>
> // Make the main window appear
>
> show(PLACEMENT_SCREEN);
>
> }
>
>
>
> // Clean up
>
> myMainWindow::~myMainWindow( void )
>
> {
>
> }
>
>
>
> long myMainWindow::onLeftButtonPress( FXObject*, FXSelector, void* )
>
> {
>
> getApp()->beep();
>
> return 1;
>
> }
>
>
>
> // Quit
>
> long myMainWindow::onCmdQuit( FXObject*, FXSelector, void* )
>
> {
>
> getApp()->exit(0);
>
> return 1;
>
> }
>
>
>
> int main( int argc, char** argv )
>
> {
>
> // Construct and initialize the
application.
>
> FXApp
application( "mytest", "mytest" );
>
> application.init(
argc, argv );
>
>
>
> // Create the main window and the
application.
>
> new myMainWindow(
&application );
>
> application.create();
>
>
>
> // Run the application.
>
> return application.run();
>
> }
>
>
There's several things that are needed:
>
>
1) Most "container" widgets are normally not mouse-sensitive; however
after
> a call to enable() they are receiving mouse messages from the system.
>
>
2) The "raw" mouse messages are received by the widget as ID=0. Thus, map as
> follows:
>
>
FXMAPFUNC( SEL_LEFTBUTTONPRESS, 0, myMainWindow::onLeftButtonPress),
>
> The idea with those message ID's is that
they're unique for the *receiver*,
> when receiving messages from a
control. However, in this case you're
> effectively writing a "custom
control", a main window with mouse-handling.
>
>
Hope this helps,
>
>
Jeroen
>
+----------------------------------------------------------------------------+
>
| Copyright (C) 21:40 09/19/2005 Jeroen van der Zijp. All Rights Reserved. |
>
+----------------------------------------------------------------------------+