1 // The following ifdef block is the standard way of creating macros which make exporting
2 // from a DLL simpler. All files within this DLL are compiled with the TEST_EXPORTS
3 // symbol defined on the command line. this symbol should not be defined on any project
4 // that uses this DLL. This way any other project whose source files include this file see
5 // TEST_API functions as being imported from a DLL, wheras this DLL sees symbols
6 // defined with this macro as being exported.
9 #define GRAPH_API __declspec(dllexport)
11 #define GRAPH_API __declspec(dllimport)
14 //////////////////////////////////////////////////////////////////////
17 // Author : Vadim SANDLER
18 //////////////////////////////////////////////////////////////////////
20 #if !defined(_Graph_h)
27 #include <qsplitter.h>
30 #include <qrubberband.h>
32 //================================================================
34 // Description : graph node
35 //================================================================
36 class GRAPH_API GraphNode {
38 // default constructor
41 GraphNode(const double x, const double y);
43 GraphNode(const GraphNode& node);
46 inline double x() const { return myX; }
48 inline double y() const { return myY; }
50 bool operator== (const GraphNode& node);
52 bool operator< (const GraphNode& node);
54 bool operator> (const GraphNode& node);
56 GraphNode& operator= (const GraphNode& node);
64 typedef QList<GraphNode*> NodeList;
67 //================================================================
69 // Description : graph data set
70 //================================================================
71 class GRAPH_API GraphItem {
74 GraphItem(GraphView* parent, QString name = QString::null);
79 void addNode (GraphNode* node);
81 void addNode (const double x, const double y);
83 void addNodes(NodeList& nodes);
84 // removes node (and deletes it)
85 void removeNode(GraphNode* node);
86 // removes node by index (and deletes it)
87 void removeNode(int index);
90 // gets number of nodes
91 int count () { return myNodes.count(); }
92 // returns true if list of nodes is empty
93 bool isEmpty () { return myNodes.isEmpty(); }
94 // returns true if item is valid, i.e. has valid attributes and not empty
96 // returns <Sorted> flag, true by default
97 bool isSorted() { return mySorted; }
98 // sets/clears <Sorted> flag (and reorders nodes)
99 void setSorted (bool sorted);
100 // gets node by index or NULL if index is out of range
101 GraphNode* getNode (const int index);
102 // gets node by index or NULL if index is out of range
103 GraphNode* operator[] (const int index);
104 // sets dynamic marker for item
105 void setMarker (const int marker,
108 // sets static marker for item
109 // (with own (NOT CHANGEABLE) marker, color and type line)
110 void setMarker (const int marker,
112 const Qt::PenStyle line);
114 QString getName() const { return myName; }
116 void setName(const QString& name) { myName = name; }
117 // returns true if item has own color
118 bool hasOwnColor() const { return myHasOwnColor; }
119 // returns true if item has own line type
120 bool hasOwnLine() const { return myHasOwnLine; }
121 // returns true if item has own marker
122 bool hasOwnMarker() const { return myHasOwnMarker; }
124 void setColor(const QColor& color);
125 // returns item's color
128 void setLine(const Qt::PenStyle line);
129 // returns item's line type
130 Qt::PenStyle getLine();
132 void setMarker(const int marker);
133 // return item's marker type
135 // gets marker attributes
136 void getMarker (int& marker, int& color, int& line);
139 // performs initialization
143 // parent graph viewer
149 // attributes type of line, color and marker
160 Qt::PenStyle myOwnLine;
161 // <Sort coordinates> flag
165 typedef QList<GraphItem*> ItemList;
166 typedef QList<QColor> ColorList;
167 typedef QList<Qt::PenStyle> LineList;
168 typedef QList<int> IntList;
172 //================================================================
174 // Description : simple graph displayer
175 //================================================================
176 class GRAPH_API GraphView : public QWidget {
177 struct OperationButton {
178 Qt::MouseButtons button;
179 Qt::KeyboardModifiers modifier;
180 OperationButton(const Qt::MouseButtons btn = Qt::NoButton,
181 const Qt::KeyboardModifiers m = Qt::NoModifier)
182 : button(btn), modifier(m) {}
186 enum ViewOperation { voNone, voZoom, voZoomX, voZoomY,
187 voPan, voPanX, voPanY, voRect };
188 enum GridMode { gmFixed, gmIntervals, gmFloating };
191 void drawItem(QPainter* painter,
203 /* ================== CONSTRUCTION/DESTRUCTION ================ */
205 GraphView(QWidget* parent = 0);
209 /* ======================= OVERRIDED ========================== */
211 bool eventFilter(QObject* object, QEvent* event);
213 /* ================== CURSORS HANDLING ======================== */
214 // sets cursor for certain view operation
215 void setOperationCursor (const ViewOperation operation,
216 const QCursor& newCursor);
217 // gets cursor for certain view operation
218 QCursor getOperationCursor (const ViewOperation operation) const;
220 /* =================== VIEW OPERATIONS ======================== */
221 // returns global <Enable operations> flag state
222 bool isOperationsEnabled() const { return myEnableGlobal; }
223 // globally enables/disables operations
224 void setOperationsEnabled(bool on);
225 // returns 'true' if view operation is enabled
226 bool isOperationEnabled (const ViewOperation operation) const;
227 // enables/disables view operation
228 void setOperationEnabled(const ViewOperation operation,
230 // sets operation key-mousebutton combination
231 void setOperationButton (const ViewOperation operation,
232 const Qt::MouseButtons button,
233 const Qt::KeyboardModifiers modifier);
234 // gets operation key-mousebutton combination
235 void getOperationButton (const ViewOperation operation,
236 Qt::MouseButtons& button,
237 Qt::KeyboardModifiers& modifier) const;
238 // tests for operation key-mousebutton combination
239 bool testOperation (const ViewOperation theOp,
240 const Qt::MouseButtons button,
241 const Qt::KeyboardModifiers modifier) const;
242 // tests key-mousebutton combination and returns view operation if any matches
243 ViewOperation testOperation (const Qt::MouseButtons button,
244 const Qt::KeyboardModifiers modifier) const;
246 // resets view : sets origin to 0.0 and scales to 1.0
248 // fits viewer so display all data
250 // fits viewer to display certain data
251 void fitData(const double xMin, const double xMax,
252 const double yMin, const double yMax);
253 // fits viewer to display certain data along horizontal axis
254 void fitDataX(const double xMin, const double xMax);
255 // fits viewer to display certain data along vertical axis
256 void fitDataY(const double yMin, const double yMax);
257 // performs pan operation by dx, dy pixels
258 void pan(const int dx, const int dy);
259 // performs zoom operation by dx, dy pixels
260 void zoom(const int dx, const int dy);
261 // starts view operation if it is enabled
262 void startViewOperation(const ViewOperation operation);
264 /* ================== ATRIBUTES HANDLING ====================== */
265 // enables/disables internal markers drawing
266 void showMarkers (bool show);
267 // enables/disables tooltips
268 void showTooltips (bool show);
269 // returns true is axes are shown
270 bool isAxesShown () const { return myShowAxes; }
272 void showAxes (bool show);
273 // returns true is tick-marks are shown
274 bool isTickMarkShown () const { return myShowTickMarks; }
275 // shows/hides tick-marks
276 void showTickMark (bool show);
277 // returns true is title is shown
278 bool isTitleShown () const { return myShowTitle; }
280 void showTitle (bool show);
282 const QString& getTitle () const { return myTitle; }
284 void setTitle (const QString& title);
285 // returns true is axes titles are shown
286 bool isAxesTitleShown() const { return myShowAxesTitle; }
287 // shows/hides axis titles
288 void showAxesTitle (bool show);
289 // gets graph X axis title
290 const QString& getXTitle () const { return myXTitle; }
291 // sets graph X axis title
292 void setXTitle (const QString& title);
293 // gets graph Y axis title
294 const QString& getYTitle () const { return myYTitle; }
295 // sets graph Y axis title
296 void setYTitle (const QString& title);
297 // returns true is grid is shown
298 bool isGridShown () const { return myShowGrid; }
300 void showGrid (bool show);
301 // sets grid step (FLOATING mode) for x, y axes,
302 // doesn't change step if it is <= 0
303 void setGridStep (const double x, const double y, bool turn = true);
304 // gets grid step (FLOATING mode) for x, y axes
305 // and returns true if grid mode is FLOATING
306 bool getGridStep (double& x, double& y) const;
307 // sets grid step (FIXED mode) for x, y axes in pixels,
308 // doesn't change step if it is less <= 0
309 void setFixedGridStep (const int x, const int y, bool turn = true);
310 // gets grid step (FIXED mode) for x, y axes in pixels
311 // and returns true if grid mode is FIXED
312 bool getFixedGridStep (int& x, int& y) const;
313 // sets number of grid intervals (INTERVALS mode) for x, y axes,
314 // doesn't change if <= 0
315 void setGridIntervals (const int xInt,
318 // gets number of grid intervals (INTERVALS mode) for x, y axes,
319 // and returns true if grid mode is INTERVALS
320 bool getGridIntervals (int &xInt, int &yInt) const;
321 // returns grid mode [FIXED, INTERVALS, FLOATING]
322 GridMode getGridMode() const { return myGridMode; }
323 // switches grid mode [FIXED, INTERVALS, FLOATING]
324 void setGridMode(const GridMode mode);
326 void setXScale(const double scale);
327 // gets X axis scale (data per pixel along X axis)
328 double getXScale() const { return myXScale; }
330 void setYScale(const double scale);
331 // gets Y axis scale (data per pixel along Y axis)
332 double getYScale() const { return myYScale; }
333 // sets X,Y axis scale
334 void setScale(const double scale);
335 // moves axes origin to point [x, y]
336 void setOrigin(const double x, const double y);
338 void getOrigin(double& x, double& y) const;
339 // changes backgroundColor, use it instead setBackgroundColor
340 void changeBackgroundColor(const int index = -1);
341 // gets main title font
342 QFont getTitleFont() { return myTitleFont; }
343 // sets main title font
344 void setTitleFont(QFont& font);
345 // gets axes title font
346 QFont getAxesTitleFont() { return myAxesTitleFont; }
347 // sets axes title font
348 void setAxesTitleFont(QFont& font);
349 // gets tick marks font
350 QFont getTickMarksFont() { return myTickMarksFont; }
351 // sets tick marks font
352 void setTickMarksFont(QFont& font);
353 // sets legend widget
354 void setLegend(GraphLegend* legend);
355 // gets legend widget
356 GraphLegend* getLegend() { return myLegend; }
358 void getMargins(int& leftMargin,
363 /* ================== DATA HANDLING =========================== */
364 // inserts item into list
365 void insertItem(GraphItem* item);
366 // removes item from list
367 void removeItem(const int index);
370 // gets number of items
371 int getNbItems() { return myItems.count(); }
372 // gets item by index, returns NULL if index is out of range
373 GraphItem* getItem(const int index);
374 // returns index of item in data list
375 int findItem(GraphItem* item);
376 // sets/unsets items to be sorted by horizontal coordinate
377 void setSorted(bool sorted);
378 // gets full data range
379 void getRange(double& minX, double& minY,
380 double& maxX, double& maxY);
381 // gets current data range
382 void getCurrentRange(double& minX, double& minY,
383 double& maxX, double& maxY);
384 // returns number of colors provided
385 virtual int getNbColors();
386 // returns number of markers provided
387 virtual int getNbMarkers();
388 // returns number of type lines provided
389 virtual int getNbTypeLines();
390 // gets marker size (default is 9 pixels)
391 int getMarkerSize() { return myMarkerSize; }
392 // sets marker size (for good look it should be odd)
393 void setMarkerSize(const int size);
394 // gets color by index
395 virtual QColor getColor(const int color);
397 virtual Qt::PenStyle getLine(const int line);
398 // returns true if colors seem to be the same (difference is less than gap)
399 static bool isSameColors(const QColor color1,
404 /* ================== VIEW OPERATIONS HANDLING ================ */
405 // starts/finishes view operation
406 void startOperation (ViewOperation theOp);
407 // called on view operation starting
408 virtual void onStartOperation ();
409 // called on view operation finishing
410 virtual void onFinishOperation ();
411 // called on view operation running
412 virtual void onOperation (QPoint mousePos);
413 // called on mouse moving action (e.g. for highlighting item)
414 virtual void onMouseMove (QPoint mousePos);
415 // gets sensibility area size
416 int getSensibilitySize() const { return mySensibilitySize; }
417 // sets sensibility area size
418 void setSensibilitySize(const int size);
419 // handles tooltips for the view
420 QRect tip(const QPoint& point, QString& tipText);
422 /* ================== EVENTS HANDLING ========================= */
423 // MousePress event handler
424 void mousePressEvent (QMouseEvent* e);
425 // MouseMove event handler
426 void mouseMoveEvent (QMouseEvent* e);
427 // MouseRelease event handler
428 void mouseReleaseEvent (QMouseEvent* e);
429 // MouseDoubleClick event handler
430 void mouseDoubleClickEvent (QMouseEvent *e);
431 // KeyPress event handler
432 void keyPressEvent (QKeyEvent *e);
433 // KeyRelease event handler
434 void keyReleaseEvent (QKeyEvent *e);
435 // Resize event handler
436 void resizeEvent (QResizeEvent* e);
437 // Paint event handler
438 void paintEvent (QPaintEvent* e);
439 // global event handler
440 bool event (QEvent* e);
442 /* ================== DRAWING FUNCTIONS ======================= */
443 // gets graph painting area
444 virtual QRect getGraphRect ();
446 virtual void drawGrid (QPainter* painter);
447 // draws border (it is drawn when grid is not)
448 virtual void drawBorder (QPainter* painter);
450 virtual void drawAxes (QPainter* painter);
452 virtual void drawTickMarks(QPainter* painter);
454 virtual void drawAxesTitle(QPainter* painter);
456 virtual void drawTitle(QPainter* painter);
458 virtual void drawItem (QPainter* painter, GraphItem* item);
459 // draws marker at position
460 virtual void drawMarker(QPainter* painter,
463 const QColor& color);
464 // gets new unique marker for item if possible
465 virtual void getNextMarker(int& typeMarker, int& color, int& typeLine);
466 // checks if marker belongs to some entity
467 bool existMarker(const int typeMarker,
472 // returns true if line [x1,y1] - [x2,y2] intersect rectangle
473 static bool intersects(QRect rect, long x1, long y1, long x2, long y2);
474 // calculates points for grid and/or tick marks
475 void getTickPoints(IntList& xList, IntList& yList);
478 // enable view operations flags
487 // current view operation
488 ViewOperation myOperation;
489 // current view operation
490 ViewOperation myForcedOp;
491 // sensibility size for rect selection operation
492 int mySensibilitySize;
493 // view operation points (second is used for rubber rectangle)
496 // view operations key-mouse combinations
497 OperationButton myRectKey;
498 OperationButton myPanKey;
499 OperationButton myPanXKey;
500 OperationButton myPanYKey;
501 OperationButton myZoomKey;
502 OperationButton myZoomXKey;
503 OperationButton myZoomYKey;
506 QCursor myRectCursor;
508 QCursor myPanXCursor;
509 QCursor myPanYCursor;
510 QCursor myZoomCursor;
511 QCursor myZoomXCursor;
512 QCursor myZoomYCursor;
513 // axes origin (left-bottom point)
521 bool myShowAxesTitle;
522 bool myShowTickMarks;
531 // floating grid size
534 // number of grid intervals
549 GraphLegend* myLegend;
552 QFont myAxesTitleFont;
553 QFont myTickMarksFont;
555 QRubberBand* myRubberBand;
557 friend class GraphLegend;
560 //================================================================
561 // Class : GraphLegend
562 // Description : Legend widget
563 //================================================================
564 class GRAPH_API GraphLegend : public QWidget {
567 GraphLegend(QWidget* parent, GraphView* graph);
569 // updates legend contents
571 // shows/hides legend title
572 void showTitle(bool show);
574 void setTitle(const QString& title);
576 QString getTitle() const { return myTitle; }
577 // returns graph item which is below the point or NULL
578 GraphItem* itemAt(const QPoint& point);
579 // gets legend title font
580 QFont getTitleFont() { return myTitleFont; }
581 // sets legend title font
582 void setTitleFont(QFont& font);
584 QFont getItemFont() { return font(); }
586 void setItemFont(QFont& font);
588 QSize minimumSizeHint() const;
589 QSize sizeHint() const;
592 // handles tooltips for the view
593 QRect tip(const QPoint& point, QString& tipText);
594 // returns rect which contains item's name
595 QRect textRect(GraphItem* item, QString& tipText);
597 void paintEvent(QPaintEvent* e);
598 // global event handler
599 bool event(QEvent* e);
609 //================================================================
610 // Class : GraphSplitView
611 // Description : Graph view with a legend in splitted window
612 //================================================================
613 class GRAPH_API GraphSplitView : public QWidget {
616 GraphSplitView(QWidget* parent);
618 // returns graph view
619 GraphView* getGraph() { return myGraph; }
620 // returns legend view
621 GraphLegend* getLegend();
622 // shows/hides legend view
623 void showLegend(bool show);
624 // returns true if legend is being shown
625 bool isLegendShown();
631 QSplitter* mySplitter;
634 #endif // !defined(_Graph_h)