finalcut/examples/mouse.cpp

582 lines
15 KiB
C++
Raw Normal View History

2017-11-04 07:03:53 +01:00
/***********************************************************************
* mouse.cpp - A small mouse-controlled drawing program *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2017-2019 Markus Gans *
2017-11-04 07:03:53 +01:00
* *
* The Final Cut is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public License *
* as published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* The Final Cut is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* <http://www.gnu.org/licenses/>. *
***********************************************************************/
2017-03-17 23:22:13 +01:00
#include <final/final.h>
2017-03-19 17:18:07 +01:00
namespace fc = finalcut::fc;
2019-08-11 18:15:57 +02:00
using finalcut::FColorPair;
using finalcut::FRect;
using finalcut::FPoint;
using finalcut::FSize;
2017-03-19 17:18:07 +01:00
//----------------------------------------------------------------------
// class ColorChooser
//----------------------------------------------------------------------
class ColorChooser : public finalcut::FWidget
2017-03-19 17:18:07 +01:00
{
2017-09-11 03:06:02 +02:00
public:
// Constructor
explicit ColorChooser (finalcut::FWidget* = nullptr);
// Disable copy constructor
ColorChooser (const ColorChooser&) = delete;
2017-09-11 03:06:02 +02:00
// Destructor
~ColorChooser();
2017-03-19 17:18:07 +01:00
// Disable assignment operator (=)
ColorChooser& operator = (const ColorChooser&) = delete;
2017-09-11 03:06:02 +02:00
// Accessors
2018-11-13 02:51:41 +01:00
FColor getForeground();
FColor getBackground();
2017-03-19 17:18:07 +01:00
2017-09-11 03:06:02 +02:00
private:
// Method
2019-08-06 23:45:28 +02:00
void draw() override;
void drawBorder() override;
2017-03-19 17:18:07 +01:00
2017-09-11 03:06:02 +02:00
// Event handler
2019-08-06 23:45:28 +02:00
void onMouseDown (finalcut::FMouseEvent*) override;
2017-03-19 17:18:07 +01:00
// Data members
FColor fg_color{fc::White};
FColor bg_color{fc::Black};
finalcut::FLabel headline{this};
2017-03-19 17:18:07 +01:00
};
//----------------------------------------------------------------------
ColorChooser::ColorChooser (finalcut::FWidget* parent)
2017-03-19 17:18:07 +01:00
: FWidget(parent)
{
setSize (FSize(8, 12));
setFixedSize (FSize(8, 12));
2017-03-19 17:18:07 +01:00
unsetFocusable();
if ( parent )
{
2018-11-13 02:51:41 +01:00
FColor fg = parent->getForegroundColor();
FColor bg = parent->getBackgroundColor();
setForegroundColor(fg);
setBackgroundColor(bg);
headline.setForegroundColor(fg);
headline.setBackgroundColor(bg);
2017-03-19 17:18:07 +01:00
}
// Text label
headline.setGeometry (FPoint(1, 1), FSize(8, 1));
headline.setEmphasis();
headline.setAlignment (fc::alignCenter);
headline << "Color";
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
ColorChooser::~ColorChooser()
{ }
//----------------------------------------------------------------------
void ColorChooser::onMouseDown (finalcut::FMouseEvent* ev)
2017-03-19 17:18:07 +01:00
{
int mouse_x = ev->getX();
int mouse_y = ev->getY();
if ( ev->getButton() == fc::MiddleButton )
2017-03-19 17:18:07 +01:00
return;
2019-08-25 22:16:00 +02:00
for (int c{0}; c < 16; c++)
2017-03-19 17:18:07 +01:00
{
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 )
2018-11-13 02:51:41 +01:00
bg_color = FColor(c);
else if ( ev->getButton() == fc::RightButton )
2018-11-13 02:51:41 +01:00
fg_color = FColor(c);
2017-03-19 17:18:07 +01:00
redraw();
emitCallback("clicked");
}
}
}
//----------------------------------------------------------------------
void ColorChooser::draw()
{
setColor();
drawBorder();
2017-03-19 17:18:07 +01:00
2019-08-25 22:16:00 +02:00
for (FColor c{0}; c < 16; c++)
2017-03-19 17:18:07 +01:00
{
print() << FPoint(2 + (c / 8) * 3, 3 + c % 8);
2017-03-19 17:18:07 +01:00
if ( c < 6 )
setColor (fc::LightGray, c);
2017-03-19 17:18:07 +01:00
else if ( c > 8 )
setColor (fc::DarkGray, c);
2017-03-19 17:18:07 +01:00
else
setColor (fc::White, c);
2017-03-19 17:18:07 +01:00
if ( c == bg_color )
{
print() << L' ' << wchar_t(fc::Times) << L' ';
2017-03-19 17:18:07 +01:00
}
else
print (" ");
}
}
//----------------------------------------------------------------------
void ColorChooser::drawBorder()
{
finalcut::drawBorder (this, FRect(FPoint(1, 2), FSize(8, 10)));
}
2017-03-19 17:18:07 +01:00
//----------------------------------------------------------------------
2018-11-13 02:51:41 +01:00
inline FColor ColorChooser::getForeground()
2017-03-19 17:18:07 +01:00
{
return fg_color;
}
//----------------------------------------------------------------------
2018-11-13 02:51:41 +01:00
inline FColor ColorChooser::getBackground()
2017-03-19 17:18:07 +01:00
{
return bg_color;
}
//----------------------------------------------------------------------
// class Brushes
//----------------------------------------------------------------------
class Brushes : public finalcut::FWidget
2017-03-19 17:18:07 +01:00
{
2017-09-11 03:06:02 +02:00
public:
// Constructor
explicit Brushes (finalcut::FWidget* = nullptr);
// Disable copy constructor
Brushes (const Brushes&) = delete;
2017-09-11 03:06:02 +02:00
// Destructor
~Brushes();
2017-03-19 17:18:07 +01:00
// Disable assignment operator (=)
Brushes& operator = (const Brushes&) = delete;
2017-09-11 03:06:02 +02:00
// Accessor
wchar_t getBrush();
2017-03-19 17:18:07 +01:00
2017-09-11 03:06:02 +02:00
// Mutators
2018-11-13 02:51:41 +01:00
void setForeground (FColor);
void setBackground (FColor);
2017-03-19 17:18:07 +01:00
2017-09-11 03:06:02 +02:00
private:
// Method
2019-08-06 23:45:28 +02:00
void draw() override;
void drawBorder() override;
2017-03-19 17:18:07 +01:00
2017-09-11 03:06:02 +02:00
// Event handler
2019-08-06 23:45:28 +02:00
void onMouseDown (finalcut::FMouseEvent*) override;
2017-03-19 17:18:07 +01:00
// Data members
wchar_t brush{L' '};
FColor fg_color{fc::White};
FColor bg_color{fc::Black};
finalcut::FLabel headline{this};
2017-03-19 17:18:07 +01:00
};
//----------------------------------------------------------------------
Brushes::Brushes (finalcut::FWidget* parent)
2017-03-19 17:18:07 +01:00
: FWidget(parent)
{
setSize (FSize(8, 4));
setFixedSize (FSize(8, 4));
2017-03-19 17:18:07 +01:00
unsetFocusable();
if ( parent )
{
2018-11-13 02:51:41 +01:00
FColor fg = parent->getForegroundColor();
FColor bg = parent->getBackgroundColor();
setForegroundColor(fg);
setBackgroundColor(bg);
headline.setForegroundColor(fg);
headline.setBackgroundColor(bg);
2017-03-19 17:18:07 +01:00
}
// Text label
headline.setGeometry(FPoint(1, 1), FSize(8, 1));
headline.setEmphasis();
headline.setAlignment (fc::alignCenter);
headline << "Brush";
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
Brushes::~Brushes()
{ }
//----------------------------------------------------------------------
void Brushes::draw()
{
2019-08-25 22:16:00 +02:00
int pos{};
2017-03-19 17:18:07 +01:00
setColor();
drawBorder();
print() << FPoint(2, 3)
<< FColorPair(fg_color, bg_color) << " "
<< finalcut::FString(3, fc::MediumShade);
2017-03-19 17:18:07 +01:00
if ( brush == L' ' )
pos = 0;
else
pos = 3;
setColor();
print() << FPoint(3 + pos, 2)
<< fc::BlackDownPointingTriangle
<< FPoint(3 + pos, 4)
<< fc::BlackUpPointingTriangle;
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
void Brushes::drawBorder()
{
finalcut::drawBorder (this, FRect(FPoint(1, 2), FSize(8, 3)));
}
2017-03-19 17:18:07 +01:00
//----------------------------------------------------------------------
void Brushes::onMouseDown (finalcut::FMouseEvent* ev)
2017-03-19 17:18:07 +01:00
{
int mouse_x = ev->getX();
int mouse_y = ev->getY();
if ( ev->getButton() != fc::LeftButton )
2017-03-19 17:18:07 +01:00
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 = fc::MediumShade;
2017-03-19 17:18:07 +01:00
redraw();
}
}
//----------------------------------------------------------------------
inline wchar_t Brushes::getBrush()
{
return brush;
}
//----------------------------------------------------------------------
2018-11-13 02:51:41 +01:00
inline void Brushes::setForeground (FColor color)
2017-03-19 17:18:07 +01:00
{
fg_color = color;
}
//----------------------------------------------------------------------
2018-11-13 02:51:41 +01:00
inline void Brushes::setBackground (FColor color)
2017-03-19 17:18:07 +01:00
{
bg_color = color;
}
//----------------------------------------------------------------------
// class MouseDraw
//----------------------------------------------------------------------
class MouseDraw : public finalcut::FDialog
2017-03-19 17:18:07 +01:00
{
2017-09-11 03:06:02 +02:00
public:
// Using-declaration
using FWidget::setGeometry;
// Constructor
explicit MouseDraw (finalcut::FWidget* = nullptr);
// Disable copy constructor
MouseDraw (const MouseDraw&) = delete;
2017-09-11 03:06:02 +02:00
// Destructor
~MouseDraw();
// Disable assignment operator (=)
MouseDraw& operator = (const MouseDraw&) = delete;
2017-09-11 03:06:02 +02:00
// Methods
void setGeometry (const FPoint&, const FSize&, bool = true) override;
2017-09-11 03:06:02 +02:00
// Event handlers
2019-08-06 23:45:28 +02:00
void onKeyPress (finalcut::FKeyEvent*) override;
void onClose (finalcut::FCloseEvent*) override;
2017-09-11 03:06:02 +02:00
private:
// Methods
2019-08-06 23:45:28 +02:00
void draw() override;
2017-09-11 03:06:02 +02:00
void drawBrush (int, int, bool = false);
void drawCanvas();
2019-08-06 23:45:28 +02:00
void adjustSize() override;
2017-09-11 03:06:02 +02:00
// Event handler
2019-08-06 23:45:28 +02:00
void onMouseDown (finalcut::FMouseEvent*) override;
void onMouseMove (finalcut::FMouseEvent*) override;
2017-09-11 03:06:02 +02:00
// Callback methods
2018-12-27 00:14:46 +01:00
void cb_colorChanged (finalcut::FWidget*, FDataPtr);
2017-09-11 03:06:02 +02:00
// Data members
term_area* canvas{nullptr};
ColorChooser c_chooser{this};
Brushes brush{this};
2017-03-19 17:18:07 +01:00
};
2019-09-08 02:04:24 +02:00
2017-03-19 17:18:07 +01:00
//----------------------------------------------------------------------
MouseDraw::MouseDraw (finalcut::FWidget* parent)
: finalcut::FDialog(parent)
2017-03-19 17:18:07 +01:00
{
setText ("Drawing with the mouse");
c_chooser.setPos (FPoint(1, 1));
c_chooser.addCallback
2017-03-19 17:18:07 +01:00
(
"clicked",
F_METHOD_CALLBACK (this, &MouseDraw::cb_colorChanged)
2017-03-19 17:18:07 +01:00
);
brush.setPos (FPoint(1, 12));
2017-03-19 17:18:07 +01:00
FSize no_shadow(0, 0);
finalcut::FRect scroll_geometry(0, 0, 1, 1);
2017-03-19 17:18:07 +01:00
createArea (scroll_geometry, no_shadow, canvas);
}
//----------------------------------------------------------------------
MouseDraw::~MouseDraw()
{ }
//----------------------------------------------------------------------
void MouseDraw::setGeometry ( const FPoint& p, const FSize& s, bool adjust)
2017-03-19 17:18:07 +01:00
{
finalcut::FDialog::setGeometry (p, s, adjust);
std::size_t w = s.getWidth();
std::size_t h = s.getHeight();
finalcut::FRect scroll_geometry (FPoint(0, 0), FSize(w - 11, h - 3));
FSize no_shadow(0, 0);
int old_w = canvas->width;
int old_h = canvas->height;
2017-03-19 17:18:07 +01:00
resizeArea (scroll_geometry, no_shadow, canvas);
if ( old_w != canvas->width || old_h != canvas->height )
{
setColor(getForegroundColor(), getBackgroundColor());
clearArea (canvas, ' ');
}
}
//----------------------------------------------------------------------
void MouseDraw::onKeyPress (finalcut::FKeyEvent* ev)
2017-03-19 17:18:07 +01:00
{
if ( ! ev )
return;
if ( ev->key() == 'q' )
{
close();
ev->accept();
}
else
finalcut::FDialog::onKeyPress(ev);
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
void MouseDraw::onClose (finalcut::FCloseEvent* ev)
2017-03-19 17:18:07 +01:00
{
finalcut::FApplication::closeConfirmationDialog (this, ev);
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
void MouseDraw::draw()
{
int y_max = int(getHeight());
finalcut::FDialog::draw();
2017-03-19 17:18:07 +01:00
setColor();
2017-11-03 05:04:27 +01:00
if ( isNewFont() )
{
2019-08-25 22:16:00 +02:00
for (int y{2}; y < y_max; y++)
2017-11-03 05:04:27 +01:00
{
print() << FPoint(10, y)
<< fc::NF_rev_border_line_right;
2017-11-03 05:04:27 +01:00
}
2017-03-19 17:18:07 +01:00
print() << FPoint(10, y_max)
<< fc::NF_rev_border_corner_lower_right;
2017-11-03 05:04:27 +01:00
}
else
2017-03-19 17:18:07 +01:00
{
print() << FPoint(10, 2)
<< fc::BoxDrawingsDownAndHorizontal;
2017-11-03 05:04:27 +01:00
2019-08-25 22:16:00 +02:00
for (int y{3}; y < y_max; y++)
2017-11-03 05:04:27 +01:00
{
print() << FPoint(10, y) << fc::BoxDrawingsVertical;
2017-11-03 05:04:27 +01:00
}
print() << FPoint(10, y_max)
<< fc::BoxDrawingsUpAndHorizontal;
2017-03-19 17:18:07 +01:00
}
drawCanvas();
}
//----------------------------------------------------------------------
void MouseDraw::drawBrush (int x, int y, bool swap_color)
{
int Cols = int(getWidth());
int Lines = int(getHeight());
2017-03-19 17:18:07 +01:00
if ( x > 10 && x < Cols && y > 2 && y < Lines )
{
if ( swap_color )
setColor (c_chooser.getBackground(), c_chooser.getForeground());
2017-03-19 17:18:07 +01:00
else
setColor (c_chooser.getForeground(), c_chooser.getBackground());
2017-03-19 17:18:07 +01:00
// 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());
2017-03-19 17:18:07 +01:00
// copy canvas to the dialog
drawCanvas();
}
}
//----------------------------------------------------------------------
void MouseDraw::drawCanvas()
{
if ( ! hasPrintArea() )
finalcut::FVTerm::getPrintArea();
2017-03-19 17:18:07 +01:00
if ( ! (hasPrintArea() && canvas) )
return;
auto printarea = getCurrentPrintArea();
int ax = 9 + getTermX() - printarea->offset_left
, ay = 1 + getTermY() - printarea->offset_top
, y_end = canvas->height
, x_end = canvas->width
, w_line_len = printarea->width + printarea->right_shadow;
2017-03-19 17:18:07 +01:00
2019-08-25 22:16:00 +02:00
for (int y{0}; y < y_end; y++) // line loop
2017-03-19 17:18:07 +01:00
{
2019-08-25 22:16:00 +02:00
finalcut::charData* canvaschar{}; // canvas character
finalcut::charData* winchar{}; // window character
2018-09-02 03:57:57 +02:00
canvaschar = &canvas->text[y * x_end];
winchar = &printarea->text[(ay + y) * w_line_len + ax];
std::memcpy ( winchar
, canvaschar
, sizeof(finalcut::charData) * unsigned(x_end) );
2017-03-19 17:18:07 +01:00
if ( int(printarea->changes[ay + y].xmin) > ax )
printarea->changes[ay + y].xmin = uInt(ax);
2017-03-19 17:18:07 +01:00
if ( int(printarea->changes[ay + y].xmax) < ax + x_end - 1 )
printarea->changes[ay + y].xmax = uInt(ax + x_end - 1);
2017-03-19 17:18:07 +01:00
}
printarea->has_changes = true;
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
void MouseDraw::adjustSize()
{
2019-08-25 22:16:00 +02:00
std::size_t w{60}, h{18};
int x = 1 + int((getParentWidget()->getWidth() - w) / 2);
int y = 1 + int((getParentWidget()->getHeight() - h) / 2);
setGeometry (FPoint(x, y), FSize(w, h), false);
finalcut::FDialog::adjustSize();
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
void MouseDraw::onMouseDown (finalcut::FMouseEvent* ev)
2017-03-19 17:18:07 +01:00
{
finalcut::FDialog::onMouseDown(ev);
2017-03-19 17:18:07 +01:00
if ( ev->getButton() != fc::LeftButton
&& ev->getButton() != fc::RightButton )
2017-03-19 17:18:07 +01:00
return;
drawBrush ( ev->getX()
, ev->getY()
, ev->getButton() == fc::RightButton );
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
void MouseDraw::onMouseMove (finalcut::FMouseEvent* ev)
2017-03-19 17:18:07 +01:00
{
FDialog::onMouseMove(ev);
if ( ev->getButton() != fc::LeftButton
&& ev->getButton() != fc::RightButton )
2017-03-19 17:18:07 +01:00
return;
drawBrush ( ev->getX()
, ev->getY()
, ev->getButton() == fc::RightButton);
2017-03-19 17:18:07 +01:00
}
//----------------------------------------------------------------------
2018-12-27 00:14:46 +01:00
void MouseDraw::cb_colorChanged (finalcut::FWidget*, FDataPtr)
2017-03-19 17:18:07 +01:00
{
brush.setForeground (c_chooser.getForeground());
brush.setBackground (c_chooser.getBackground());
brush.redraw();
2017-03-19 17:18:07 +01:00
}
2017-03-17 23:22:13 +01:00
//----------------------------------------------------------------------
// main part
//----------------------------------------------------------------------
int main (int argc, char* argv[])
{
// Create the application object
finalcut::FApplication app(argc, argv);
2017-03-17 23:22:13 +01:00
// Create a simple dialog box
2017-03-19 17:18:07 +01:00
MouseDraw mouse_draw(&app);
mouse_draw.setGeometry (FPoint(12, 4), FSize(60, 18));
2017-03-17 23:22:13 +01:00
// Set dialog object mouse_draw as main widget
2017-03-17 23:22:13 +01:00
app.setMainWidget(&mouse_draw);
// Show and start the application
2017-03-17 23:22:13 +01:00
mouse_draw.show();
return app.exec();
}