diff --git a/ChangeLog b/ChangeLog index 2d8937ef..08edb2fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2017-03-19 Markus Gans + * Add the "mouse" example to illustrate mouse programming + 2017-03-17 Markus Gans * More constant character pointers diff --git a/src/flabel.cpp b/src/flabel.cpp index 7784db43..28ea33d8 100644 --- a/src/flabel.cpp +++ b/src/flabel.cpp @@ -455,6 +455,7 @@ void FLabel::draw() if ( isMonochron() ) { setReverse(true); + if ( hasEmphasis() ) setBold(true); } diff --git a/src/fobject.h b/src/fobject.h index 16f921a5..73d29ebe 100644 --- a/src/fobject.h +++ b/src/fobject.h @@ -49,14 +49,6 @@ typedef long double lDouble; class FObject { public: - struct timer_data - { - int id; - timeval interval; - timeval timeout; - FObject* object; - }; - // Typedef typedef std::list FObjectList; @@ -93,6 +85,14 @@ class FObject bool delAllTimer(); protected: + struct timer_data + { + int id; + timeval interval; + timeval timeout; + FObject* object; + }; + // Typedef typedef std::vector TimerList; diff --git a/src/fvterm.cpp b/src/fvterm.cpp index 1c0dfe3a..1e097805 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -763,6 +763,20 @@ void FVTerm::resizeArea ( int offset_left, int offset_top if ( ! area ) return; + if ( width == area->width + && height == area->height + && rsw == area->right_shadow + && bsh == area->bottom_shadow ) + { + if ( offset_left != area->offset_left ) + area->offset_left = offset_left; + + if ( offset_top != area->offset_top ) + area->offset_top = offset_top; + + return; + } + area_size = (width+rsw) * (height+bsh); if ( area->height + area->bottom_shadow != height + bsh ) diff --git a/test/mouse.cpp b/test/mouse.cpp index 87977e86..3b3f93ba 100644 --- a/test/mouse.cpp +++ b/test/mouse.cpp @@ -2,6 +2,522 @@ #include "fapp.h" #include "fdialog.h" +#include "flabel.h" +#include "fmessagebox.h" + + +//---------------------------------------------------------------------- +// class ColorChooser +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class ColorChooser : public FWidget +{ + public: + // Constructor + explicit ColorChooser (FWidget* = 0); + + // Destructor + ~ColorChooser(); + + // Accessors + short getForeground(); + short getBackground(); + + private: + // Disable copy constructor + ColorChooser (const ColorChooser&); + // Disable assignment operator (=) + ColorChooser& operator = (const ColorChooser&); + + // Method + void draw(); + + // Event handler + void onMouseDown (FMouseEvent*); + + // Data Members + short fg_color; + short bg_color; +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +ColorChooser::ColorChooser (FWidget* parent) + : FWidget(parent) + , fg_color(fc::White) + , bg_color(fc::Black) +{ + setSize (8, 12); + setFixedSize (8, 12); + unsetFocusable(); + + if ( parent ) + { + setForegroundColor(parent->getForegroundColor()); + setBackgroundColor(parent->getBackgroundColor()); + } + + // Text label + FLabel* headline = new FLabel (this); + headline->setGeometry(1, 1, 8, 1); + headline->setText ("Color"); + headline->setEmphasis(); + headline->setAlignment (fc::alignCenter); +} + +//---------------------------------------------------------------------- +ColorChooser::~ColorChooser() +{ } + +//---------------------------------------------------------------------- +void ColorChooser::onMouseDown (FMouseEvent* ev) +{ + int mouse_x = ev->getX(); + int mouse_y = ev->getY(); + + if ( ev->getButton() == fc::MiddleButton ) + return; + + for (int c=0; c < 16; c++) + { + int xmin = 2 + (c / 8) * 3; + int xmax = 4 + (c / 8) * 3; + int y = 3 + c % 8; + + if ( mouse_x >= xmin && mouse_x <= xmax && mouse_y == y ) + { + if ( ev->getButton() == fc::LeftButton ) + bg_color = short(c); + else if ( ev->getButton() == fc::RightButton ) + fg_color = short(c); + + redraw(); + emitCallback("clicked"); + } + } +} + +//---------------------------------------------------------------------- +void ColorChooser::draw() +{ + setColor(); + FWidget::drawBorder (1, 2, 8, 11); + + for (short c=0; c < 16; c++) + { + setPrintPos (2 + (c/8)*3, 3 + c%8); + + if ( c < 6 ) + setColor (fc::LightGray, c); + else if ( c > 8 ) + setColor (fc::DarkGray, c); + else + setColor (fc::White, c); + + if ( c == bg_color ) + { + print (' '); + print (fc::Times); + print (' '); + } + else + print (" "); + } +} + +//---------------------------------------------------------------------- +inline short ColorChooser::getForeground() +{ + return fg_color; +} + +//---------------------------------------------------------------------- +inline short ColorChooser::getBackground() +{ + return bg_color; +} + + +//---------------------------------------------------------------------- +// class Brushes +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class Brushes : public FWidget +{ + public: + // Constructor + explicit Brushes (FWidget* = 0); + + // Destructor + ~Brushes(); + + // Accessor + wchar_t getBrush(); + + // Mutators + void setForeground (short); + void setBackground (short); + + private: + // Disable copy constructor + Brushes (const Brushes&); + // Disable assignment operator (=) + Brushes& operator = (const Brushes&); + + // Method + void draw(); + + // Event handler + void onMouseDown (FMouseEvent*); + + // Data Members + wchar_t brush; + short fg_color; + short bg_color; +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +Brushes::Brushes (FWidget* parent) + : FWidget(parent) + , brush(L' ') + , fg_color(fc::White) + , bg_color(fc::Black) +{ + setSize (8, 4); + setFixedSize (8, 4); + unsetFocusable(); + + if ( parent ) + { + setForegroundColor(parent->getForegroundColor()); + setBackgroundColor(parent->getBackgroundColor()); + } + + // Text label + FLabel* headline = new FLabel (this); + headline->setGeometry(1, 1, 8, 1); + headline->setText ("Brush"); + headline->setEmphasis(); + headline->setAlignment (fc::alignCenter); +} + +//---------------------------------------------------------------------- +Brushes::~Brushes() +{ } + + +//---------------------------------------------------------------------- +void Brushes::draw() +{ + int pos; + setColor(); + FWidget::drawBorder (1, 2, 8, 4); + setColor (fg_color, bg_color); + setPrintPos (2, 3); + print(" "); + print(FString(3, wchar_t(fc::MediumShade))); + + if ( brush == L' ' ) + pos = 0; + else + pos = 3; + + setColor(); + setPrintPos (3 + pos, 2); + print(wchar_t(fc::BlackDownPointingTriangle)); + setPrintPos (3 + pos, 4); + print(wchar_t(fc::BlackUpPointingTriangle)); +} + +//---------------------------------------------------------------------- +void Brushes::onMouseDown (FMouseEvent* ev) +{ + int mouse_x = ev->getX(); + int mouse_y = ev->getY(); + + if ( ev->getButton() != fc::LeftButton ) + return; + + if ( mouse_x >= 2 && mouse_x <= 4 && mouse_y == 3 ) + { + brush = L' '; + redraw(); + } + else if ( mouse_x >= 5 && mouse_x <= 7 && mouse_y == 3 ) + { + brush = wchar_t(fc::MediumShade); + redraw(); + } +} + +//---------------------------------------------------------------------- +inline wchar_t Brushes::getBrush() +{ + return brush; +} + +//---------------------------------------------------------------------- +inline void Brushes::setForeground (short color) +{ + fg_color = color; +} + +//---------------------------------------------------------------------- +inline void Brushes::setBackground (short color) +{ + bg_color = color; +} + + +//---------------------------------------------------------------------- +// class MouseDraw +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class MouseDraw : public FDialog +{ + public: + // Using-declaration + using FWidget::setGeometry; + + // Constructor + explicit MouseDraw (FWidget* = 0); + + // Destructor + ~MouseDraw(); + + // Methods + void setGeometry (int, int, int, int, bool = true); + + // Event handlers + void onAccel (FAccelEvent*); + void onClose (FCloseEvent*); + + private: + // Disable copy constructor + MouseDraw (const MouseDraw&); + // Disable assignment operator (=) + MouseDraw& operator = (const MouseDraw&); + + // Methods + virtual void draw(); + void drawBrush (int, int, bool = false); + void drawCanvas(); + void adjustSize(); + + // Event handler + void onMouseDown (FMouseEvent*); + void onMouseMove (FMouseEvent*); + + // Callback methods + void cb_colorChanged (FWidget*, data_ptr); + + // Data Members + term_area* canvas; + ColorChooser* c_chooser; + Brushes* brush; +}; +#pragma pack(pop) + +//---------------------------------------------------------------------- +MouseDraw::MouseDraw (FWidget* parent) + : FDialog(parent) + , canvas(0) + , c_chooser() + , brush() +{ + setText ("Drawing with the mouse"); + c_chooser = new ColorChooser(this); + c_chooser->setPos (1,1); + c_chooser->addCallback + ( + "clicked", + _METHOD_CALLBACK (this, &MouseDraw::cb_colorChanged) + ); + + brush = new Brushes(this); + brush->setPos (1,12); + + FPoint no_shadow(0,0); + FRect scroll_geometry(0, 0, 1, 1); + createArea (scroll_geometry, no_shadow, canvas); +} + +//---------------------------------------------------------------------- +MouseDraw::~MouseDraw() +{ } + +//---------------------------------------------------------------------- +void MouseDraw::setGeometry (int x, int y, int w, int h, bool adjust) +{ + int old_w, old_h; + FDialog::setGeometry (x, y, w, h, adjust); + + FPoint no_shadow(0,0); + FRect scroll_geometry (0, 0, w-11, h-3); + old_w = canvas->width; + old_h = canvas->height; + resizeArea (scroll_geometry, no_shadow, canvas); + + if ( old_w != canvas->width || old_h != canvas->height ) + { + setColor(getForegroundColor(), getBackgroundColor()); + clearArea (canvas, ' '); + } +} + +//---------------------------------------------------------------------- +void MouseDraw::onAccel (FAccelEvent* ev) +{ + close(); + ev->accept(); +} + +//---------------------------------------------------------------------- +void MouseDraw::onClose (FCloseEvent* ev) +{ + int ret = FMessageBox::info ( this, "Quit" + , "Do you really want\n" + "to quit the program ?" + , FMessageBox::Yes + , FMessageBox::No ); + + if ( ret == FMessageBox::Yes ) + ev->accept(); + else + ev->ignore(); +} + +//---------------------------------------------------------------------- +void MouseDraw::draw() +{ + int y_max = getHeight(); + FDialog::draw(); + setColor(); + setPrintPos (10, 2); + print (wchar_t(fc::BoxDrawingsDownAndHorizontal)); + + for (int y=3; y < y_max; y++) + { + setPrintPos (10, y); + print (wchar_t(fc::BoxDrawingsVertical)); + } + + setPrintPos (10, y_max); + print (wchar_t(fc::BoxDrawingsUpAndHorizontal)); + drawCanvas(); +} + +//---------------------------------------------------------------------- +void MouseDraw::drawBrush (int x, int y, bool swap_color) +{ + int Cols = getWidth(); + int Lines = getHeight(); + + if ( x > 10 && x < Cols && y > 2 && y < Lines ) + { + if ( swap_color ) + setColor (c_chooser->getBackground(), c_chooser->getForeground()); + else + setColor (c_chooser->getForeground(), c_chooser->getBackground()); + + // set canvas print cursor position + canvas->cursor_x = x - canvas->offset_left - 10; + canvas->cursor_y = y - canvas->offset_top - 2; + // print on canvas + print (canvas, brush->getBrush()); + // copy canvas to the dialog + drawCanvas(); + } +} + +//---------------------------------------------------------------------- +void MouseDraw::drawCanvas() +{ + int ax, ay, y_end, x_end; + char_data* cc; // canvas character + char_data* wc; // window character + + if ( ! hasPrintArea() ) + FVTerm::getPrintArea(); + + if ( ! (hasPrintArea() && canvas) ) + return; + + ax = 9 + getTermX() - print_area->offset_left; + ay = 1 + getTermY() - print_area->offset_top; + y_end = canvas->height; + x_end = canvas->width; + int w_line_len = print_area->width + print_area->right_shadow; + + for (int y=0; y < y_end; y++) // line loop + { + cc = &canvas->text[y * x_end]; + wc = &print_area->text[(ay+y) * w_line_len + ax]; + std::memcpy (wc, cc, sizeof(char_data) * unsigned(x_end)); + + if ( short(print_area->changes[ay+y].xmin) > ax ) + print_area->changes[ay+y].xmin = uInt(ax); + + if ( short(print_area->changes[ay+y].xmax) < ax+x_end-1 ) + print_area->changes[ay+y].xmax = uInt(ax+x_end-1); + } + + print_area->has_changes = true; +} + +//---------------------------------------------------------------------- +void MouseDraw::adjustSize() +{ + int w = 60; + int h = 18; + int x = 1 + (getParentWidget()->getWidth() - w) / 2; + int y = 1 + (getParentWidget()->getHeight() - h) / 2; + setGeometry (x, y, w, h, false); + FDialog::adjustSize(); +} + +//---------------------------------------------------------------------- +void MouseDraw::onMouseDown (FMouseEvent* ev) +{ + FDialog::onMouseDown(ev); + + if ( ev->getButton() != fc::LeftButton + && ev->getButton() != fc::RightButton ) + return; + + drawBrush (ev->getX(), ev->getY(), ev->getButton() == fc::RightButton); +} + +//---------------------------------------------------------------------- +void MouseDraw::onMouseMove (FMouseEvent* ev) +{ + FDialog::onMouseMove(ev); + + if ( ev->getButton() != fc::LeftButton + && ev->getButton() != fc::RightButton ) + return; + + drawBrush (ev->getX(), ev->getY(), ev->getButton() == fc::RightButton); +} + +//---------------------------------------------------------------------- +void MouseDraw::cb_colorChanged (FWidget*, data_ptr) +{ + brush->setForeground (c_chooser->getForeground()); + brush->setBackground (c_chooser->getBackground()); + brush->redraw(); +} + //---------------------------------------------------------------------- // main part @@ -12,8 +528,9 @@ int main (int argc, char* argv[]) FApplication app(argc, argv); // Create a simple dialog box - FDialog mouse_draw(&app); + MouseDraw mouse_draw(&app); mouse_draw.setGeometry (12, 4, 60, 18); + mouse_draw.addAccelerator('q'); // press 'q' to quit app.setMainWidget(&mouse_draw); mouse_draw.show();