diff --git a/bazaar/Scatter/Scatter.cpp b/bazaar/Scatter/Scatter.cpp index b82bac198..99e239722 100644 --- a/bazaar/Scatter/Scatter.cpp +++ b/bazaar/Scatter/Scatter.cpp @@ -4,6 +4,16 @@ #define IMAGEFILE #include +Scatter::MouseBehaviour defaultMouse[] = { + {false, false, false, true , false, 0, false, Scatter::SHOW_INFO}, + {false, false, false, false, true , 0, false, Scatter::SCROLL}, + {false, false, false, false, false, 1, false, Scatter::ZOOM_H_RED}, + {false, false, false, false, false, 1, false, Scatter::ZOOM_V_RED}, + {false, false, false, false, false,-1, false, Scatter::ZOOM_H_ENL}, + {false, false, false, false, false,-1, false, Scatter::ZOOM_V_ENL}, + {false, false, false, false, false, 0, false, Scatter::NO_ACTION}}; + + Scatter& Scatter::SetColor(const class::Color& _color) { graphColor=_color; @@ -486,7 +496,7 @@ void Scatter::SetFunctColor(const int& j, const class::Color& fcolor) Refresh(); } } -Acolor Scatter::GetDataColor(const int& j) const +Color Scatter::GetDataColor(const int& j) const { if(IsValid(j)) { @@ -495,7 +505,7 @@ Acolor Scatter::GetDataColor(const int& j) const throw (Exc(t_("Invalid series index!"))); } -Acolor Scatter::GetFunctColor(const int& j) const +Color Scatter::GetFunctColor(const int& j) const { if(IsValid(j)) { @@ -575,7 +585,7 @@ int Scatter::GetMarkStyle(const int& j) const throw (Exc(t_("Invalid series index!"))); } -void Scatter::SetMarkColor(const int& j, const Acolor& mcolor) +void Scatter::SetMarkColor(const int& j, const ::Color& mcolor) { if(IsValid(j)) { @@ -584,7 +594,7 @@ void Scatter::SetMarkColor(const int& j, const Acolor& mcolor) } } -Acolor Scatter::GetMarkColor(const int& j) const +Color Scatter::GetMarkColor(const int& j) const { if(IsValid(j)) { @@ -940,36 +950,135 @@ void Scatter::ProcessPopUp(const Point & pt) popText.SetText(str).Move(this,p2.x,p2.y); } -void Scatter::LeftDown(Point pt, dword) +void Scatter::DoMouseAction(bool down, Point pt, MouseAction action, int value) { - if(paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - popText.AppearOnly(this); - ProcessPopUp(pt); - isLeftDown = true; - } -} -void Scatter::LeftUp(Point, dword) -{ - if(paintInfo && isLeftDown) - { - popText.Close(); - isLeftDown = false; + switch (action) { + case SCROLL: Scrolling(down, pt); + break; + case ZOOM_H_ENL: + case ZOOM_H_RED: MouseZoom(value, true, false); + break; + case ZOOM_V_ENL: + case ZOOM_V_RED: MouseZoom(value, false, true); + break; + case SHOW_INFO: LabelPopUp(down, pt); + break; } } -void Scatter::MiddleDown(Point pt, dword) +bool Scatter::SetMouseBehavior(MouseBehaviour *_mouseBehavior) { - if((mouseHandlingX || mouseHandlingY) && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) - { - butDownX = pt.x; - butDownY = pt.y; - isMidDown = true; + if (!_mouseBehavior) + return false; + int i; + for (i = 0; _mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) ; + if (i == MAX_MOUSEBEHAVIOR) + return false; + mouseBehavior = _mouseBehavior; + return true; +} + +void Scatter::ProcessMouse(bool down, Point pt, bool ctrl, bool alt, bool shift, bool left, bool middle, int middleWheel, bool right) +{ + int i; + for (i = 0; mouseBehavior[i].action != NO_ACTION && i < MAX_MOUSEBEHAVIOR; ++i) { + if (mouseBehavior[i].ctrl == ctrl && mouseBehavior[i].alt == alt && + mouseBehavior[i].shift == shift && mouseBehavior[i].left == left && + mouseBehavior[i].middle == middle && mouseBehavior[i].right == right && + ((mouseBehavior[i].middleWheel == 0) || mouseBehavior[i].middleWheel == ((middleWheel > 0) - (middleWheel < 0)))) + DoMouseAction(down, pt, mouseBehavior[i].action, middleWheel); + } +} + +void Scatter::LabelPopUp(bool down, Point pt) +{ + if (down) { + if(paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + popText.AppearOnly(this); + ProcessPopUp(pt); + isLabelPopUp = true; + } + } else { + if(paintInfo && isLabelPopUp) + { + popText.Close(); + isLabelPopUp = false; + } } } + +#ifdef PLATFORM_LINUX + #include +#endif + +void Scatter::Scrolling(bool down, Point pt) +{ + static Image mouseImg; + if (down) { + if((mouseHandlingX || mouseHandlingY) && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) + { + butDownX = pt.x; + butDownY = pt.y; + isScrolling = true; +/* INTERLOCKED { +#ifdef PLATFORM_WIN32 + static Image img = Win32Cursor(IDC_SIZEALL); +#else + static Image img = X11Cursor(XC_fleur); +#endif + mouseImg = Ctrl::OverrideCursor(img); + }*/ + } + } else { + if (isScrolling) { + MouseMove(pt, 0); + isScrolling = false; +// Ctrl::OverrideCursor(mouseImg); + } + } +} + +void Scatter::LeftDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); +} + +void Scatter::LeftUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, true, false, 0, false); +} + +void Scatter::MiddleDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); +} + +void Scatter::MiddleUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, true, 0, false); +} + +void Scatter::RightDown(Point pt, dword keyFlags) +{ + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); +} + +void Scatter::RightUp(Point pt, dword keyFlags) +{ + ProcessMouse(false, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, 0, true); +} + +void Scatter::MouseWheel(Point pt, int zdelta, dword keyFlags) +{ + if (zdelta == 0) + return; + ProcessMouse(true, pt, keyFlags & K_CTRL, keyFlags & K_ALT, keyFlags & K_SHIFT, false, false, zdelta, false); +} + void Scatter::MouseMove(Point pt, dword) { - if (isMidDown) + if (isScrolling) { int shiftX = pt.x - butDownX; if (mouseHandlingX && shiftX != 0) { @@ -999,7 +1108,7 @@ void Scatter::MouseMove(Point pt, dword) WhenZoomScroll(); } } - if(isLeftDown) { + if(isLabelPopUp) { if (paintInfo && px <=pt.x && pt.x<= GetSize().cx-px && (py + titleFont.GetHeight())<=pt.y && pt.y<= GetSize().cy-py) { ProcessPopUp(pt); @@ -1007,25 +1116,23 @@ void Scatter::MouseMove(Point pt, dword) } } -void Scatter::MiddleUp(Point pt, dword d) -{ - if (isMidDown) { - MouseMove(pt, d); - isMidDown = false; - } -} - void Scatter::MouseLeave() { - isMidDown = false; + isScrolling = false; } -void Scatter::Zoom(double scale) +void Scatter::MouseZoom(int zdelta, bool hor, bool ver) { - bool mouseX = mouseHandlingX; + double scale = zdelta > 0 ? zdelta/100. : -100./zdelta; + Zoom(scale); +} + +void Scatter::Zoom(double scale, bool hor, bool ver) +{ + bool mouseX = mouseHandlingX && hor; mouseX = mouseX && ((minXZoom > 0 && xRange*scale > minXZoom) || (minXZoom < 0)); mouseX = mouseX && ((maxXZoom > 0 && xRange*scale < maxXZoom) || (maxXZoom < 0)); - bool mouseY = mouseHandlingY; + bool mouseY = mouseHandlingY && ver; mouseY = mouseY && ((minYZoom > 0 && yRange*scale > minYZoom) || (minYZoom < 0)); mouseY = mouseY && ((maxYZoom > 0 && yRange*scale < maxYZoom) || (maxYZoom < 0)); mouseX = mouseX && (!mouseHandlingY || mouseY); @@ -1077,14 +1184,6 @@ void Scatter::Scroll(double factorX, double factorY) } } -void Scatter::MouseWheel(Point, int zdelta, dword) -{ - if (zdelta == 0) - return; - double scale = zdelta > 0 ? zdelta/100. : -100./zdelta; - Zoom(scale); -} - Image Scatter::CursorImage(Point p, dword keyflags) { return ChartImg::cursor1(); @@ -1607,7 +1706,7 @@ Scatter::Scatter(): gridColor(::Color(102,102,102)), gridWidth(4), paintInfo(false), - mouseHandlingX(false), mouseHandlingY(false), isMidDown(false), isLeftDown(false), + mouseHandlingX(false), mouseHandlingY(false), isScrolling(false), isLabelPopUp(false), drawXReticle(true), drawYReticle(true), drawY2Reticle(false), drawVGrid(true), drawHGrid(true), showLegend(true),legendWeight(80), @@ -1618,6 +1717,7 @@ Scatter::Scatter(): Color(graphColor); BackPaint(); popText.SetColor(::Color(200,220,255)); + SetMouseBehavior(defaultMouse); } Scatter::~Scatter() diff --git a/bazaar/Scatter/Scatter.h b/bazaar/Scatter/Scatter.h index 42c9f2f88..8a84c550d 100644 --- a/bazaar/Scatter/Scatter.h +++ b/bazaar/Scatter/Scatter.h @@ -12,7 +12,6 @@ using namespace Upp; typedef Pointf XY; -typedef class::Color Acolor; class Scatter : public StaticRect { public: @@ -48,6 +47,8 @@ public: virtual void MiddleDown(Point, dword); virtual void MouseMove(Point, dword); virtual void MiddleUp(Point, dword); + virtual void RightDown(Point, dword); + virtual void RightUp(Point, dword); virtual void MouseLeave(); virtual void MouseWheel(Point, int zdelta, dword); @@ -55,6 +56,23 @@ public: Callback WhenSetRange; Callback WhenSetXYMin; + enum MouseAction {NO_ACTION = 1111110, SCROLL, ZOOM_H_ENL, ZOOM_H_RED, ZOOM_V_ENL, ZOOM_V_RED, SHOW_INFO}; + + struct MouseBehaviour { + bool ctrl; + bool alt; + bool shift; + bool left; + bool middle; + int middleWheel; + bool right; + MouseAction action; + }; + + #define MAX_MOUSEBEHAVIOR 20 + + bool SetMouseBehavior(MouseBehaviour *_mouseBehavior); + Scatter& SetColor(const class::Color& _color); Scatter& SetTitle(const String& _title); Scatter& SetTitleFont(const Font& fontTitle); @@ -87,7 +105,7 @@ public: Scatter& SetAntialiasing(const bool& aa=true); void FitToData(bool Y = false); - void Zoom(double scale); + void Zoom(double scale, bool hor = true, bool ver = true); void Scroll(double factorX, double factorY); Scatter& SetRange(double rx, double ry, double ry2 = -1); @@ -141,7 +159,7 @@ public: void SetMarkStyle(const int& j, MarkStyle noStyle); int GetMarkStyle(const int& j) const; void SetMarkColor(const int& j, const class::Color& pcolor); - Acolor GetMarkColor (const int& j) const; + ::Color GetMarkColor (const int& j) const; void SetShowMark(const int& j, const bool& show=true); bool IsMarkShow(const int& j) const throw (Exc); @@ -247,7 +265,7 @@ private: bool logX, logY, logY2; int butDownX, butDownY; - bool isMidDown, isLeftDown; + bool isScrolling, isLabelPopUp; Vector > vPointsData,vFunctionData; Vector vFPrimaryY, vPPrimaryY; @@ -274,6 +292,14 @@ private: Vector Cubic (const Vector& DataSet, const int& fineness=10, double tension=0.4)const; void DrawLegend(Draw& w,const int& scale) const; + MouseBehaviour *mouseBehavior; + + void DoMouseAction(bool down, Point pt, MouseAction action, int value); + void ProcessMouse(bool down, Point pt, bool ctrl, bool alt, bool shift, bool left, bool middle, int middleWheel, bool right); + void LabelPopUp(bool down, Point pt); + void Scrolling(bool down, Point pt); + void MouseZoom(int zdelta, bool hor, bool ver); + void SetDrawing(Draw& w, const int& scale)const; void Circle(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const; void Square(Draw& w, const int& scale, const Point& cp, const int& size, const class::Color& markColor)const; diff --git a/bazaar/Scatter/src.tpp/Scatter$en-us.tpp b/bazaar/Scatter/src.tpp/Scatter$en-us.tpp index dd48cc0b1..7ddde4a7f 100644 --- a/bazaar/Scatter/src.tpp/Scatter$en-us.tpp +++ b/bazaar/Scatter/src.tpp/Scatter$en-us.tpp @@ -11,14 +11,19 @@ topic "Scatter Reference"; [b42;2 $$9,9#13035079074754324216151401829390:normal] [{_} [ {{10000@(113.42.0) [s0;%% [*@7;4 Scatter]]}}&] +[s3; &] +[s1;:Scatter`:`:class: [@(0.0.255)3 class][3 _][*3 Scatter][3 _:_][@(0.0.255)3 public][3 _][*@3;3 St +aticRect]&] +[s9; A class to plot 2D graphs.&] [s0;i448;a25;kKO9;@(0.0.255) &] [ {{10000F(128)G(128)@1 [s0;%% [* Function List]]}}&] [s4; &] -[s5;:Scatter`:`:FitToData`(bool`): [@(0.0.255) void]_[* FitToData]([@(0.0.255) bool]_[*@3 Y]_ -`=_[@(0.0.255) false])&] +[s5;:Scatter`:`:class: [@(0.0.255) void]_[* FitToData]([@(0.0.255) bool]_[*@3 Y]_`=_[@(0.0.255) f +alse])&] [s0;l288;%% Changes X axis zoom to fit visible all data in Ctrl.&] [s0;l288;i448;a25;kKO9;%% If [%-*@3 Y ]is true, Y axis zoom is also changed to fit the data.&] +[s3;%% &] [s4; &] [s5;:Scatter`:`:SaveToClipboard`(bool`): [@(0.0.255) void]_[* SaveToClipboard]([@(0.0.255) b ool]_[*@3 saveAsMetafile]_`=_[@(0.0.255) false])&] @@ -119,4 +124,75 @@ side of control.&] [s2;%% Gets secondary Y axis coordinate of the first visible point in the bottommost side of control.&] [s3; &] +[s4; &] +[s5;:Scatter`:`:SetMouseBehavior`(Scatter`:`:MouseBehaviour`*`): [@(0.0.255) bool]_[* Set +MouseBehavior]([_^Scatter`:`:MouseBehaviour^ MouseBehaviour]_`*[*@3 mouseBehavior])&] +[s2;%% Sets with [%-*@3 mouseBehavior] the array of MouseBehavior conditions +and actions to be considered when handling the mouse over the +control.&] +[s2;%% This array has to be ended with an item with action `=`= NO`_ACTION.&] +[s2;%% Returns false if [%-*@3 mouseBehavior] array is not well defined.&] +[s3; &] +[s0; &] +[ {{10000@3 [s0;%% [*@(229)4 Scatter`::MouseBehavior]]}}&] +[s3;%% &] +[s1;:Scatter`:`:MouseBehaviour`:`:struct: [@(0.0.255)3 struct][3 _][*3 MouseBehavior]&] +[s9;%% This structure is used to describe the behavior of the mouse +when used in Scatter. It includes the keyboard and mouse conditions +that, when complied, will launch the indicated action.&] +[s9;%% It is used by SetMouseBehavior(MouseBehaviour `*`_mouseBehavior) +function to set an array of MouseBehavior items that will be +used to launch actions as zooming or scrolling when mouse is +used.&] +[s9;%% The default array is in Scatter`::MouseBehaviour defaultMouse.&] +[s3;%% &] +[s0; &] +[ {{10000F(128)G(128)@1 [s0;%% [* Public Member List]]}}&] +[s3;%% &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:ctrl: [@(0.0.255) bool]_[* ctrl]&] +[s2;%% Set to true if Ctrl has to be pressed.&] +[s3; &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:alt: [@(0.0.255) bool]_[* alt]&] +[s2;%% Set to true if Alt has to be pressed.&] +[s3; &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:shift: [@(0.0.255) bool]_[* shift]&] +[s2;%% Set to true if Shift has to be pressed.&] +[s3; &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:left: [@(0.0.255) bool]_[* left]&] +[s2;%% Set to true if mouse left button has to be pressed.&] +[s3; &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:middle: [@(0.0.255) bool]_[* middle]&] +[s2;%% Set to true if mouse middle button has to be pressed.&] +[s3; &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:middleWheel: [@(0.0.255) int]_[* middleWheel]&] +[s2;%% Set to true if mouse middle wheel has to be rolled.&] +[s3; &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:right: [@(0.0.255) bool]_[* right]&] +[s2;%% Set to true if mouse right button has to be pressed.&] +[s3; &] +[s4; &] +[s5;:Scatter`:`:MouseBehaviour`:`:action: MouseAction_[* action]&] +[s2;%% Is the action to be launched if the previous conditions are +complied. It can be:&] +[s2;i150;O0;~~~1248;%% NO`_ACTION-|No action. It serves to mark the +end of MouseBehavior array.&] +[s2;i150;O0;~~~1248;%% SCROLL-|Scrolls the graphs.&] +[s2;i150;O0;~~~1248;%% ZOOM`_H`_ENL-|Zooms horizontally enlarging +the graphs. &] +[s2;i150;O0;~~~1248;%% ZOOM`_H`_RED-|Zooms horizontally reducing the +graphs.&] +[s2;i150;O0;~~~1248;%% ZOOM`_V`_ENL-|Zooms vertically enlarging the +graphs.&] +[s2;i150;O0;~~~1248;%% ZOOM`_V`_RED-|Zooms horizontally reducing the +graphs.&] +[s2;i150;O0;~~~1248;%% SHOW`_INFO-|Shows an info label including mouse +real X and Y coordinates.&] +[s3;%% &] [s0; ] \ No newline at end of file