[Uml-devel] Diagram toolbar handling

Raymond Bosman bosman at hetnet.nl
Wed Apr 28 01:43:09 UTC 2004


Hi,

I have a proposal for the diagram toolbar handling. 

Please, see the attached files. And let me know what you think.

Raymond. 

-------------- next part --------------
Problem statement
=================

Selecting an action in the diagram toolbar, determines the exact mouse
behavior.

For example, if the Class button is chosen (selected), a simple
left-mouse button click on the canvas results to creating an classWidget. But
choosing an Dependency lets the mouse behave differently. Instead of creating
a widget, lines can be drawn between widgets. 

In the current version: the handling of the mouse is implemented in the
UMLView class. The slot: slotToolBarChanged keeps track of the active toolbar
state (m_CurrentCursor). Mouse events are handled by the (overloaded)
functions: contentsMouseMoveEvent, contentsMouseDoubleClickEvent,
contentsMousePressEvent, contentsMouseReleaseEvent.

In each Event function, 'if' statements determine the current state (cursor),
and act upon this. States that don't have shared data (or functionality
in common) are implemented in the same function. My opinion is that the code 
is hard to read and maintain.


State pattern
=============

The intent of the state pattern is: "Allow an object to alter its behavior
when its internal state changes. The object will appear to change its class".

The main idea is to give each toolbar state an separate class. Changing from
toolbar state, means pointing to another class. 

Pro's:

* It enhances the readability of the source code. Each toolbar button has it's
  own class. 
* Subclassing saves duplicate code. (And brings structure in the dependencies
  of each button.)
* Moves code from the UMLView implementation and function definitions from its 
  interface. This may lead to faster compilation. (Or a smaller chance to
  recompile everything.)
* Easy to add a new state. All states are handled identically in UMLView.


Con's:

* This means a lot of classes.
* Some state-classes need to access the protected and private members of the
  UMLView. 


The second problem can easily be solved by creating a full interface for
UMLView, or make the state-classes 'friend'. 
  
  
The first problem can be solved using the flyweight pattern.


Flyweight pattern
=================

The intent: "Use sharing to support large numbers of fine-grained objects
efficiently."

Some classes share so much data, that we do as if it is a independent,
separate class, but in fact a member variable keeps track of the behavior of
the class. 

A 'Factory' handles the state creation and retrieval. 

So this pattern solves the state explosion problem. At a cost that a
factory is needed. 


Implementation
==============

The slotToolBarChanged and contentsMouseMoveEvent look like this:


void UMLView::slotToolBarChanged(int c) 
{
	// Retrieves the state of the given ToolBar_Button. 
	m_pToolBarState = m_pToolBarStateFactory->getState((WorkToolBar::ToolBar_Buttons)c);

	// ...
}

void UMLView::contentsMouseMoveEvent(QMouseEvent* ome) 
{
	//  Call the mouseMove function from the selected state. 
	m_pToolBarState->mouseMove(ome);
}



The ToolBarStateFactory returns a subclass of a ToolBarState class. Classes
that have a flyweight pool are subclassed from toolbarstatepool.  (See UML
diagram)



Todo
====

Currently I am trying to get the modified source stable, fix some minor
things, let it work with the latest CVS checkout. 

To create a full interface for UMLView, that the states are 'no-friends'
anymore, is too much work for me (at the moment). 






-------------- next part --------------
A non-text attachment was scrubbed...
Name: state_diagram.png
Type: image/png
Size: 125261 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/umbrello-devel/attachments/20040428/9f7e23f7/attachment.png>


More information about the umbrello-devel mailing list