Source: ./associationwidget.h


Annotated List
Files
Globals
Hierarchy
Index
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef ASSOCIATIONWIDGET_H
#define ASSOCIATIONWIDGET_H

#include "umlview.h"
#include "associationwidgetdata.h"
#include "umlnamespace.h"

class FloatingText;
class IDChangeLog;
class QBitmap;
class QPixmap;
class QDataStream;

/**
 * This class represents an association
 * inside a diagram. It is the equivalent
 * to the original Association class
 * plus support for non straight lines
 *
 * @author Gustavo Madrigal
 */
class AssociationWidget : public QObject, public Uml {
	Q_OBJECT
public:
	/**
	*   enumeration used for stating where a line is on a widget.
	*/
	enum Region{ Error = 0, West , North, East, South, NorthWest, NorthEast, SouthEast, SouthWest, Center };

	/**
	* Constructor
	*/
	AssociationWidget(QWidget *parent, AssociationWidgetData * pData);

	/**
	* Constructor
	*/
	AssociationWidget(QWidget *parent);

	/**
	* Constructor
	*/
	AssociationWidget(QWidget *parent, UMLWidget* WidgetA, Association_Type Type, UMLWidget* WidgetB);

	/**
	* Deconstructor
	*/
	virtual ~AssociationWidget();

	/**
	* Overrides = operator
	*/
	AssociationWidget& operator=(AssociationWidget & Other);

	/**
	*   Overrides == operator
	*/
	bool operator==(AssociationWidget & Other);

	/**
	* Overrides != operator
	*/
	bool operator!=(AssociationWidget & Other);

	/**
	*  Write property of FloatingText* m_pMultiA.
	*/
	virtual bool setMultiA( FloatingText* pMultiA);

	/**

	*   activates an associationwidget after a serialize function
	*/
	bool Activate();

	/**
	* Read property of FloatingText* m_pMultiA.
	*/
	virtual  FloatingText* getMultiAWidget();

	/**
	 * Returns the m_pMultiA's text.
	 */
	virtual  QString getMultiA();

	/**
	* Write property of FloatingText* m_pMultiB.
	*/
	virtual bool setMultiB( FloatingText* pMultiB);

	/**
	* Read property of FloatingText* m_pMultiB.
	*/
	virtual  FloatingText* getMultiBWidget();

	/**
	* Returns the m_pMultiB's text.
	*/
	virtual  QString getMultiB();

	/**
	*  Write property of CFloatingText* m_pRole.
	*/
	virtual bool setRole( FloatingText* pRole);

	/**
	* Read property of CFloatingText* m_pRole.
	*/
	virtual  FloatingText* getRoleWidget();

	/**
	* Returns the m_pRole's text.
	*/
	virtual  QString getRole();

	/**
	* Sets the text to the FloatingText representing the Multiplicity at the ending side
	* of the association
	*/
	bool setMultiB(QString strMultiB);


	/**
	* Sets the text to the FloatingText representing the Multiplicity at the starting side
	* of the association
	*/
	bool setMultiA(QString strMultiA);

	/**
	 * Sets the text to the FloatingText that display the Role text of this association
	 * For this funtion to work properly, the associated widgets (m_pWidgetA and m_pWidgetB)
	 * should be already set
	 */
	bool setRole(QString strRole);

	/**
	 * Read property of UMLWidget* m_pWidgetA.
	 */
	virtual UMLWidget* getWidgetA();

	/**
	 * Set the associated widgets.
	 */
	virtual bool setWidgets( UMLWidget* WidgetA, Association_Type AssocType, UMLWidget* WidgetB);

	/**
	 * Read property of UMLWidget* m_pWidgetB.
	 */
	virtual UMLWidget* getWidgetB();

	/**
	 * Synchronizes the Widget's m_pData member with its display properties, for example:
	 * the X and Y positions of the widget, etc
	 */
	void SynchronizeData();

	/**
	 * Returns true if this association associates WidgetA to WidgetB, otherwise it returns
	 *false
	 */
	bool checkAssoc(UMLWidget * WidgetA, UMLWidget *WidgetB);

	/**
	 * CleansUp all the association's data in the related widgets
	 */
	void cleanup();

	/**
	 * Returns true if the Widget is either at the starting or ending side of the association
	 */
	bool contains(UMLWidget* Widget);

	/**
	 * Returns the Association's Type
	 */
	Association_Type getAssocType();

	/**
	 * Sets the association's type
	 */
	void setAssocType(Association_Type Type);

	/**
	 * Returns a QString Object representing this AssociationWidget
	 */
	QString toString();

	/**
	 * Read property of bool m_bActivated.
	 */
	const bool IsActivated();

	/**
	 * Set the m_bActivated flag of a widget but does not perform the Activate method
	 */
	void SetActivated(bool Active /*=true*/);

	/**
	 *  Save/load the widget
	 */
	bool serialize(QDataStream *s, bool archive );

	/**
	 *Returns the amount of bytes needed to serialize this object
	 */
	long getClipSizeOf();

	/**
	 *	Sets the state of whether the widget is selected.
	 *
	 *	@param _select The state of whether the widget is selected.
	 */
	void setSelected(bool _select);

	/**
	 *	Returns the state of whether the widget is selected.
	 *
	 *	@return Returns the state of whether the widget is selected.
	 */
	bool getSelected() {
		return m_bSelected;
	}

	/**
	 * Return the widget data instance.
	 */
	AssociationWidgetData* getData();

	/**
	 * Adjusts the endding point of the association that connects to Widget
	 */
	void WidgetMoved(UMLWidget* Widget, int x, int y);

	/**
	 * calculates the m_unRoleLineSegment value according to the new RoleText topleft
	 *  corner PT.
	 * It iterates through all LinePath's segments for each one it calculates the sum of
	 * PT's distance to the start point + PT's distance to the end point. The segment with
	 * the smallest sum will be the RoleTextSegment (if this segment moves then the
	 * RoleText will move with it). It sets m_unRoleLineSegment to the start point of the
	 * chosen segment
	 */
	void calculateRoleTextSegment();

	/**
	 * Overrides standard event method
	 */
	void mouseDoubleClickEvent(QMouseEvent * me);

	/**
	 *  Overrides standard event method
	 */
	void mousePressEvent(QMouseEvent * me);

	/**
	 *  Overrides standard event method
	 */
	void mouseReleaseEvent(QMouseEvent * me);

	/**
	 *  Overrides standard event method
	 */
	void mouseMoveEvent(QMouseEvent * me);


	/**
	 *   Returns true if the given point is ob the Association.
	 */
	bool onAssociation(const QPoint & point);

	/**
	 *  	Returns the associations documentation.
	 */
	QString getDoc() {
		return m_pData -> getDoc();
	}

	/**
	 *	Sets the associations documentation.
	 */
	void setDoc( QString doc) {
		m_pData -> setDoc( doc );
	}

	/**
	* 	Moves all the mid points (all expcept start /end ) by the given amount
	*/
	void moveMidPointsBy( int x, int y );

	/**
	* 	Moves the entire association by the given offset.
	*/
	void moveEntireAssoc( int x, int y );

	/**
	 *     Sets the new font for the text widgets used.  Called by the text widgets
	 *    when the menu was selected on one of them.
	 */
	void changeFont( Uml::Text_Role callingRole, QFont font );


private:
	/**
	 * Finds out in which region contains the Point (PosX, PosY) and returns the region
	 * number
	 */
	AssociationWidget::Region findPointRegion(QRect Rect, int PosX, int PosY);

	/**
	 *  Overrides moveEvent
	 */
	void moveEvent(QMoveEvent *me);

	/**
	 * This function calculates which role should be set for the m_pRole FloatingText
	 */
	Text_Role CalculateRoleType();

	/**
	 * Calculates and sets the first and last point in the Association's LinePath
	 * Each point is a middle point of its respecting UMLWidget's Bounding rectangle
	 * This method picks which sides to use for the association
	 */
	void calculateEndingPoints();

	/**
	 * Returns true if point (PosX, PosY) is close enough to any of association's segments
	 */
	bool IsPointInsideBoundaries(int PosX, int PosY, QPoint & SPoint,
				     uint & StartSegmentIndex, uint & EndSegmentIndex);

	/**
	 * Returns the intersection point between line P1P2 and the bounding rectangle of pWidget
	 */
	QPoint FindRectIntersectionPoint(UMLWidget* pWidget, QPoint P1, QPoint P2);

	/**
	 * Returns the intersection point between lines P1P2 and P3P4
	 */
	QPoint FindIntersection(QPoint P1, QPoint P2, QPoint P3, QPoint P4);

	/**
	 * Returns the total lenght of the assocition's LinePath:
	 * result = segment_1_lenght + segment_2_lenght + ..... + segment_n_lenght
	 */
	float TotalLenght();

	/**
	 * Calculates which point of segment P1P2 has a distance equal to Distance from P1,
	 * Lets say such point is PX,  the distance from P1 to PX must be equal to Distance
	 * and if PX is not a point of the segment P1P2 then the function returns (-1,-1)
	 */
	QPoint CalculatePointAtDistance(QPoint P1, QPoint P2, float Distance);

	/**
	 * Calculates which point of a perpendicular line to segment P1P2 that contains P2
	 * has a distance equal to Distance from P2,
	 * Lets say such point is PX,  the distance from P2 to PX must be equal to Distance
	 */
	QPoint CalculatePointAtDistanceOnPerpendicular(QPoint P1, QPoint P2, float Distance);

	/**
	 * Calculates the intersection between line P1P2 and a perpendicular line containing
	 * P3, the result is returned in ResultingPoint. and result value represents the distance
	 * between ResultingPoint and P3; if this value is negative an error ocurred.
	 */
	float PerpendicularProjection(QPoint P1, QPoint P2, QPoint P3, QPoint ResultingPoint);

	/**
	 * Calculates the position of the text widget depending on the role
	 * that widget is under-taking.  Returns the point at which to put the widget.
	 */
	QPoint calculateTextPosition(Text_Role role);

	/**
	 * Puts the text widget with the given role at the given position.
	 * This method is usually called after calling @ref calculateTextPostion
	 * to get the needed postion.  It is a seperate function incase there is a need
	 * to place the text without calculation.  i.e.  The line segment it is on has moved
	 * and it should move the same amount as the line.
	 */
	void setTextPosition(Text_Role role, QPoint pos);

	/**
	 * Shows the select operation dialog.
	 */
	void showOpDlg();

	/**
	 * Returns the Region the widget to line intersection is for the given widget
	 * in this Association.  If the given widget is not in the Association then
	 * Region::Error is returned.
	 * Used by @ref calculateEndingPoints to work these positions out for another
	 * Association, Since the number of Associations on the same region for the
	 * same widget will mean the lines will need to be spread out across the region.
	 */
	Region getWidgetRegion(AssociationWidget * widget);

	/**
	 * This is a pointer to the Floating Text widget at the ending side of the association.
	 * This FloatingText displays the information regarding multiplicity
	 */
	FloatingText* m_pMultiB;

	/**
	 * This is a pointer to the Floating Text widget at the starting side of the association.
	 * This FloatingText displays the information regarding multiplicity
	 */
	FloatingText* m_pMultiA;

	/**
	 * This member holds a pointer to the floating text that displays the role of this
	 * association
	 */
	FloatingText* m_pRole;

	/**
	 * This member holds a pointer to the UMLWidget at the starting side of the association
	 */
	UMLWidget* m_pWidgetA;

	/**
	 * WidgetA's Old TopLeft Corner before moving
	 */
	QPoint m_OldCornerA;

	/**
	 * Old WidgetA's TopLeft Region according to WidgetB's bounding rectangle
	 */
	int m_nCornerARegion;

	/**
	 * Old WidgetA's TopLeft Region according to WidgetB's bounding rectangle
	 */
	int m_nCornerBRegion;

	/**
	 * WidgetB's Old TopLeft Corner before moving
	 */
	QPoint m_OldCornerB;

	/**
	 * This member holds a pointer to the UMLWidget at the ending side of the association
	 */
	UMLWidget* m_pWidgetB;

	/**
	 * Returns the region the line is on for widgetA.
	 */
	Region getWidgetARegion() {
		return m_WidgetARegion;
	}

	/**
	 * Returns the region the line is on for widgetB.
	 */
	Region getWidgetBRegion() {
		return m_WidgetBRegion;
	}

	/**
	 * Called to tell the association that another association has added
	 * a line to the region of one of its' widgets. true - widgetA
	 * false - widgetB.
	 *
	 * Called by @ref updateAssociations which is called by
	 * @ref calculateEndingPoints when required.
	 */
	void updateRegionLineCount(int index, int totalCount, AssociationWidget::Region region , bool widgetA);

protected:

	/**
	 * Tells all the other view associations the new count for the
	 * given widget on a certain region. And also what index they should be.
	 */
	void updateAssociations(int totalCount, Region region, bool widgetA);

	/**
	 * Returns the number of lines there are on the given region for
	 * either widget a or b of the association.  Setting the boolean value
	 * to true will give a count for widgetA and false for widgetB.
	 */
	int getRegionCount(Region region, bool widgetA);

private:
	/**
	 *  Checks to see if the given point is one of the points of the line.
	 *  If so will try and get the view to flag the point for moving.
	 *  This is only valid if no other point id being moved and only
	 *  while the left mouse button is down.
	 */
	void checkPoints(QPoint p);

	/*QPixmap * m_pPix;
	QBitmap *m_pMask;*/

	UMLView * m_pView;
	AssociationWidgetData *m_pData;
	Region m_WidgetARegion, m_WidgetBRegion;

	/**
	 * It is true if the Activate Function has been called for this
	 * class instance
	 */
	bool m_bActivated;

	/**
	 * When the association has a Role Floating Text this text should move when the
	 * LinePath moves but only if the closest segment to the role text moves.
	 * this segment is m_LinePath[m_unRoleLineSegment] -- m_LinePath[m_unRoleLineSegment + 1]
	 */
	uint m_unRoleLineSegment;
	bool m_bFocus;
	bool m_bSelected;
	ListPopupMenu * m_pMenu;
	int m_nMovingPoint;

public slots:
	/**
	 * Handles the selection from the popup menu.
	 */
	void slotMenuSelection(int sel);

	/**
	 * This slot is entered when an event has occurred on the views display,
	 * most likely a mouse event.  Before it sends out that mouse event all
	 * children should make sure that they don't have a menu active or there
	 * could be more than one popup menu displayed.
	 */
	virtual void slotRemovePopupMenu();

	/**
	 * Handles any signals that tells everyone not to be selected.
	 */
	void slotClearAllSelected();
};
#endif

Generated by: jr on radge on Wed Sep 25 00:11:47 2002, using kdoc 2.0a54.