From dedc1f3410f27a2cad3863071e9ed9571417e246 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sat, 16 Nov 2019 15:16:44 +0100 Subject: [PATCH] New Widget class FSpinBox to provide spin boxes --- .gitignore | 1 + ChangeLog | 3 + README.md | 51 ++-- doc/class-diagram.txt | 51 ++-- doc/first-steps.md | 2 +- examples/7segment.cpp | 2 +- examples/Makefile.am | 2 + examples/background-color.cpp | 140 ++++++++++ examples/term-attributes.cpp | 2 +- examples/treeview.cpp | 2 +- src/Makefile.am | 6 +- src/fbutton.cpp | 21 -- src/flineedit.cpp | 47 ++-- src/flistbox.cpp | 25 -- src/fmenuitem.cpp | 74 ++---- src/fobject.cpp | 15 ++ src/fscrollbar.cpp | 4 +- src/fsize.cpp | 22 ++ src/fspinbox.cpp | 428 ++++++++++++++++++++++++++++++ src/fterm_functions.cpp | 36 +++ src/ftogglebutton.cpp | 24 +- src/fvterm.cpp | 41 +-- src/fwidget.cpp | 96 ++++--- src/fwidget_functions.cpp | 22 ++ src/fwidgetcolors.cpp | 4 + src/include/final/fdialog.h | 2 +- src/include/final/final.h | 1 + src/include/final/flineedit.h | 59 ++-- src/include/final/flistbox.h | 17 +- src/include/final/fobject.h | 1 + src/include/final/fsize.h | 7 + src/include/final/fspinbox.h | 219 +++++++++++++++ src/include/final/fterm.h | 1 + src/include/final/fwidget.h | 4 + src/include/final/fwidgetcolors.h | 2 + test/fsize-test.cpp | 33 +++ 36 files changed, 1173 insertions(+), 294 deletions(-) create mode 100644 examples/background-color.cpp create mode 100644 src/fspinbox.cpp create mode 100644 src/include/final/fspinbox.h diff --git a/.gitignore b/.gitignore index c1e67a39..e1d70755 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ examples/.libs/ examples/calculator examples/dialog examples/string-operations +examples/background-color examples/opti-move examples/termcap examples/hello diff --git a/ChangeLog b/ChangeLog index a5aa9352..89a3386d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2019-11-16 Markus Gans + * New Widget class FSpinBox to provide spin boxes + 2019-11-06 Markus Gans * Improved display of the NewFont midline diff --git a/README.md b/README.md index 6e7de034..ef17b9aa 100644 --- a/README.md +++ b/README.md @@ -178,36 +178,39 @@ Class digramm : ┌--------┤ FString │ │ ┌──────────────┐ : : └─────────┘ │ ┌────┤ FApplication │ : : *┌────────┐ │ │ └──────────────┘ - : ┌--------┤ FPoint │ │ │ ┌─────────┐ - : : └────────┘ │ ├────┤ FButton │ - : : *┌───────┐ │ │ └─────────┘ - : ┌--------┤ FRect │ │ │ ┌────────┐ - : : └───────┘ │ ├────┤ FLabel │ + : ┌--------┤ FPoint │ │ │ ┌────────┐ + : : └────────┘ │ ├────┤ FLabel │ : : *┌───────┐ │ │ └────────┘ - : ┌--------┤ FSize │ │ │ ┌───────────┐ + : ┌--------┤ FRect │ │ │ ┌───────────┐ : : └───────┘ │ ├────┤ FLineEdit │ - :1 :1 │ │ └───────────┘ - ┌─┴──┴──┐ │ │ ┌──────────────┐ ┌──────────────┐ - │ FTerm │ │ ├────┤ FButtonGroup │ ┌──┤ FRadioButton │ - └───┬───┘ ┌────────┐ │ │ └──────────────┘ │ └──────────────┘ - :1 │ FEvent │◄─────┘ │ ┌───────────────┐ │ ┌───────────┐ - ┌───┴────┐ └────┬───┘ ├────┤ FToggleButton │◄─┼──┤ FCheckBox │ - │ FVTerm │◄──┐ :1 │ └───────────────┘ │ └───────────┘ - └────────┘ │ ┌────┴────┐ │ ┌──────────────┐ │ ┌─────────┐ - ├────┤ FWidget │◄───────┼────┤ FProgressbar │ └──┤ FSwitch │ -┌─────────┐ │ └─────────┘ │ └──────────────┘ └─────────┘ -│ FObject │◄──┘ │ ┌────────────┐ -└─────────┘ ├────┤ FScrollbar │ + : : *┌───────┐ │ │ └───────────┘ + : ┌--------┤ FSize │ │ │ ┌──────────┐ + : : └───────┘ │ ├────┤ FSpinBox │ + :1 :1 │ │ └──────────┘ + ┌─┴──┴──┐ │ │ ┌─────────┐ + │ FTerm │ │ ├────┤ FButton │ + └───┬───┘ ┌────────┐ │ │ └─────────┘ + :1 │ FEvent │◄─────┘ │ ┌──────────────┐ ┌──────────────┐ + ┌───┴────┐ └────┬───┘ ├────┤ FButtonGroup │ ┌──┤ FRadioButton │ + │ FVTerm │◄──┐ :1 │ └──────────────┘ │ └──────────────┘ + └────────┘ │ ┌────┴────┐ │ ┌───────────────┐ │ ┌───────────┐ + ├────┤ FWidget │◄───────┼────┤ FToggleButton │◄─┼──┤ FCheckBox │ +┌─────────┐ │ └─────────┘ │ └───────────────┘ │ └───────────┘ +│ FObject │◄──┘ │ ┌──────────────┐ │ ┌─────────┐ +└─────────┘ ├────┤ FProgressbar │ └──┤ FSwitch │ + │ └──────────────┘ └─────────┘ + │ ┌────────────┐ + ├────┤ FScrollbar │ │ └────────────┘ │ ┌───────────┐ ├────┤ FTextView │ │ └───────────┘ - │ ┌──────────┐1 *┌──────────────┐ - ├────┤ FListBox ├-------┤ FListBoxItem │ - │ └──────────┘ └──────────────┘ - ┌─────────────┐1 │ 1┌───────────┐1 *┌───────────────┐ - │ FTermBuffer ├----------------------├────┤ FListView ├------┤ FListViewItem │ - └─────────────┘ │ └───────────┘ └───────────────┘ + ┌─────────────┐1 │ ┌──────────┐1 *┌──────────────┐ + │ FTermBuffer ├----------------------├────┤ FListBox ├-------┤ FListBoxItem │ + └─────────────┘ │ └──────────┘ └──────────────┘ + │ 1┌───────────┐1 *┌───────────────┐ + ├────┤ FListView ├------┤ FListViewItem │ + │ └───────────┘ └───────────────┘ │ ┌─────────────┐ ├────┤ FScrollView │ │ └─────────────┘ diff --git a/doc/class-diagram.txt b/doc/class-diagram.txt index 5157f210..a48e9d16 100644 --- a/doc/class-diagram.txt +++ b/doc/class-diagram.txt @@ -44,36 +44,39 @@ : ┌--------┤ FString │ │ ┌──────────────┐ : : └─────────┘ │ ┌────┤ FApplication │ : : *┌────────┐ │ │ └──────────────┘ - : ┌--------┤ FPoint │ │ │ ┌─────────┐ - : : └────────┘ │ ├────┤ FButton │ - : : *┌───────┐ │ │ └─────────┘ - : ┌--------┤ FRect │ │ │ ┌────────┐ - : : └───────┘ │ ├────┤ FLabel │ + : ┌--------┤ FPoint │ │ │ ┌────────┐ + : : └────────┘ │ ├────┤ FLabel │ : : *┌───────┐ │ │ └────────┘ - : ┌--------┤ FSize │ │ │ ┌───────────┐ + : ┌--------┤ FRect │ │ │ ┌───────────┐ : : └───────┘ │ ├────┤ FLineEdit │ - :1 :1 │ │ └───────────┘ - ┌─┴──┴──┐ │ │ ┌──────────────┐ ┌──────────────┐ - │ FTerm │ │ ├────┤ FButtonGroup │ ┌──┤ FRadioButton │ - └───┬───┘ ┌────────┐ │ │ └──────────────┘ │ └──────────────┘ - :1 │ FEvent │◄─────┘ │ ┌───────────────┐ │ ┌───────────┐ - ┌───┴────┐ └────┬───┘ ├────┤ FToggleButton │◄─┼──┤ FCheckBox │ - │ FVTerm │◄──┐ :1 │ └───────────────┘ │ └───────────┘ - └────────┘ │ ┌────┴────┐ │ ┌──────────────┐ │ ┌─────────┐ - ├────┤ FWidget │◄───────┼────┤ FProgressbar │ └──┤ FSwitch │ -┌─────────┐ │ └─────────┘ │ └──────────────┘ └─────────┘ -│ FObject │◄──┘ │ ┌────────────┐ -└─────────┘ ├────┤ FScrollbar │ + : : *┌───────┐ │ │ └───────────┘ + : ┌--------┤ FSize │ │ │ ┌──────────┐ + : : └───────┘ │ ├────┤ FSpinBox │ + :1 :1 │ │ └──────────┘ + ┌─┴──┴──┐ │ │ ┌─────────┐ + │ FTerm │ │ ├────┤ FButton │ + └───┬───┘ ┌────────┐ │ │ └─────────┘ + :1 │ FEvent │◄─────┘ │ ┌──────────────┐ ┌──────────────┐ + ┌───┴────┐ └────┬───┘ ├────┤ FButtonGroup │ ┌──┤ FRadioButton │ + │ FVTerm │◄──┐ :1 │ └──────────────┘ │ └──────────────┘ + └────────┘ │ ┌────┴────┐ │ ┌───────────────┐ │ ┌───────────┐ + ├────┤ FWidget │◄───────┼────┤ FToggleButton │◄─┼──┤ FCheckBox │ +┌─────────┐ │ └─────────┘ │ └───────────────┘ │ └───────────┘ +│ FObject │◄──┘ │ ┌──────────────┐ │ ┌─────────┐ +└─────────┘ ├────┤ FProgressbar │ └──┤ FSwitch │ + │ └──────────────┘ └─────────┘ + │ ┌────────────┐ + ├────┤ FScrollbar │ │ └────────────┘ │ ┌───────────┐ ├────┤ FTextView │ │ └───────────┘ - │ ┌──────────┐1 *┌──────────────┐ - ├────┤ FListBox ├-------┤ FListBoxItem │ - │ └──────────┘ └──────────────┘ - ┌─────────────┐1 │ 1┌───────────┐1 *┌───────────────┐ - │ FTermBuffer ├----------------------├────┤ FListView ├------┤ FListViewItem │ - └─────────────┘ │ └───────────┘ └───────────────┘ + ┌─────────────┐1 │ ┌──────────┐1 *┌──────────────┐ + │ FTermBuffer ├----------------------├────┤ FListBox ├-------┤ FListBoxItem │ + └─────────────┘ │ └──────────┘ └──────────────┘ + │ 1┌───────────┐1 *┌───────────────┐ + ├────┤ FListView ├------┤ FListViewItem │ + │ └───────────┘ └───────────────┘ │ ┌─────────────┐ ├────┤ FScrollView │ │ └─────────────┘ diff --git a/doc/first-steps.md b/doc/first-steps.md index e393ed41..3092699c 100644 --- a/doc/first-steps.md +++ b/doc/first-steps.md @@ -1,5 +1,5 @@ -First steps with the Final Cut widget toolkit +First steps with the FINAL CUT widget toolkit ============================================= Table of Contents diff --git a/examples/7segment.cpp b/examples/7segment.cpp index ecc1ff02..81791e2d 100644 --- a/examples/7segment.cpp +++ b/examples/7segment.cpp @@ -33,7 +33,7 @@ using finalcut::FSize; //---------------------------------------------------------------------- -// class TextWindow +// class SegmentView //---------------------------------------------------------------------- class SegmentView : public finalcut::FDialog diff --git a/examples/Makefile.am b/examples/Makefile.am index 2722af3b..a6358174 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -25,6 +25,7 @@ noinst_PROGRAMS = \ calculator \ watch \ term-attributes \ + background-color \ transparent \ keyboard \ mouse \ @@ -50,6 +51,7 @@ mandelbrot_SOURCES = mandelbrot.cpp calculator_SOURCES = calculator.cpp watch_SOURCES = watch.cpp term_attributes_SOURCES = term-attributes.cpp +background_color_SOURCES = background-color.cpp termcap_SOURCES = termcap.cpp transparent_SOURCES = transparent.cpp keyboard_SOURCES = keyboard.cpp diff --git a/examples/background-color.cpp b/examples/background-color.cpp new file mode 100644 index 00000000..ead1f9fa --- /dev/null +++ b/examples/background-color.cpp @@ -0,0 +1,140 @@ +/*********************************************************************** +* background-color.cpp - Sets the background color palette * +* * +* This file is part of the Final Cut widget toolkit * +* * +* Copyright 2019 Markus Gans * +* * +* 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 * +* . * +***********************************************************************/ + +#include +#include + +#include + +using finalcut::FPoint; +using finalcut::FSize; + + +//---------------------------------------------------------------------- +// class Background +//---------------------------------------------------------------------- + +class Background : public finalcut::FDialog +{ + public: + explicit Background (finalcut::FWidget* = nullptr); + + private: + // Callback method + void cb_changed (finalcut::FWidget*, FDataPtr); + + // Data members + finalcut::FSpinBox red{this}; + finalcut::FSpinBox green{this}; + finalcut::FSpinBox blue{this}; + finalcut::FButton quit{"&Quit", this}; +}; + +//---------------------------------------------------------------------- +Background::Background (finalcut::FWidget* parent) + : FDialog(parent) +{ + // Dialog settings + setText ("Background color palette"); + setGeometry (FPoint(25, 5), FSize(32, 9)); + + // Spin boxes + red.setGeometry (FPoint(2, 2), FSize(7, 1)); + red.setLabelOrientation (finalcut::FLineEdit::label_above); + red.setLabelText ("Red"); + red.setRange (0, 255); + red.setValue (0x80); + + green.setGeometry (FPoint(12, 2), FSize(7, 1)); + green.setLabelOrientation (finalcut::FLineEdit::label_above); + green.setLabelText ("Green"); + green.setRange (0, 255); + green.setValue (0xa4); + + blue.setGeometry (FPoint(22, 2), FSize(7, 1)); + blue.setLabelOrientation (finalcut::FLineEdit::label_above); + blue.setLabelText ("Blue"); + blue.setRange (0, 255); + blue.setValue (0xec); + + // Set the initial palette values + const auto& wc = getFWidgetColors(); + finalcut::FTerm::setPalette ( wc.term_bg + , red.getValue() + , green.getValue() + , blue.getValue() ); + + // Quit button + quit.setGeometry(FPoint(19, 5), FSize(10, 1)); + + // Add some function callbacks + quit.addCallback + ( + "clicked", + F_METHOD_CALLBACK (this, &finalcut::FApplication::cb_exitApp) + ); + + red.addCallback + ( + "changed", + F_METHOD_CALLBACK (this, &Background::cb_changed) + ); + + green.addCallback + ( + "changed", + F_METHOD_CALLBACK (this, &Background::cb_changed) + ); + + blue.addCallback + ( + "changed", + F_METHOD_CALLBACK (this, &Background::cb_changed) + ); +} + +//---------------------------------------------------------------------- +void Background::cb_changed (finalcut::FWidget*, FDataPtr) +{ + const auto& wc = getFWidgetColors(); + finalcut::FTerm::setPalette ( wc.term_bg + , red.getValue() + , green.getValue() + , blue.getValue() ); + redraw(); + updateTerminal(); +} + + +//---------------------------------------------------------------------- +// main part +//---------------------------------------------------------------------- + +int main (int argc, char* argv[]) +{ + finalcut::FApplication app(argc, argv); + Background dialog(&app); + app.setMainWidget(&dialog); + dialog.show(); + return app.exec(); +} + diff --git a/examples/term-attributes.cpp b/examples/term-attributes.cpp index 37566b6d..3aca493d 100644 --- a/examples/term-attributes.cpp +++ b/examples/term-attributes.cpp @@ -253,7 +253,7 @@ void AttribDemo::printColorLine() { auto parent = static_cast(getParent()); - for (FColor color{0}; color < colors; color++) + for (FColor color{0}; color < uInt(colors); color++) { print() << FColorPair(color, parent->bgcolor) << " # "; } diff --git a/examples/treeview.cpp b/examples/treeview.cpp index c2c0bdef..fb7a4917 100644 --- a/examples/treeview.cpp +++ b/examples/treeview.cpp @@ -353,7 +353,7 @@ Treeview::Treeview (finalcut::FWidget* parent) Quit.setGeometry(FPoint(24, 16), FSize(10, 1)); Quit.setText (L"&Quit"); - // Add some function callbacks + // Callback function Quit.addCallback ( "clicked", diff --git a/src/Makefile.am b/src/Makefile.am index 5b65d121..b2c716df 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,7 +44,7 @@ libfinal_la_SOURCES = \ ffiledialog.cpp \ fkey_map.cpp \ fcharmap.cpp \ - ftextview.cpp \ + fspinbox.cpp \ fstartoptions.cpp \ fstatusbar.cpp \ ftermcap.cpp \ @@ -58,6 +58,7 @@ libfinal_la_SOURCES = \ ftermios.cpp \ fterm.cpp \ fterm_functions.cpp \ + ftextview.cpp \ fvterm.cpp \ fevent.cpp \ foptiattr.cpp \ @@ -117,6 +118,7 @@ finalcutinclude_HEADERS = \ include/final/frect.h \ include/final/fscrollbar.h \ include/final/fscrollview.h \ + include/final/fspinbox.h \ include/final/fstartoptions.h \ include/final/fstatusbar.h \ include/final/fstring.h \ @@ -133,8 +135,8 @@ finalcutinclude_HEADERS = \ include/final/ftermios.h \ include/final/fterm.h \ include/final/ftermdata.h \ - include/final/fvterm.h \ include/final/ftextview.h \ + include/final/fvterm.h \ include/final/ftogglebutton.h \ include/final/fcolorpalette.h \ include/final/fwidgetcolors.h \ diff --git a/src/fbutton.cpp b/src/fbutton.cpp index 0f215211..8a443cad 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -151,27 +151,6 @@ bool FButton::setEnable (bool enable) bool FButton::setFocus (bool enable) { FWidget::setFocus(enable); - - if ( enable ) - { - if ( isEnabled() ) - { - if ( getStatusBar() ) - { - const auto& msg = getStatusbarMessage(); - const auto& curMsg = getStatusBar()->getMessage(); - - if ( curMsg != msg ) - getStatusBar()->setMessage(msg); - } - } - } - else - { - if ( isEnabled() && getStatusBar() ) - getStatusBar()->clearMessage(); - } - updateButtonColor(); return enable; } diff --git a/src/flineedit.cpp b/src/flineedit.cpp index 8b1930c0..b9208e66 100644 --- a/src/flineedit.cpp +++ b/src/flineedit.cpp @@ -40,7 +40,7 @@ namespace finalcut // constructor and destructor //---------------------------------------------------------------------- -FLineEdit::FLineEdit(FWidget* parent) +FLineEdit::FLineEdit (FWidget* parent) : FWidget(parent) , label{new FLabel("", parent)} { @@ -196,35 +196,21 @@ bool FLineEdit::setEnable (bool enable) //---------------------------------------------------------------------- bool FLineEdit::setFocus (bool enable) { - const auto& wc = getFWidgetColors(); FWidget::setFocus(enable); - if ( enable ) + if ( isEnabled() ) { - if ( isEnabled() ) + const auto& wc = getFWidgetColors(); + + if ( enable ) { setForegroundColor (wc.inputfield_active_focus_fg); setBackgroundColor (wc.inputfield_active_focus_bg); - - if ( getStatusBar() ) - { - const auto& msg = getStatusbarMessage(); - const auto& curMsg = getStatusBar()->getMessage(); - - if ( curMsg != msg ) - getStatusBar()->setMessage(msg); - } } - } - else - { - if ( isEnabled() ) + else { setForegroundColor (wc.inputfield_active_fg); setBackgroundColor (wc.inputfield_active_bg); - - if ( getStatusBar() ) - getStatusBar()->clearMessage(); } } @@ -534,6 +520,19 @@ void FLineEdit::onMouseMove (FMouseEvent* ev) } } +//---------------------------------------------------------------------- +void FLineEdit::onWheel (FWheelEvent* ev) +{ + // Sends the wheel event to the parent widget + + auto widget = getParentWidget(); + + if ( widget ) + { + FApplication::sendEvent(widget, ev); + } +} + //---------------------------------------------------------------------- void FLineEdit::onTimer (FTimerEvent*) { @@ -652,6 +651,10 @@ void FLineEdit::onFocusOut (FFocusEvent*) void FLineEdit::adjustLabel() { auto label_width = getColumnWidth(label_text); + auto w = label_associated_widget; + + if ( ! w ) + return; if ( hasHotkey() ) label_width--; @@ -662,12 +665,12 @@ void FLineEdit::adjustLabel() switch ( label_orientation ) { case label_above: - label->setGeometry ( FPoint(getX(), getY() - 1) + label->setGeometry ( FPoint(w->getX(), w->getY() - 1) , FSize(label_width, 1) ); break; case label_left: - label->setGeometry ( FPoint(getX() - int(label_width) - 1, getY()) + label->setGeometry ( FPoint(w->getX() - int(label_width) - 1, w->getY()) , FSize(label_width, 1) ); break; } diff --git a/src/flistbox.cpp b/src/flistbox.cpp index d4445672..420c60ef 100644 --- a/src/flistbox.cpp +++ b/src/flistbox.cpp @@ -180,31 +180,6 @@ void FListBox::setGeometry ( const FPoint& pos, const FSize& size } } -//---------------------------------------------------------------------- -bool FListBox::setFocus (bool enable) -{ - FWidget::setFocus(enable); - - if ( enable ) - { - if ( getStatusBar() ) - { - const auto& msg = getStatusbarMessage(); - const auto& curMsg = getStatusBar()->getMessage(); - - if ( curMsg != msg ) - getStatusBar()->setMessage(msg); - } - } - else - { - if ( getStatusBar() ) - getStatusBar()->clearMessage(); - } - - return enable; -} - //---------------------------------------------------------------------- void FListBox::setText (const FString& txt) { diff --git a/src/fmenuitem.cpp b/src/fmenuitem.cpp index 1e6750d8..8ad5608a 100644 --- a/src/fmenuitem.cpp +++ b/src/fmenuitem.cpp @@ -112,56 +112,36 @@ bool FMenuItem::setFocus (bool enable) { FWidget::setFocus(enable); - if ( enable ) + if ( ! enable || ! isEnabled() || selected ) + return enable; + + auto menu_list = getFMenuList(*getSuperMenu()); + setSelected(); + + if ( menu_list ) { - if ( isEnabled() ) - { - if ( ! selected ) - { - auto menu_list = getFMenuList(*getSuperMenu()); - setSelected(); - - if ( menu_list ) - { - menu_list->unselectItem(); - menu_list->setSelectedItem(this); - } - - if ( getStatusBar() ) - getStatusBar()->drawMessage(); - - auto parent = getSuperMenu(); - - if ( isMenuBar(parent) ) - { - auto menubar_ptr = static_cast(parent); - - if ( menubar_ptr ) - menubar_ptr->redraw(); - } - else if ( isMenu(parent) ) - { - auto menu_ptr = static_cast(parent); - - if ( menu_ptr ) - menu_ptr->redraw(); - } - } - - if ( getStatusBar() ) - { - const auto& msg = getStatusbarMessage(); - const auto& curMsg = getStatusBar()->getMessage(); - - if ( curMsg != msg ) - getStatusBar()->setMessage(msg); - } - } + menu_list->unselectItem(); + menu_list->setSelectedItem(this); } - else + + if ( getStatusBar() ) + getStatusBar()->drawMessage(); + + auto parent = getSuperMenu(); + + if ( isMenuBar(parent) ) { - if ( isEnabled() && getStatusBar() ) - getStatusBar()->clearMessage(); + auto menubar_ptr = static_cast(parent); + + if ( menubar_ptr ) + menubar_ptr->redraw(); + } + else if ( isMenu(parent) ) + { + auto menu_ptr = static_cast(parent); + + if ( menu_ptr ) + menu_ptr->redraw(); } return enable; diff --git a/src/fobject.cpp b/src/fobject.cpp index 3ea55507..7ef0be95 100644 --- a/src/fobject.cpp +++ b/src/fobject.cpp @@ -174,6 +174,21 @@ void FObject::delChild (FObject* obj) } } +//---------------------------------------------------------------------- +void FObject::setParent (FObject* parent) +{ + // Sets a new parent object + + if ( ! parent ) + return; + + removeParent(); + + parent_obj = parent; + has_parent = true; + parent->children_list.push_back(this); +} + //---------------------------------------------------------------------- bool FObject::event (FEvent* ev) { diff --git a/src/fscrollbar.cpp b/src/fscrollbar.cpp index 867f760a..a6692734 100644 --- a/src/fscrollbar.cpp +++ b/src/fscrollbar.cpp @@ -273,7 +273,7 @@ void FScrollbar::onMouseDown (FMouseEvent* ev) return; } - // Process left button + // Process left mouse button scroll_type = getClickedScrollType(mouse_x, mouse_y); if ( scroll_type == FScrollbar::noScroll ) @@ -341,7 +341,7 @@ void FScrollbar::onMouseMove (FMouseEvent* ev) return; } - // Process left button + // Process left mouse button int new_scroll_type = getClickedScrollType(mouse_x, mouse_y); if ( scroll_type == FScrollbar::scrollJump ) diff --git a/src/fsize.cpp b/src/fsize.cpp index 2690ea1e..94e01e28 100644 --- a/src/fsize.cpp +++ b/src/fsize.cpp @@ -21,6 +21,8 @@ ***********************************************************************/ #include + +#include "final/fpoint.h" #include "final/fsize.h" namespace finalcut @@ -100,6 +102,26 @@ bool FSize::isEmpty() const return width == 0 && height == 0; } +//---------------------------------------------------------------------- +void FSize::scaleBy (int dx, int dy) +{ + if ( dx < 0 ) + width -= std::size_t(-dx); + else + width += std::size_t(dx); + + if ( dx < 0 ) + height -= std::size_t(-dy); + else + height += std::size_t(dy); +} + +//---------------------------------------------------------------------- +void FSize::scaleBy (const FPoint& d) +{ + scaleBy (d.getX(), d.getY()); +} + //---------------------------------------------------------------------- std::ostream& operator << (std::ostream& outstr, const FSize& s) { diff --git a/src/fspinbox.cpp b/src/fspinbox.cpp new file mode 100644 index 00000000..d8f4acf4 --- /dev/null +++ b/src/fspinbox.cpp @@ -0,0 +1,428 @@ +/*********************************************************************** +* fspinbox.cpp - Widget FSpinBox * +* * +* This file is part of the Final Cut widget toolkit * +* * +* Copyright 2019 Markus Gans * +* * +* 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 * +* . * +***********************************************************************/ + +#include + +#include "final/fcolorpair.h" +#include "final/fevent.h" +#include "final/flabel.h" +#include "final/flineedit.h" +#include "final/fpoint.h" +#include "final/fsize.h" +#include "final/fspinbox.h" +#include "final/fstatusbar.h" +#include "final/fwidgetcolors.h" + +namespace finalcut +{ + +//---------------------------------------------------------------------- +// class FSpinBox +//---------------------------------------------------------------------- + +// constructors and destructor +//---------------------------------------------------------------------- +FSpinBox::FSpinBox (FWidget* parent) + : FWidget(parent) +{ + init(); +} + +//---------------------------------------------------------------------- +FSpinBox::~FSpinBox() // destructor +{ } + + +// public methods of FSpinBox +//---------------------------------------------------------------------- +void FSpinBox::setGeometry ( const FPoint& pos, const FSize& size + , bool adjust ) +{ + FWidget::setGeometry (pos, size, adjust); + FSize input_field_size(size); + input_field_size.scaleBy(-2, 0); + input_field.setGeometry (FPoint(1, 1), input_field_size, adjust); +} + +//---------------------------------------------------------------------- +bool FSpinBox::setEnable (bool enable) +{ + FWidget::setEnable(enable); + input_field.setEnable(enable); + return enable; +} + +//---------------------------------------------------------------------- +bool FSpinBox::setFocus (bool enable) +{ + FWidget::setFocus(enable); + input_field.setFocus(enable); + return enable; +} + +//---------------------------------------------------------------------- +bool FSpinBox::setShadow (bool enable) +{ + if ( enable + && getEncoding() != fc::VT100 + && getEncoding() != fc::ASCII ) + { + setFlags().shadow = true; + setShadowSize(FSize(1, 1)); + } + else + { + setFlags().shadow = false; + setShadowSize(FSize(0, 0)); + } + + return getFlags().shadow; +} +//---------------------------------------------------------------------- +void FSpinBox::setValue (sInt64 n) +{ + if ( n > max ) + value = max; + else if ( n < min ) + value = min; + else + value = n; + + updateInputField(); +} + +//---------------------------------------------------------------------- +void FSpinBox::setMinValue (sInt64 n) +{ + if ( n <= max ) + value = min = n; +} + +//---------------------------------------------------------------------- +void FSpinBox::setMaxValue (sInt64 n) +{ + if ( n >= min ) + max = n; +} + +//---------------------------------------------------------------------- +void FSpinBox::setRange (sInt64 m, sInt64 n) +{ + if ( m <= n ) + { + value = min = m; + max = n; + } +} + +//---------------------------------------------------------------------- +void FSpinBox::setPrefix (const FString& text) +{ + pfix = text; + updateInputField(); +} + +//---------------------------------------------------------------------- +void FSpinBox::setSuffix (const FString& text) +{ + sfix = text; + updateInputField(); +} + +//---------------------------------------------------------------------- +void FSpinBox::draw() +{ + const auto& wc = getFWidgetColors(); + + FColorPair inc_button_color = [&] () -> FColorPair + { + if ( value == max ) + return FColorPair ( wc.scrollbar_button_inactive_fg + , wc.scrollbar_button_inactive_bg ); + else + return FColorPair ( wc.scrollbar_button_fg + , wc.scrollbar_button_bg ); + }(); + + FColorPair dec_button_color = [&] () -> FColorPair + { + if ( value == min ) + return FColorPair ( wc.scrollbar_button_inactive_fg + , wc.scrollbar_button_inactive_bg ); + else + return FColorPair ( wc.scrollbar_button_fg + , wc.scrollbar_button_bg ); + }(); + + print() << FPoint(getWidth() - 1, 1) + << dec_button_color + << fc::BlackDownPointingTriangle // ▼ + << inc_button_color + << fc::BlackUpPointingTriangle; // ▲ + + if ( getFlags().shadow ) + drawShadow(this); +} + +//---------------------------------------------------------------------- +void FSpinBox::onKeyPress (FKeyEvent* ev) +{ + if ( ! isEnabled() ) + return; + + FKey key = ev->key(); + + switch ( key ) + { + case fc::Fkey_tab: + focusNextChild(); + break; + + case fc::Fkey_btab: + focusPrevChild(); + break; + + case fc::Fkey_up: + increaseValue(); + ev->accept(); + break; + + case fc::Fkey_down: + decreaseValue(); + ev->accept(); + break; + + default: + break; + } + + if ( ev->isAccepted() ) + updateInputField(); +} + +//---------------------------------------------------------------------- +void FSpinBox::onMouseDown (FMouseEvent* ev) +{ + if ( ev->getButton() != fc::LeftButton + && ev->getButton() != fc::MiddleButton ) + return; + + forceFocus(); + + if ( min == max ) + return; + + int mouse_x = ev->getX(); + int mouse_y = ev->getY(); + + if ( mouse_x == int(getWidth()) - 1 && mouse_y == 1 ) + { + spining_state = FSpinBox::spinDown; + decreaseValue(); + updateInputField(); + threshold_reached = false; + addTimer(threshold_time); + } + else if ( mouse_x == int(getWidth()) && mouse_y == 1 ) + { + spining_state = FSpinBox::spinUp; + increaseValue(); + updateInputField(); + threshold_reached = false; + addTimer(threshold_time); + } + else + delOwnTimer(); +} + +//---------------------------------------------------------------------- +void FSpinBox::onMouseUp (FMouseEvent*) +{ + delOwnTimer(); + spining_state = FSpinBox::noSpin; +} + +//---------------------------------------------------------------------- +void FSpinBox::onWheel (FWheelEvent* ev) +{ + int wheel = ev->getWheel(); + + delOwnTimer(); + forceFocus(); + spining_state = FSpinBox::noSpin; + + switch ( wheel ) + { + case fc::WheelUp: + increaseValue(); + updateInputField(); + break; + + case fc::WheelDown: + decreaseValue(); + updateInputField(); + break; + + default: + break; + } +} + +//---------------------------------------------------------------------- +void FSpinBox::onTimer (FTimerEvent*) +{ + if ( ! threshold_reached ) + { + threshold_reached = true; + delOwnTimer(); + addTimer(repeat_time); + } + + switch ( spining_state ) + { + case FSpinBox::spinUp: + increaseValue(); + updateInputField(); + break; + + case FSpinBox::spinDown: + decreaseValue(); + updateInputField(); + break; + + default: + break; + } +} + +// private methods of FSpinBox +//---------------------------------------------------------------------- +void FSpinBox::init() +{ + setShadow(); + auto parent_widget = getParentWidget(); + FLabel* label = input_field.getLabelObject(); + label->setParent(getParent()); + label->setForegroundColor (parent_widget->getForegroundColor()); + label->setBackgroundColor (parent_widget->getBackgroundColor()); + input_field.setLabelAssociatedWidget(this); + input_field.setInputFilter("[-[:digit:]]"); // Only numbers + input_field.unsetShadow(); + input_field << value; + input_field.addCallback + ( + "changed", + F_METHOD_CALLBACK (this, &FSpinBox::cb_inputFieldChange) + ); +} + +//---------------------------------------------------------------------- +inline void FSpinBox::updateInputField() +{ + input_field.clear(); + input_field << pfix << value << sfix; + input_field.redraw(); + redraw(); + updateTerminal(); +} + +//---------------------------------------------------------------------- +inline void FSpinBox::increaseValue() +{ + if ( value < max ) + { + value++; + processChanged(); + } + else + delOwnTimer(); +} + +//---------------------------------------------------------------------- +inline void FSpinBox::decreaseValue() +{ + if ( value > min ) + { + value--; + processChanged(); + } + else + delOwnTimer(); +} + +//---------------------------------------------------------------------- +void FSpinBox::processChanged() +{ + emitCallback("changed"); +} + +//---------------------------------------------------------------------- +void FSpinBox::forceFocus() +{ + if ( hasFocus() ) + return; + + auto focused_widget = getFocusWidget(); + setFocus(); + + if ( focused_widget ) + focused_widget->redraw(); + + redraw(); + + if ( getStatusBar() ) + getStatusBar()->drawMessage(); +} + +//---------------------------------------------------------------------- +void FSpinBox::cb_inputFieldChange (finalcut::FWidget* w, FDataPtr) +{ + auto lineedit = static_cast(w); + + if ( lineedit->getText().isEmpty() ) + value = 0; + else + { + std::wregex regex(L"[-]?[[:xdigit:]]+"); + std::wsmatch match; + std::wstring text = lineedit->getText().wc_str(); + + if ( std::regex_search(text, match, regex) ) + { + FString tmp(match[0]); + value = tmp.toLong(); + } + else + value = 0; + } + + if ( value > max ) + value = max; + else if ( value < min ) + value = min; + + updateInputField(); + processChanged(); +} + +} // namespace finalcut + diff --git a/src/fterm_functions.cpp b/src/fterm_functions.cpp index b4b963f9..3d6b6027 100644 --- a/src/fterm_functions.cpp +++ b/src/fterm_functions.cpp @@ -150,6 +150,30 @@ const wchar_t ambiguous_width_list[] = #endif }; +const wchar_t reverse_newfont_list[] = +{ + fc::NF_rev_left_arrow2, + fc::NF_rev_right_arrow2, + fc::NF_rev_border_corner_upper_right, + fc::NF_rev_border_line_right, + fc::NF_rev_border_line_vertical_left, + fc::NF_rev_border_corner_lower_right, + fc::NF_rev_up_arrow2, + fc::NF_rev_down_arrow2, + fc::NF_rev_up_arrow1, + fc::NF_rev_down_arrow1, + fc::NF_rev_left_arrow1, + fc::NF_rev_right_arrow1, + fc::NF_rev_menu_button1, + fc::NF_rev_menu_button2, + fc::NF_rev_up_pointing_triangle1, + fc::NF_rev_down_pointing_triangle1, + fc::NF_rev_up_pointing_triangle2, + fc::NF_rev_down_pointing_triangle2, + fc::NF_rev_menu_button3, + fc::NF_rev_border_line_right_and_left +}; + // FTerm non-member functions //---------------------------------------------------------------------- @@ -182,6 +206,18 @@ inline bool hasAmbiguousWidth (wchar_t wchar) return false; } +//---------------------------------------------------------------------- +bool isReverseNewFontchar (wchar_t wchar) +{ + const auto& begin = std::begin(reverse_newfont_list); + const auto& end = std::end(reverse_newfont_list); + + if ( std::find(begin, end, wchar) != end ) // found + return true; + + return false; +} + //---------------------------------------------------------------------- wchar_t cp437_to_unicode (uChar c) { diff --git a/src/ftogglebutton.cpp b/src/ftogglebutton.cpp index 5ed44a1f..ce6b21a6 100644 --- a/src/ftogglebutton.cpp +++ b/src/ftogglebutton.cpp @@ -143,37 +143,23 @@ bool FToggleButton::setEnable (bool enable) bool FToggleButton::setFocus (bool enable) { FWidget::setFocus(enable); - const auto& wc = getFWidgetColors(); - if ( enable ) + if ( isEnabled() ) { - if ( isEnabled() ) + const auto& wc = getFWidgetColors(); + + if ( enable ) { if ( isRadioButton() ) focus_inside_group = false; setForegroundColor (wc.toggle_button_active_focus_fg); setBackgroundColor (wc.toggle_button_active_focus_bg); - - if ( getStatusBar() ) - { - const auto& msg = getStatusbarMessage(); - const auto& curMsg = getStatusBar()->getMessage(); - - if ( curMsg != msg ) - getStatusBar()->setMessage(msg); - } } - } - else - { - if ( isEnabled() ) + else { setForegroundColor (wc.toggle_button_active_fg); setBackgroundColor (wc.toggle_button_active_bg); - - if ( getStatusBar() ) - getStatusBar()->clearMessage(); } } diff --git a/src/fvterm.cpp b/src/fvterm.cpp index 54365597..fc481257 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -2864,41 +2864,16 @@ inline void FVTerm::markAsPrinted (uInt from, uInt to, uInt line) inline void FVTerm::newFontChanges (FChar*& next_char) { // NewFont special cases - if ( isNewFont() ) - { - switch ( next_char->ch ) - { - case fc::LowerHalfBlock: - next_char->ch = fc::UpperHalfBlock; - // fall through - case fc::NF_rev_left_arrow2: - case fc::NF_rev_right_arrow2: - case fc::NF_rev_border_corner_upper_right: - case fc::NF_rev_border_line_right: - case fc::NF_rev_border_line_vertical_left: - case fc::NF_rev_border_corner_lower_right: - case fc::NF_rev_up_arrow2: - case fc::NF_rev_down_arrow2: - case fc::NF_rev_up_arrow1: - case fc::NF_rev_down_arrow1: - case fc::NF_rev_left_arrow1: - case fc::NF_rev_right_arrow1: - case fc::NF_rev_menu_button1: - case fc::NF_rev_menu_button2: - case fc::NF_rev_up_pointing_triangle1: - case fc::NF_rev_down_pointing_triangle1: - case fc::NF_rev_up_pointing_triangle2: - case fc::NF_rev_down_pointing_triangle2: - case fc::NF_rev_menu_button3: - case fc::NF_rev_border_line_right_and_left: - // Show in reverse video - next_char->attr.bit.reverse = true; - break; + if ( ! isNewFont() ) + return; - default: - break; - } + if ( next_char->ch == fc::LowerHalfBlock ) + { + next_char->ch = fc::UpperHalfBlock; + next_char->attr.bit.reverse = true; } + else if ( isReverseNewFontchar(next_char->ch) ) + next_char->attr.bit.reverse = true; // Show in reverse video } //---------------------------------------------------------------------- diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 4ea1432f..d942695f 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -284,23 +284,11 @@ bool FWidget::setFocus (bool enable) FWidget::setFocusWidget(this); } - auto window = FWindow::getWindowWidget(this); - - // set window focus - if ( enable && window ) - { - if ( ! window->isWindowActive() ) - { - bool has_raised = window->raiseWindow(); - FWindow::setActiveWindow(window); - - if ( has_raised && window->isVisible() && window->isShown() ) - window->redraw(); - } - - window->setWindowFocusWidget(this); - } + // Activates the window with the focused widget + setWindowFocus (enable); + // Set status bar text for widget focus + setStatusbarText (enable); return (flags.focus = enable); } @@ -1794,17 +1782,7 @@ inline void FWidget::insufficientSpaceAdjust() //---------------------------------------------------------------------- void FWidget::KeyPressEvent (FKeyEvent* kev) { - bool accpt_focus{false}; - - if ( kev->key() == fc::Fkey_tab ) - accpt_focus = focusNextChild(); - else if ( kev->key() == fc::Fkey_btab ) - accpt_focus = focusPrevChild(); - - if ( accpt_focus ) - return; - - FWidget* widget(this); + FWidget* widget(this); while ( widget ) { @@ -1812,15 +1790,20 @@ void FWidget::KeyPressEvent (FKeyEvent* kev) if ( ! kev->isAccepted() ) { - if ( kev->key() == fc::Fkey_right - || kev->key() == fc::Fkey_down ) - accpt_focus = focusNextChild(); - else if ( kev->key() == fc::Fkey_left - || kev->key() == fc::Fkey_up ) - accpt_focus = focusPrevChild(); + FKey key = kev->key(); - if ( accpt_focus ) + if ( [&] () -> bool + { + if ( isFocusNextKey(key) ) + return focusNextChild(); + else if ( isFocusPrevKey(key) ) + return focusPrevChild(); + + return false; + }() ) + { return; + } } if ( kev->isAccepted() || widget->isRootWidget() ) @@ -1846,6 +1829,31 @@ void FWidget::KeyDownEvent (FKeyEvent* kev) } } +//---------------------------------------------------------------------- +void FWidget::setWindowFocus (bool enable) +{ + // set the window focus + + if ( ! enable ) + return; + + auto window = FWindow::getWindowWidget(this); + + if ( ! window ) + return; + + if ( ! window->isWindowActive() ) + { + bool has_raised = window->raiseWindow(); + FWindow::setActiveWindow(window); + + if ( has_raised && window->isVisible() && window->isShown() ) + window->redraw(); + } + + window->setWindowFocusWidget(this); +} + //---------------------------------------------------------------------- FWidget::FCallbackPtr FWidget::getCallbackPtr (FCallback cb_function) { @@ -1954,6 +1962,26 @@ void FWidget::setColorTheme() wcolors.set16ColorTheme(); } +//---------------------------------------------------------------------- +void FWidget::setStatusbarText (bool enable) +{ + if ( ! isEnabled() || ! getStatusBar() ) + return; + + if ( enable ) + { + const auto& msg = getStatusbarMessage(); + const auto& curMsg = getStatusBar()->getMessage(); + + if ( curMsg != msg ) + getStatusBar()->setMessage(msg); + } + else + { + getStatusBar()->clearMessage(); + } +} + // non-member functions //---------------------------------------------------------------------- diff --git a/src/fwidget_functions.cpp b/src/fwidget_functions.cpp index 6e15883a..fe3ed332 100644 --- a/src/fwidget_functions.cpp +++ b/src/fwidget_functions.cpp @@ -27,6 +27,28 @@ namespace finalcut { // FWidget non-member functions +//---------------------------------------------------------------------- +bool isFocusNextKey (FKey key) +{ + if ( key == fc::Fkey_tab + || key == fc::Fkey_right + || key == fc::Fkey_down ) + return true; + + return false; +} + +//---------------------------------------------------------------------- +bool isFocusPrevKey (FKey key) +{ + if ( key == fc::Fkey_btab + || key == fc::Fkey_left + || key == fc::Fkey_up ) + return true; + + return false; +} + //---------------------------------------------------------------------- FKey getHotkey (const FString& text) { diff --git a/src/fwidgetcolors.cpp b/src/fwidgetcolors.cpp index b473aa86..6c3d3474 100644 --- a/src/fwidgetcolors.cpp +++ b/src/fwidgetcolors.cpp @@ -117,6 +117,8 @@ void FWidgetColors::set8ColorTheme() scrollbar_bg = fc::LightGray; scrollbar_button_fg = fc::Black; scrollbar_button_bg = fc::LightGray; + scrollbar_button_inactive_fg = fc::Cyan; + scrollbar_button_inactive_bg = fc::LightGray; progressbar_fg = fc::Blue; progressbar_bg = fc::LightGray; } @@ -206,6 +208,8 @@ void FWidgetColors::set16ColorTheme() scrollbar_bg = fc::LightBlue; scrollbar_button_fg = fc::Black; scrollbar_button_bg = fc::LightGray; + scrollbar_button_inactive_fg = fc::DarkGray; + scrollbar_button_inactive_bg = fc::LightGray; progressbar_fg = fc::DarkGray; progressbar_bg = fc::LightBlue; diff --git a/src/include/final/fdialog.h b/src/include/final/fdialog.h index b7183b79..818428ad 100644 --- a/src/include/final/fdialog.h +++ b/src/include/final/fdialog.h @@ -72,7 +72,7 @@ class FToolTip; class FDialog : public FWindow { public: - // Using-declaration + // Using-declaration using FWindow::setResizeable; // Enumeration diff --git a/src/include/final/final.h b/src/include/final/final.h index 1755e4f3..9f26cf3e 100644 --- a/src/include/final/final.h +++ b/src/include/final/final.h @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include diff --git a/src/include/final/flineedit.h b/src/include/final/flineedit.h index e7b6a4e2..83b81608 100644 --- a/src/include/final/flineedit.h +++ b/src/include/final/flineedit.h @@ -70,6 +70,9 @@ class FLabel; class FLineEdit : public FWidget { public: + // Using-declaration + using FWidget::setGeometry; + // Enumerations enum label_o { @@ -83,9 +86,6 @@ class FLineEdit : public FWidget password = 1 }; - // Using-declaration - using FWidget::setGeometry; - // Constructor explicit FLineEdit (FWidget* = nullptr); explicit FLineEdit (const FString&, FWidget* = nullptr); @@ -118,7 +118,8 @@ class FLineEdit : public FWidget FString getText() const; std::size_t getMaxLength() const; std::size_t getCursorPosition() const; - int getLabelOrientation(); + FLabel* getLabelObject() const; + label_o getLabelOrientation(); // Mutators void setText (const FString&); @@ -129,6 +130,7 @@ class FLineEdit : public FWidget void setLabelText (const FString&); void setInputType (const inputType); void setLabelOrientation (const label_o); + void setLabelAssociatedWidget (FWidget*); void setGeometry ( const FPoint&, const FSize& , bool = true ) override; bool setEnable(bool) override; @@ -154,6 +156,7 @@ class FLineEdit : public FWidget void onMouseDown (FMouseEvent*) override; void onMouseUp (FMouseEvent*) override; void onMouseMove (FMouseEvent*) override; + void onWheel (FWheelEvent*) override; void onTimer (FTimerEvent*) override; void onAccel (FAccelEvent*) override; void onHide (FHideEvent*) override; @@ -206,22 +209,26 @@ class FLineEdit : public FWidget void processChanged(); // Data members - FString text{""}; - FString print_text{""}; - FString label_text{""}; - FLabel* label{}; - std::wstring input_filter{}; - dragScroll drag_scroll{FLineEdit::noScroll}; - label_o label_orientation{FLineEdit::label_left}; - inputType input_type{FLineEdit::textfield}; - int scroll_repeat{100}; - bool scroll_timer{false}; - bool insert_mode{true}; - std::size_t cursor_pos{NOT_SET}; - std::size_t text_offset{0}; - std::size_t char_width_offset{0}; - std::size_t x_pos{0}; - std::size_t max_length{std::numeric_limits::max()}; + FString text{""}; + FString print_text{""}; + FString label_text{""}; + FLabel* label{}; + FWidget* label_associated_widget{this}; + std::wstring input_filter{}; + dragScroll drag_scroll{FLineEdit::noScroll}; + label_o label_orientation{FLineEdit::label_left}; + inputType input_type{FLineEdit::textfield}; + int scroll_repeat{100}; + bool scroll_timer{false}; + bool insert_mode{true}; + std::size_t cursor_pos{NOT_SET}; + std::size_t text_offset{0}; + std::size_t char_width_offset{0}; + std::size_t x_pos{0}; + std::size_t max_length{std::numeric_limits::max()}; + + // Friend class + friend class FSpinBox; }; @@ -243,8 +250,12 @@ inline std::size_t FLineEdit::getCursorPosition() const { return cursor_pos; } //---------------------------------------------------------------------- -inline int FLineEdit::getLabelOrientation() -{ return int(label_orientation); } +inline FLabel* FLineEdit::getLabelObject() const +{ return label; } + +//---------------------------------------------------------------------- +inline FLineEdit::label_o FLineEdit::getLabelOrientation() +{ return label_orientation; } //---------------------------------------------------------------------- inline void FLineEdit::setInputFilter (const FString& regex_string) @@ -258,6 +269,10 @@ inline void FLineEdit::clearInputFilter() inline void FLineEdit::setInputType (const inputType type) { input_type = type; } +//---------------------------------------------------------------------- +inline void FLineEdit::setLabelAssociatedWidget (FWidget* w) +{ label_associated_widget = w; } + //---------------------------------------------------------------------- inline bool FLineEdit::setEnable() { return setEnable(true); } diff --git a/src/include/final/flistbox.h b/src/include/final/flistbox.h index ffc18dd5..ec686df1 100644 --- a/src/include/final/flistbox.h +++ b/src/include/final/flistbox.h @@ -142,12 +142,12 @@ inline void FListBoxItem::clear() class FListBox : public FWidget { public: - // Typedef - typedef std::vector listBoxItems; - // Using-declaration using FWidget::setGeometry; + // Typedef + typedef std::vector listBoxItems; + // Constructor explicit FListBox (FWidget* = nullptr); template @@ -188,9 +188,6 @@ class FListBox : public FWidget void setMultiSelection (); void unsetMultiSelection (); bool setDisable() override; - bool setFocus (bool) override; - bool setFocus() override; - bool unsetFocus() override; void setText (const FString&); // Inquiries @@ -442,14 +439,6 @@ inline void FListBox::unsetMultiSelection() inline bool FListBox::setDisable() { return setEnable(false); } -//---------------------------------------------------------------------- -inline bool FListBox::setFocus() -{ return setFocus(true); } - -//---------------------------------------------------------------------- -inline bool FListBox::unsetFocus() -{ return setFocus(false); } - //---------------------------------------------------------------------- inline bool FListBox::isSelected (std::size_t index) { return index2iterator(index - 1)->selected; } diff --git a/src/include/final/fobject.h b/src/include/final/fobject.h index 96921ac9..9c40c3b5 100644 --- a/src/include/final/fobject.h +++ b/src/include/final/fobject.h @@ -113,6 +113,7 @@ class FObject void removeParent(); void addChild (FObject*); void delChild (FObject*); + void setParent (FObject*); // Event handler virtual bool event (FEvent*); diff --git a/src/include/final/fsize.h b/src/include/final/fsize.h index b94f4256..0870421c 100644 --- a/src/include/final/fsize.h +++ b/src/include/final/fsize.h @@ -44,6 +44,9 @@ namespace finalcut { +// class forward declaration +class FPoint; + //---------------------------------------------------------------------- // class FSize //---------------------------------------------------------------------- @@ -95,6 +98,10 @@ class FSize std::size_t& width_ref(); std::size_t& height_ref(); + // Methods + void scaleBy (int, int); + void scaleBy (const FPoint&); + private: // Data members std::size_t width{0}; diff --git a/src/include/final/fspinbox.h b/src/include/final/fspinbox.h new file mode 100644 index 00000000..48de479c --- /dev/null +++ b/src/include/final/fspinbox.h @@ -0,0 +1,219 @@ +/*********************************************************************** +* fspinbox.h - Widget FSpinBox * +* * +* This file is part of the Final Cut widget toolkit * +* * +* Copyright 2019 Markus Gans * +* * +* 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 * +* . * +***********************************************************************/ + +/* Inheritance diagram + * ═══════════════════ + * + * ▕▔▔▔▔▔▔▔▔▔▏ + * ▕ FTerm ▏ + * ▕▁▁▁▁▁▁▁▁▁▏ + * ▲ + * │ + * ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▏ + * ▕ FVTerm ▏ ▕ FObject ▏ + * ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏ + * ▲ ▲ + * │ │ + * └─────┬─────┘ + * │ + * ▕▔▔▔▔▔▔▔▔▔▏ + * ▕ FWidget ▏ + * ▕▁▁▁▁▁▁▁▁▁▏ + * ▲ + * │ + * ▕▔▔▔▔▔▔▔▔▔▔▏ + * ▕ FSpinBox ▏ + * ▕▁▁▁▁▁▁▁▁▁▁▏ + */ + +#ifndef FSPINBOX_H +#define FSPINBOX_H + +#if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT) + #error "Only can be included directly." +#endif + +#include "final/fwidget.h" + +namespace finalcut +{ + +// class forward declaration +class FLineEdit; + +//---------------------------------------------------------------------- +// class FSpinBox +//---------------------------------------------------------------------- + +class FSpinBox : public FWidget +{ + public: + // Using-declaration + using FWidget::setGeometry; + + // Constructors + explicit FSpinBox (FWidget* = nullptr); + + // Disable copy constructor + FSpinBox (const FSpinBox&) = delete; + + // Destructor + ~FSpinBox(); + + // Disable assignment operator (=) + FSpinBox& operator = (const FSpinBox&) = delete; + + // Accessors + sInt64 getValue(); + FString getPrefix() const; + FString getSuffix() const; + FLineEdit::label_o getLabelOrientation(); + + // Mutators + void setGeometry ( const FPoint&, const FSize& + , bool = true ) override; + bool setEnable (bool) override; + bool setEnable() override; + bool unsetEnable() override; + bool setDisable() override; + bool setFocus (bool) override; + bool setFocus() override; + bool unsetFocus() override; + bool setShadow (bool); + bool setShadow(); + bool unsetShadow(); + void setValue (sInt64); + void setMinValue (sInt64); + void setMaxValue (sInt64); + void setRange (sInt64, sInt64); + void setPrefix (const FString&); + void setSuffix (const FString&); + void setLabelText (const FString&); + void setLabelOrientation (const FLineEdit::label_o); + + // Inquiries + bool hasShadow(); + + // Methods + void draw() override; + + // Event handlers + void onKeyPress (FKeyEvent*) override; + void onMouseDown (FMouseEvent*) override; + void onMouseUp (FMouseEvent*) override; + void onWheel (FWheelEvent*) override; + void onTimer (FTimerEvent*) override; + + private: + // Enumeration + enum spiningState + { + noSpin = 0, + spinUp = 1, + spinDown = 2 + }; + + // Methods + void init(); + void updateInputField(); + void increaseValue(); + void decreaseValue(); + void processChanged(); + void forceFocus(); + + // Callback methods + void cb_inputFieldChange (finalcut::FWidget*, FDataPtr); + + // Data members + FLineEdit input_field{this}; + sInt64 value{0}; + sInt64 min{std::numeric_limits::min()}; + sInt64 max{std::numeric_limits::max()}; + FString pfix{}; + FString sfix{}; + spiningState spining_state{FSpinBox::noSpin}; + bool threshold_reached{false}; + int threshold_time{500}; + int repeat_time{10}; +}; + + +// FSpinBox inline functions +//---------------------------------------------------------------------- +inline sInt64 FSpinBox::getValue() +{ return value; } + +//---------------------------------------------------------------------- +FString FSpinBox::getPrefix() const +{ return pfix; } + +//---------------------------------------------------------------------- +FString FSpinBox::getSuffix() const +{ return sfix; } + +//---------------------------------------------------------------------- +inline FLineEdit::label_o FSpinBox::getLabelOrientation() +{ return input_field.getLabelOrientation(); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::setEnable() +{ return setEnable(true); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::unsetEnable() +{ return setEnable(false); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::setDisable() +{ return setEnable(false); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::setFocus() +{ return setFocus(true); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::unsetFocus() +{ return setFocus(false); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::setShadow() +{ return setShadow(true); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::unsetShadow() +{ return setShadow(false); } + +//---------------------------------------------------------------------- +inline bool FSpinBox::hasShadow() +{ return getFlags().shadow; } + +//---------------------------------------------------------------------- +inline void FSpinBox::setLabelText (const FString& s) +{ input_field.setLabelText(s); } + +//---------------------------------------------------------------------- +inline void FSpinBox::setLabelOrientation (const FLineEdit::label_o o) +{ input_field.setLabelOrientation(o); } + +} // namespace finalcut + +#endif // FSPINBOX_H diff --git a/src/include/final/fterm.h b/src/include/final/fterm.h index 8b36ed69..50bfb759 100644 --- a/src/include/final/fterm.h +++ b/src/include/final/fterm.h @@ -388,6 +388,7 @@ class FTerm final // implemented in fterm_functions.cpp //---------------------------------------------------------------------- uInt env2uint (const char*); +bool isReverseNewFontchar (wchar_t); wchar_t cp437_to_unicode (uChar); uChar unicode_to_cp437 (wchar_t); FString getFullWidth (const FString&); diff --git a/src/include/final/fwidget.h b/src/include/final/fwidget.h index 049d04f0..b657c088 100644 --- a/src/include/final/fwidget.h +++ b/src/include/final/fwidget.h @@ -410,6 +410,7 @@ class FWidget : public FVTerm, public FObject void insufficientSpaceAdjust(); void KeyPressEvent (FKeyEvent*); void KeyDownEvent (FKeyEvent*); + void setWindowFocus (bool); FCallbackPtr getCallbackPtr (FCallback); bool changeFocus (FWidget*, FWidget*, fc::FocusTypes); void processDestroy(); @@ -417,6 +418,7 @@ class FWidget : public FVTerm, public FObject void drawWindows(); void drawChildren(); static void setColorTheme(); + void setStatusbarText (bool); // Data members FPoint widget_cursor_position{-1, -1}; @@ -527,6 +529,8 @@ class FWidget : public FVTerm, public FObject // implemented in fwidget_functions.cpp //---------------------------------------------------------------------- void detectTermSize(); +bool isFocusNextKey (FKey); +bool isFocusPrevKey (FKey); FKey getHotkey (const FString&); std::size_t getHotkeyPos (const FString& src, FString& dest); void setHotkeyViaString (FWidget*, const FString&); diff --git a/src/include/final/fwidgetcolors.h b/src/include/final/fwidgetcolors.h index 83427a50..53815492 100644 --- a/src/include/final/fwidgetcolors.h +++ b/src/include/final/fwidgetcolors.h @@ -134,6 +134,8 @@ class FWidgetColors final FColor scrollbar_bg{fc::Default}; FColor scrollbar_button_fg{fc::Default}; FColor scrollbar_button_bg{fc::Default}; + FColor scrollbar_button_inactive_fg{fc::Default}; + FColor scrollbar_button_inactive_bg{fc::Default}; FColor progressbar_fg{fc::Default}; FColor progressbar_bg{fc::Default}; }; diff --git a/test/fsize-test.cpp b/test/fsize-test.cpp index 761ae866..496eedd0 100644 --- a/test/fsize-test.cpp +++ b/test/fsize-test.cpp @@ -59,6 +59,7 @@ class FSizeTest : public CPPUNIT_NS::TestFixture void subtractionTest(); void areaTest(); void referenceTest(); + void scaleTest(); void streamInsertionTest(); void streamExtractionTest(); @@ -82,6 +83,7 @@ class FSizeTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST (subtractionTest); CPPUNIT_TEST (areaTest); CPPUNIT_TEST (referenceTest); + CPPUNIT_TEST (scaleTest); CPPUNIT_TEST (streamInsertionTest); CPPUNIT_TEST (streamExtractionTest); @@ -369,6 +371,37 @@ void FSizeTest::referenceTest() CPPUNIT_ASSERT ( s1.getHeight() == 4 ); } +//---------------------------------------------------------------------- +void FSizeTest::scaleTest() +{ + finalcut::FSize s1 (15, 15); + CPPUNIT_ASSERT ( s1.getWidth() == 15 ); + CPPUNIT_ASSERT ( s1.getHeight() == 15 ); + CPPUNIT_ASSERT ( s1 == finalcut::FSize(15, 15) ); + + const finalcut::FPoint p1 (-2, -3); + s1.scaleBy(p1); + CPPUNIT_ASSERT ( s1.getWidth() == 13 ); + CPPUNIT_ASSERT ( s1.getHeight() == 12 ); + CPPUNIT_ASSERT ( s1 == finalcut::FSize(13, 12) ); + + const finalcut::FPoint p2 (3, 2); + s1.scaleBy(p2); + CPPUNIT_ASSERT ( s1.getWidth() == 16 ); + CPPUNIT_ASSERT ( s1.getHeight() == 14 ); + CPPUNIT_ASSERT ( s1 == finalcut::FSize(16, 14) ); + + s1.scaleBy(1, -1); + CPPUNIT_ASSERT ( s1.getWidth() == 17 ); + CPPUNIT_ASSERT ( s1.getHeight() == 13 ); + CPPUNIT_ASSERT ( s1 == finalcut::FSize(17, 13) ); + + s1.scaleBy(-2, 2); + CPPUNIT_ASSERT ( s1.getWidth() == 15 ); + CPPUNIT_ASSERT ( s1.getHeight() == 15 ); + CPPUNIT_ASSERT ( s1 == finalcut::FSize(15, 15) ); +} + //---------------------------------------------------------------------- void FSizeTest::streamInsertionTest() {