From 645250e1cd8ce9bc1faea599df7a1b05836bfeb8 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 29 Dec 2020 16:09:43 +0100 Subject: Split UI code into application/plugin UI and UI library. --- .gitmodules | 2 +- Makefile.am | 6 +- configure.ac | 1 + dggui/Makefile.am | 184 +++++++ dggui/button.cc | 88 ++++ dggui/button.h | 64 +++ dggui/button_base.cc | 116 +++++ dggui/button_base.h | 78 +++ dggui/canvas.h | 44 ++ dggui/checkbox.cc | 64 +++ dggui/checkbox.h | 49 ++ dggui/colour.cc | 82 +++ dggui/colour.h | 61 +++ dggui/combobox.cc | 234 +++++++++ dggui/combobox.h | 76 +++ dggui/dialog.cc | 54 ++ dggui/dialog.h | 63 +++ dggui/drawable.h | 52 ++ dggui/eventhandler.cc | 297 +++++++++++ dggui/eventhandler.h | 78 +++ dggui/font.cc | 136 +++++ dggui/font.h | 64 +++ dggui/frame.cc | 146 ++++++ dggui/frame.h | 115 +++++ dggui/guievent.h | 212 ++++++++ dggui/helpbutton.cc | 75 +++ dggui/helpbutton.h | 58 +++ dggui/image.cc | 216 ++++++++ dggui/image.h | 75 +++ dggui/imagecache.cc | 103 ++++ dggui/imagecache.h | 72 +++ dggui/knob.cc | 255 ++++++++++ dggui/knob.h | 88 ++++ dggui/label.cc | 96 ++++ dggui/label.h | 69 +++ dggui/layout.cc | 386 ++++++++++++++ dggui/layout.h | 195 ++++++++ dggui/led.cc | 97 ++++ dggui/led.h | 54 ++ dggui/lineedit.cc | 285 +++++++++++ dggui/lineedit.h | 87 ++++ dggui/listbox.cc | 105 ++++ dggui/listbox.h | 74 +++ dggui/listboxbasic.cc | 362 ++++++++++++++ dggui/listboxbasic.h | 94 ++++ dggui/listboxthin.cc | 101 ++++ dggui/listboxthin.h | 75 +++ dggui/lodepng | 1 + dggui/nativewindow.h | 100 ++++ dggui/nativewindow_cocoa.h | 78 +++ dggui/nativewindow_cocoa.mm | 832 +++++++++++++++++++++++++++++++ dggui/nativewindow_pugl.cc | 382 ++++++++++++++ dggui/nativewindow_pugl.h | 83 +++ dggui/nativewindow_win32.cc | 584 ++++++++++++++++++++++ dggui/nativewindow_win32.h | 78 +++ dggui/nativewindow_x11.cc | 715 ++++++++++++++++++++++++++ dggui/nativewindow_x11.h | 99 ++++ dggui/painter.cc | 644 ++++++++++++++++++++++++ dggui/painter.h | 103 ++++ dggui/pixelbuffer.cc | 369 ++++++++++++++ dggui/pixelbuffer.h | 101 ++++ dggui/powerbutton.cc | 88 ++++ dggui/powerbutton.h | 58 +++ dggui/progressbar.cc | 104 ++++ dggui/progressbar.h | 89 ++++ dggui/rc_data.cc | 29 ++ dggui/rcgentool.cc | 192 +++++++ dggui/resource.cc | 194 +++++++ dggui/resource.h | 50 ++ dggui/resource_data.h | 33 ++ dggui/scrollbar.cc | 214 ++++++++ dggui/scrollbar.h | 74 +++ dggui/slider.cc | 217 ++++++++ dggui/slider.h | 153 ++++++ dggui/stackedwidget.cc | 151 ++++++ dggui/stackedwidget.h | 81 +++ dggui/tabbutton.cc | 132 +++++ dggui/tabbutton.h | 85 ++++ dggui/tabwidget.cc | 214 ++++++++ dggui/tabwidget.h | 84 ++++ dggui/textedit.cc | 201 ++++++++ dggui/textedit.h | 92 ++++ dggui/texture.cc | 72 +++ dggui/texture.h | 64 +++ dggui/texturedbox.cc | 147 ++++++ dggui/texturedbox.h | 119 +++++ dggui/toggle.cc | 110 ++++ dggui/toggle.h | 70 +++ dggui/tooltip.cc | 200 ++++++++ dggui/tooltip.h | 78 +++ dggui/uitranslation.cc | 51 ++ dggui/uitranslation.h | 41 ++ dggui/utf8.cc | 361 ++++++++++++++ dggui/utf8.h | 47 ++ dggui/verticalline.cc | 51 ++ dggui/verticalline.h | 47 ++ dggui/widget.cc | 297 +++++++++++ dggui/widget.h | 139 ++++++ dggui/window.cc | 266 ++++++++++ dggui/window.h | 119 +++++ drumgizmo/Makefile.am | 10 +- drumgizmo/dgvalidator.cc | 10 +- plugin/Makefile.am | 6 +- plugin/Makefile.mingw32.in | 98 ++-- plugin/drumgizmo_plugin.h | 8 +- plugingui/Makefile.am | 179 +------ plugingui/abouttab.cc | 2 +- plugingui/abouttab.h | 6 +- plugingui/bleedcontrolframecontent.h | 6 +- plugingui/button.cc | 88 ---- plugingui/button.h | 64 --- plugingui/button_base.cc | 116 ----- plugingui/button_base.h | 78 --- plugingui/canvas.h | 44 -- plugingui/checkbox.cc | 64 --- plugingui/checkbox.h | 49 -- plugingui/colour.cc | 82 --- plugingui/colour.h | 61 --- plugingui/combobox.cc | 234 --------- plugingui/combobox.h | 76 --- plugingui/dialog.cc | 54 -- plugingui/dialog.h | 63 --- plugingui/diskstreamingframecontent.h | 8 +- plugingui/drawable.h | 52 -- plugingui/drumkitframecontent.cc | 1 - plugingui/drumkitframecontent.h | 11 +- plugingui/drumkittab.cc | 4 +- plugingui/drumkittab.h | 6 +- plugingui/eventhandler.cc | 297 ----------- plugingui/eventhandler.h | 78 --- plugingui/filebrowser.cc | 4 +- plugingui/filebrowser.h | 12 +- plugingui/font.cc | 136 ----- plugingui/font.h | 64 --- plugingui/frame.cc | 146 ------ plugingui/frame.h | 115 ----- plugingui/guievent.h | 212 -------- plugingui/helpbutton.cc | 75 --- plugingui/helpbutton.h | 58 --- plugingui/humaniservisualiser.cc | 2 +- plugingui/humaniservisualiser.h | 6 +- plugingui/humanizerframecontent.cc | 2 +- plugingui/humanizerframecontent.h | 7 +- plugingui/image.cc | 216 -------- plugingui/image.h | 75 --- plugingui/imagecache.cc | 103 ---- plugingui/imagecache.h | 72 --- plugingui/knob.cc | 255 ---------- plugingui/knob.h | 88 ---- plugingui/label.cc | 96 ---- plugingui/label.h | 69 --- plugingui/labeledcontrol.h | 4 +- plugingui/layout.cc | 386 -------------- plugingui/layout.h | 195 -------- plugingui/led.cc | 97 ---- plugingui/led.h | 54 -- plugingui/lineedit.cc | 285 ----------- plugingui/lineedit.h | 87 ---- plugingui/listbox.cc | 105 ---- plugingui/listbox.h | 74 --- plugingui/listboxbasic.cc | 362 -------------- plugingui/listboxbasic.h | 94 ---- plugingui/listboxthin.cc | 101 ---- plugingui/listboxthin.h | 75 --- plugingui/lodepng | 1 - plugingui/maintab.h | 7 +- plugingui/mainwindow.cc | 2 +- plugingui/mainwindow.h | 9 +- plugingui/nativewindow.h | 100 ---- plugingui/nativewindow_cocoa.h | 78 --- plugingui/nativewindow_cocoa.mm | 832 ------------------------------- plugingui/nativewindow_pugl.cc | 382 -------------- plugingui/nativewindow_pugl.h | 83 --- plugingui/nativewindow_win32.cc | 584 ---------------------- plugingui/nativewindow_win32.h | 78 --- plugingui/nativewindow_x11.cc | 715 -------------------------- plugingui/nativewindow_x11.h | 99 ---- plugingui/painter.cc | 644 ------------------------ plugingui/painter.h | 103 ---- plugingui/pixelbuffer.cc | 369 -------------- plugingui/pixelbuffer.h | 101 ---- plugingui/powerbutton.cc | 88 ---- plugingui/powerbutton.h | 58 --- plugingui/powerwidget.cc | 4 +- plugingui/powerwidget.h | 15 +- plugingui/progressbar.cc | 104 ---- plugingui/progressbar.h | 89 ---- plugingui/rcgen.cc | 190 ------- plugingui/resamplingframecontent.h | 8 +- plugingui/resource.cc | 192 ------- plugingui/resource.h | 50 -- plugingui/resource_data.h | 35 -- plugingui/sampleselectionframecontent.cc | 2 +- plugingui/sampleselectionframecontent.h | 7 +- plugingui/scrollbar.cc | 214 -------- plugingui/scrollbar.h | 74 --- plugingui/slider.cc | 217 -------- plugingui/slider.h | 153 ------ plugingui/stackedwidget.cc | 151 ------ plugingui/stackedwidget.h | 81 --- plugingui/statusframecontent.h | 5 +- plugingui/tabbutton.cc | 132 ----- plugingui/tabbutton.h | 85 ---- plugingui/tabwidget.cc | 214 -------- plugingui/tabwidget.h | 84 ---- plugingui/testmain.cc | 8 +- plugingui/textedit.cc | 201 -------- plugingui/textedit.h | 92 ---- plugingui/texture.cc | 72 --- plugingui/texture.h | 64 --- plugingui/texturedbox.cc | 147 ------ plugingui/texturedbox.h | 119 ----- plugingui/timingframecontent.cc | 2 +- plugingui/timingframecontent.h | 9 +- plugingui/toggle.cc | 110 ---- plugingui/toggle.h | 70 --- plugingui/tooltip.cc | 200 -------- plugingui/tooltip.h | 78 --- plugingui/uitranslation.cc | 51 -- plugingui/uitranslation.h | 41 -- plugingui/utf8.cc | 361 -------------- plugingui/utf8.h | 47 -- plugingui/verticalline.cc | 51 -- plugingui/verticalline.h | 47 -- plugingui/visualizerframecontent.cc | 2 +- plugingui/visualizerframecontent.h | 6 +- plugingui/voicelimitframecontent.h | 7 +- plugingui/widget.cc | 297 ----------- plugingui/widget.h | 139 ------ plugingui/window.cc | 266 ---------- plugingui/window.h | 119 ----- test/Makefile.am | 153 ++++-- test/imagecachetest.cc | 6 +- test/paintertest.cc | 8 +- test/resource_test.cc | 2 +- test/translationtest.cc | 2 +- test/uitests/Makefile.am | 31 +- test/uitests/benchmarktest.cc | 6 +- test/uitests/filebrowsertest.cc | 7 +- test/uitests/framewidgettest.cc | 15 +- test/uitests/powerwidgettest.cc | 17 +- test/uitests/resizetest.cc | 7 +- test/uitests/tabwidgettest.cc | 13 +- 243 files changed, 14710 insertions(+), 14560 deletions(-) create mode 100644 dggui/Makefile.am create mode 100644 dggui/button.cc create mode 100644 dggui/button.h create mode 100644 dggui/button_base.cc create mode 100644 dggui/button_base.h create mode 100644 dggui/canvas.h create mode 100644 dggui/checkbox.cc create mode 100644 dggui/checkbox.h create mode 100644 dggui/colour.cc create mode 100644 dggui/colour.h create mode 100644 dggui/combobox.cc create mode 100644 dggui/combobox.h create mode 100644 dggui/dialog.cc create mode 100644 dggui/dialog.h create mode 100644 dggui/drawable.h create mode 100644 dggui/eventhandler.cc create mode 100644 dggui/eventhandler.h create mode 100644 dggui/font.cc create mode 100644 dggui/font.h create mode 100644 dggui/frame.cc create mode 100644 dggui/frame.h create mode 100644 dggui/guievent.h create mode 100644 dggui/helpbutton.cc create mode 100644 dggui/helpbutton.h create mode 100644 dggui/image.cc create mode 100644 dggui/image.h create mode 100644 dggui/imagecache.cc create mode 100644 dggui/imagecache.h create mode 100644 dggui/knob.cc create mode 100644 dggui/knob.h create mode 100644 dggui/label.cc create mode 100644 dggui/label.h create mode 100644 dggui/layout.cc create mode 100644 dggui/layout.h create mode 100644 dggui/led.cc create mode 100644 dggui/led.h create mode 100644 dggui/lineedit.cc create mode 100644 dggui/lineedit.h create mode 100644 dggui/listbox.cc create mode 100644 dggui/listbox.h create mode 100644 dggui/listboxbasic.cc create mode 100644 dggui/listboxbasic.h create mode 100644 dggui/listboxthin.cc create mode 100644 dggui/listboxthin.h create mode 160000 dggui/lodepng create mode 100644 dggui/nativewindow.h create mode 100644 dggui/nativewindow_cocoa.h create mode 100644 dggui/nativewindow_cocoa.mm create mode 100644 dggui/nativewindow_pugl.cc create mode 100644 dggui/nativewindow_pugl.h create mode 100644 dggui/nativewindow_win32.cc create mode 100644 dggui/nativewindow_win32.h create mode 100644 dggui/nativewindow_x11.cc create mode 100644 dggui/nativewindow_x11.h create mode 100644 dggui/painter.cc create mode 100644 dggui/painter.h create mode 100644 dggui/pixelbuffer.cc create mode 100644 dggui/pixelbuffer.h create mode 100644 dggui/powerbutton.cc create mode 100644 dggui/powerbutton.h create mode 100644 dggui/progressbar.cc create mode 100644 dggui/progressbar.h create mode 100644 dggui/rc_data.cc create mode 100644 dggui/rcgentool.cc create mode 100644 dggui/resource.cc create mode 100644 dggui/resource.h create mode 100644 dggui/resource_data.h create mode 100644 dggui/scrollbar.cc create mode 100644 dggui/scrollbar.h create mode 100644 dggui/slider.cc create mode 100644 dggui/slider.h create mode 100644 dggui/stackedwidget.cc create mode 100644 dggui/stackedwidget.h create mode 100644 dggui/tabbutton.cc create mode 100644 dggui/tabbutton.h create mode 100644 dggui/tabwidget.cc create mode 100644 dggui/tabwidget.h create mode 100644 dggui/textedit.cc create mode 100644 dggui/textedit.h create mode 100644 dggui/texture.cc create mode 100644 dggui/texture.h create mode 100644 dggui/texturedbox.cc create mode 100644 dggui/texturedbox.h create mode 100644 dggui/toggle.cc create mode 100644 dggui/toggle.h create mode 100644 dggui/tooltip.cc create mode 100644 dggui/tooltip.h create mode 100644 dggui/uitranslation.cc create mode 100644 dggui/uitranslation.h create mode 100644 dggui/utf8.cc create mode 100644 dggui/utf8.h create mode 100644 dggui/verticalline.cc create mode 100644 dggui/verticalline.h create mode 100644 dggui/widget.cc create mode 100644 dggui/widget.h create mode 100644 dggui/window.cc create mode 100644 dggui/window.h delete mode 100644 plugingui/button.cc delete mode 100644 plugingui/button.h delete mode 100644 plugingui/button_base.cc delete mode 100644 plugingui/button_base.h delete mode 100644 plugingui/canvas.h delete mode 100644 plugingui/checkbox.cc delete mode 100644 plugingui/checkbox.h delete mode 100644 plugingui/colour.cc delete mode 100644 plugingui/colour.h delete mode 100644 plugingui/combobox.cc delete mode 100644 plugingui/combobox.h delete mode 100644 plugingui/dialog.cc delete mode 100644 plugingui/dialog.h delete mode 100644 plugingui/drawable.h delete mode 100644 plugingui/eventhandler.cc delete mode 100644 plugingui/eventhandler.h delete mode 100644 plugingui/font.cc delete mode 100644 plugingui/font.h delete mode 100644 plugingui/frame.cc delete mode 100644 plugingui/frame.h delete mode 100644 plugingui/guievent.h delete mode 100644 plugingui/helpbutton.cc delete mode 100644 plugingui/helpbutton.h delete mode 100644 plugingui/image.cc delete mode 100644 plugingui/image.h delete mode 100644 plugingui/imagecache.cc delete mode 100644 plugingui/imagecache.h delete mode 100644 plugingui/knob.cc delete mode 100644 plugingui/knob.h delete mode 100644 plugingui/label.cc delete mode 100644 plugingui/label.h delete mode 100644 plugingui/layout.cc delete mode 100644 plugingui/layout.h delete mode 100644 plugingui/led.cc delete mode 100644 plugingui/led.h delete mode 100644 plugingui/lineedit.cc delete mode 100644 plugingui/lineedit.h delete mode 100644 plugingui/listbox.cc delete mode 100644 plugingui/listbox.h delete mode 100644 plugingui/listboxbasic.cc delete mode 100644 plugingui/listboxbasic.h delete mode 100644 plugingui/listboxthin.cc delete mode 100644 plugingui/listboxthin.h delete mode 160000 plugingui/lodepng delete mode 100644 plugingui/nativewindow.h delete mode 100644 plugingui/nativewindow_cocoa.h delete mode 100644 plugingui/nativewindow_cocoa.mm delete mode 100644 plugingui/nativewindow_pugl.cc delete mode 100644 plugingui/nativewindow_pugl.h delete mode 100644 plugingui/nativewindow_win32.cc delete mode 100644 plugingui/nativewindow_win32.h delete mode 100644 plugingui/nativewindow_x11.cc delete mode 100644 plugingui/nativewindow_x11.h delete mode 100644 plugingui/painter.cc delete mode 100644 plugingui/painter.h delete mode 100644 plugingui/pixelbuffer.cc delete mode 100644 plugingui/pixelbuffer.h delete mode 100644 plugingui/powerbutton.cc delete mode 100644 plugingui/powerbutton.h delete mode 100644 plugingui/progressbar.cc delete mode 100644 plugingui/progressbar.h delete mode 100644 plugingui/rcgen.cc delete mode 100644 plugingui/resource.cc delete mode 100644 plugingui/resource.h delete mode 100644 plugingui/resource_data.h delete mode 100644 plugingui/scrollbar.cc delete mode 100644 plugingui/scrollbar.h delete mode 100644 plugingui/slider.cc delete mode 100644 plugingui/slider.h delete mode 100644 plugingui/stackedwidget.cc delete mode 100644 plugingui/stackedwidget.h delete mode 100644 plugingui/tabbutton.cc delete mode 100644 plugingui/tabbutton.h delete mode 100644 plugingui/tabwidget.cc delete mode 100644 plugingui/tabwidget.h delete mode 100644 plugingui/textedit.cc delete mode 100644 plugingui/textedit.h delete mode 100644 plugingui/texture.cc delete mode 100644 plugingui/texture.h delete mode 100644 plugingui/texturedbox.cc delete mode 100644 plugingui/texturedbox.h delete mode 100644 plugingui/toggle.cc delete mode 100644 plugingui/toggle.h delete mode 100644 plugingui/tooltip.cc delete mode 100644 plugingui/tooltip.h delete mode 100644 plugingui/uitranslation.cc delete mode 100644 plugingui/uitranslation.h delete mode 100644 plugingui/utf8.cc delete mode 100644 plugingui/utf8.h delete mode 100644 plugingui/verticalline.cc delete mode 100644 plugingui/verticalline.h delete mode 100644 plugingui/widget.cc delete mode 100644 plugingui/widget.h delete mode 100644 plugingui/window.cc delete mode 100644 plugingui/window.h diff --git a/.gitmodules b/.gitmodules index 77580d8..feb5114 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,7 +5,7 @@ path = plugin/plugingizmo url = git://git.drumgizmo.org/plugingizmo.git [submodule "plugingui/lodepng"] - path = plugingui/lodepng + path = dggui/lodepng url = git://git.drumgizmo.org/lodepng.git branch = a71964ed5fe4f82a32ac7f8201338900f66e855d [submodule "getoptpp"] diff --git a/Makefile.am b/Makefile.am index 4196db7..3ac094f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = tools src plugingui plugin drumgizmo man test -DISTDIRS = tools src plugingui plugin drumgizmo man test +SUBDIRS = tools src dggui plugingui plugin drumgizmo man test +DISTDIRS = tools src dggui plugingui plugin drumgizmo man test EXTRA_DIST = \ version.h \ @@ -16,7 +16,7 @@ EXTRA_DIST = \ \ getoptpp/getoptpp.hpp \ \ - plugingui/lodepng/lodepng.h \ + dggui/lodepng/lodepng.h \ \ pugixml/src/pugixml.hpp \ pugixml/src/pugiconfig.hpp \ diff --git a/configure.ac b/configure.ac index 47fedd6..ee53a72 100644 --- a/configure.ac +++ b/configure.ac @@ -720,6 +720,7 @@ AC_CONFIG_FILES( src/Makefile plugin/Makefile plugin/vst/Makefile + dggui/Makefile plugingui/Makefile plugingui/locale/Makefile man/Makefile diff --git a/dggui/Makefile.am b/dggui/Makefile.am new file mode 100644 index 0000000..e55fe12 --- /dev/null +++ b/dggui/Makefile.am @@ -0,0 +1,184 @@ +noinst_PROGRAMS = rcgen +noinst_LTLIBRARIES = libdggui.la + +libdggui_la_CPPFLAGS = \ + $(DEBUG_FLAGS) \ + -I$(top_srcdir) \ + $(GUI_CPPFLAGS) \ + -I$(top_srcdir)/hugin \ + -I$(top_srcdir)/src \ + -DWITH_HUG_MUTEX $(PTHREAD_CFLAGS) \ + -DLODEPNG_NO_COMPILE_ENCODER \ + -DLODEPNG_NO_COMPILE_DISK \ + -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS \ + -DLODEPNG_NO_COMPILE_ERROR_TEXT \ + -DLODEPNG_NO_COMPILE_CPP + +libdggui_la_CFLAGS = + +libdggui_la_LIBTOOLFLAGS=--tag=CC + +libdggui_la_LIBADD = \ + $(GUI_LIBS) $(PTHREAD_LIBS) + +# If you add a file here, remember to add it to plugin/Makefile.mingw32.in +GUI_SRC = \ + button.cc \ + button_base.cc \ + checkbox.cc \ + colour.cc \ + combobox.cc \ + dialog.cc \ + eventhandler.cc \ + font.cc \ + frame.cc \ + helpbutton.cc \ + image.cc \ + imagecache.cc \ + knob.cc \ + label.cc \ + layout.cc \ + led.cc \ + lineedit.cc \ + listbox.cc \ + listboxbasic.cc \ + listboxthin.cc \ + painter.cc \ + pixelbuffer.cc \ + powerbutton.cc \ + progressbar.cc \ + rc_data.cc \ + resource.cc \ + scrollbar.cc \ + slider.cc \ + stackedwidget.cc \ + tabbutton.cc \ + tabwidget.cc \ + textedit.cc \ + texture.cc \ + texturedbox.cc \ + toggle.cc \ + tooltip.cc \ + uitranslation.cc \ + utf8.cc \ + verticalline.cc \ + widget.cc \ + window.cc + +GUI_HDR = \ + button.h \ + button_base.h \ + canvas.h \ + checkbox.h \ + colour.h \ + combobox.h \ + dialog.h \ + drawable.h \ + eventhandler.h \ + font.h \ + frame.h \ + guievent.h \ + helpbutton.h \ + image.h \ + imagecache.h \ + knob.h \ + label.h \ + layout.h \ + led.h \ + lineedit.h \ + listbox.h \ + listboxbasic.h \ + listboxthin.h \ + nativewindow.h \ + nativewindow_cocoa.h \ + nativewindow_cocoa.mm \ + nativewindow_pugl.h \ + nativewindow_pugl.cc \ + nativewindow_win32.h \ + nativewindow_win32.cc \ + nativewindow_x11.h \ + nativewindow_x11.cc \ + painter.h \ + pixelbuffer.h \ + powerbutton.h \ + progressbar.h \ + resource.h \ + resource_data.h \ + scrollbar.h \ + slider.h \ + stackedwidget.h \ + tabbutton.h \ + tabwidget.h \ + textedit.h \ + texture.h \ + texturedbox.h \ + toggle.h \ + tooltip.h \ + uitranslation.h \ + utf8.h \ + verticalline.h \ + widget.h \ + window.h + +libdggui_la_SOURCES = \ + $(GUI_SRC) \ + lodepng/lodepng.cpp + +nodist_libdggui_la_SOURCES = + +if ENABLE_X11 +nodist_libdggui_la_SOURCES += \ + nativewindow_x11.cc +endif + +if ENABLE_WIN32 +nodist_libdggui_la_SOURCES += \ + nativewindow_win32.cc +endif + +if ENABLE_COCOA +nodist_libdggui_la_SOURCES += \ + nativewindow_cocoa.mm + +libdggui_la_OBJCXXFLAGS = \ + -fblocks +endif + +if ENABLE_PUGL_X11 +nodist_libdggui_la_SOURCES += \ + nativewindow_pugl.cc \ + $(top_srcdir)/pugl/pugl/pugl_x11.c + +libdggui_la_CPPFLAGS += \ + -I$(top_srcdir)/pugl + +libdggui_la_CFLAGS += \ + -std=c99 +endif + +if ENABLE_PUGL_WIN32 +nodist_libdggui_la_SOURCES += \ + nativewindow_pugl.cc \ + $(top_srcdir)/pugl/pugl/pugl_win.cpp + +libdggui_la_CPPFLAGS += \ + -I$(top_srcdir)/pugl +endif + +if ENABLE_PUGL_COCOA +nodist_libdggui_la_SOURCES += \ + nativewindow_pugl.cc \ + $(top_srcdir)/pugl/pugl/pugl_osx.m + +libdggui_la_CPPFLAGS += \ + -I$(top_srcdir)/pugl +endif + +rcgen_LDFLAGS = -static +rcgen_CXXFLAGS = -I$(top_srcdir)/getoptpp +rcgen_SOURCES = \ + rcgentool.cc + +EXTRA_DIST = \ + $(RES) \ + $(GUI_HDR) diff --git a/dggui/button.cc b/dggui/button.cc new file mode 100644 index 0000000..30bda82 --- /dev/null +++ b/dggui/button.cc @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * button.cc + * + * Sun Oct 9 13:01:56 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "button.h" + +#include "painter.h" + +#include +#include + +namespace GUI +{ + +Button::Button(Widget* parent) + : ButtonBase(parent) +{ +} + +Button::~Button() +{ +} + +void Button::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + p.clear(); + + int padTop = 3; + int padLeft = 0; + int padTextTop = 3; + + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } + + if (enabled) { + switch(draw_state) + { + case State::Up: + box_up.setSize(w - padLeft, h - padTop); + p.drawImage(padLeft, padTop, box_up); + break; + + case State::Down: + box_down.setSize(w - padLeft, h - padTop); + p.drawImage(padLeft, padTop, box_down); + break; + } + } + else { + box_grey.setSize(w - padLeft, h - padTop); + p.drawImage(padLeft, padTop, box_grey); + + p.setColour(Colour(0.55)); + } + + auto x = padLeft + (width() - font.textWidth(text)) / 2; + auto y = padTop + padTextTop + font.textHeight(text); + p.drawText(x, y, font, text, enabled); +} + +} // GUI:: diff --git a/dggui/button.h b/dggui/button.h new file mode 100644 index 0000000..52f22e2 --- /dev/null +++ b/dggui/button.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * button.h + * + * Sun Oct 9 13:01:56 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "button_base.h" +#include "font.h" +#include "texturedbox.h" + +namespace GUI { + +class Button + : public ButtonBase { +public: + Button(Widget* parent); + virtual ~Button(); + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* e) override; + +private: + TexturedBox box_up{getImageCache(), ":resources/pushbutton.png", + 0, 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 6, 12, 9}; // dy1, dy2, dy3 + + TexturedBox box_down{getImageCache(), ":resources/pushbutton.png", + 15, 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 6, 12, 9}; // dy1, dy2, dy3 + + TexturedBox box_grey{getImageCache(), ":resources/pushbutton.png", + 30, 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 6, 12, 9}; // dy1, dy2, dy3 + + Font font{":resources/fontemboss.png"}; +}; + +} // GUI:: diff --git a/dggui/button_base.cc b/dggui/button_base.cc new file mode 100644 index 0000000..bf441f5 --- /dev/null +++ b/dggui/button_base.cc @@ -0,0 +1,116 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * button_base.cc + * + * Sat Apr 15 21:45:30 CEST 2017 + * Copyright 2017 AndrĂ© Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "button_base.h" + +namespace GUI { + +ButtonBase::ButtonBase(Widget *parent) + : Widget(parent) + , draw_state(State::Up) + , button_state(State::Up) +{ +} + +ButtonBase::~ButtonBase() +{ +} + +void ButtonBase::buttonEvent(ButtonEvent* buttonEvent) +{ + // Ignore everything except left clicks. + if(!enabled || buttonEvent->button != MouseButton::left) + { + return; + } + + if(buttonEvent->direction == Direction::down) + { + draw_state = State::Down; + button_state = State::Down; + in_button = true; + redraw(); + } + + if(buttonEvent->direction == Direction::up) + { + draw_state = State::Up; + button_state = State::Up; + redraw(); + if(in_button) + { + clicked(); + clickNotifier(); + } + } +} + +void ButtonBase::setText(const std::string& text) +{ + this->text = text; + redraw(); +} + +void ButtonBase::setEnabled(bool enabled) +{ + this->enabled = enabled; + redraw(); +} + +bool ButtonBase::isEnabled() const +{ + return enabled; +} + +void ButtonBase::mouseLeaveEvent() +{ + if (!enabled) { + return; + } + + in_button = false; + if(button_state == State::Down) + { + draw_state = State::Up; + redraw(); + } +} + +void ButtonBase::mouseEnterEvent() +{ + if (!enabled) { + return; + } + + in_button = true; + if(button_state == State::Down) + { + draw_state = State::Down; + redraw(); + } +} + +} // GUI:: diff --git a/dggui/button_base.h b/dggui/button_base.h new file mode 100644 index 0000000..c872d9b --- /dev/null +++ b/dggui/button_base.h @@ -0,0 +1,78 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * button_base.h + * + * Sat Apr 15 21:45:30 CEST 2017 + * Copyright 2017 AndrĂ© Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include + +#include "widget.h" + +namespace GUI { + +class ButtonBase + : public Widget +{ +public: + ButtonBase(Widget* parent); + virtual ~ButtonBase(); + + // From Widget: + bool isFocusable() override { return true; } + bool catchMouse() override { return true; } + + void setText(const std::string& text); + + void setEnabled(bool enabled); + bool isEnabled() const; + + Notifier<> clickNotifier; + +protected: + virtual void clicked() {} + + // From Widget: + virtual void repaintEvent(RepaintEvent* e) override {}; + virtual void buttonEvent(ButtonEvent* e) override; + virtual void mouseLeaveEvent() override; + virtual void mouseEnterEvent() override; + + bool enabled{true}; + bool in_button{false}; + + enum class State { + Up, + Down + }; + + std::string text; + + State draw_state{State::Up}; + State button_state{State::Up}; +}; + +} // GUI:: diff --git a/dggui/canvas.h b/dggui/canvas.h new file mode 100644 index 0000000..d6e8f99 --- /dev/null +++ b/dggui/canvas.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * canvas.h + * + * Sun Sep 4 13:03:51 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "pixelbuffer.h" + +namespace GUI +{ + +//! Abstract class that can be used by the Painter to draw on. +class Canvas +{ +public: + virtual ~Canvas() = default; + + //! @returns a reference to the pixel buffer. + virtual PixelBufferAlpha& getPixelBuffer() = 0; +}; + +} // GUI:: diff --git a/dggui/checkbox.cc b/dggui/checkbox.cc new file mode 100644 index 0000000..f3601bd --- /dev/null +++ b/dggui/checkbox.cc @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * checkbox.cc + * + * Sat Nov 26 15:07:44 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "checkbox.h" + +#include "painter.h" + +namespace GUI +{ + +CheckBox::CheckBox(Widget* parent) + : Toggle(parent) + , bg_on(getImageCache(), ":resources/switch_back_on.png") + , bg_off(getImageCache(), ":resources/switch_back_off.png") + , knob(getImageCache(), ":resources/switch_front.png") +{ +} + +void CheckBox::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + p.clear(); + p.drawImage(0, (knob.height() - bg_on.height()) / 2, state ? bg_on : bg_off); + + if(clicked) + { + p.drawImage((bg_on.width() - knob.width()) / 2 + 1, 0, knob); + return; + } + + if(state) + { + p.drawImage(bg_on.width() - 40 + 2, 0, knob); + } + else + { + p.drawImage(0, 0, knob); + } +} + +} // GUI:: diff --git a/dggui/checkbox.h b/dggui/checkbox.h new file mode 100644 index 0000000..6627304 --- /dev/null +++ b/dggui/checkbox.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * checkbox.h + * + * Sat Nov 26 15:07:44 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "toggle.h" +#include "texture.h" + +namespace GUI { + +class CheckBox : public Toggle { +public: + CheckBox(Widget *parent); + virtual ~CheckBox() = default; + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + Texture bg_on; + Texture bg_off; + Texture knob; +}; + +} // GUI:: diff --git a/dggui/colour.cc b/dggui/colour.cc new file mode 100644 index 0000000..7fd649c --- /dev/null +++ b/dggui/colour.cc @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * colour.cc + * + * Fri Oct 14 09:38:28 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "colour.h" + +#include + +namespace GUI +{ + +Colour::Colour() +{ +} + +Colour::Colour(float grey, float a) + : pixel({{(std::uint8_t)(grey * 255), + (std::uint8_t)(grey * 255), + (std::uint8_t)(grey * 255), + (std::uint8_t)(a * 255)}}) +{ +} + +Colour::Colour(float r, float g, float b, float a) + : pixel({{(std::uint8_t)(r * 255), + (std::uint8_t)(g * 255), + (std::uint8_t)(b * 255), + (std::uint8_t)(a * 255)}}) +{ +} + +Colour::Colour(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a) + : pixel({{r, g, b, a}}) +{ +} + +Colour::Colour(const Colour& other) + : pixel(other.pixel) +{ +} + +Colour& Colour::operator=(const Colour& other) +{ + pixel = other.pixel; + return *this; +} + +bool Colour::operator==(const Colour& other) const +{ + return pixel[0] == other.pixel[0] && + pixel[1] == other.pixel[1] && + pixel[2] == other.pixel[2]; +} + +bool Colour::operator!=(const Colour& other) const +{ + return !(*this == other); +} + +} // GUI:: diff --git a/dggui/colour.h b/dggui/colour.h new file mode 100644 index 0000000..0bc8659 --- /dev/null +++ b/dggui/colour.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * colour.h + * + * Fri Oct 14 09:38:28 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +namespace GUI +{ + +class Colour +{ +public: + Colour(); + Colour(float grey, float alpha = 1.0f); + Colour(float red, float green, float blue, float alpha = 1.0f); + Colour(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a); + Colour(const Colour& other); + + Colour& operator=(const Colour& other); + + bool operator==(const Colour& other) const; + bool operator!=(const Colour& other) const; + + inline std::uint8_t red() const { return pixel[0]; } + inline std::uint8_t green() const { return pixel[1]; } + inline std::uint8_t blue() const { return pixel[2]; } + inline std::uint8_t alpha() const { return pixel[3]; } + + std::uint8_t* data() { return pixel.data(); } + const std::uint8_t* data() const { return pixel.data(); } + +private: + std::array pixel{{255, 255, 255, 255}}; +}; + +} // GUI:: diff --git a/dggui/combobox.cc b/dggui/combobox.cc new file mode 100644 index 0000000..aa2058e --- /dev/null +++ b/dggui/combobox.cc @@ -0,0 +1,234 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * combobox.cc + * + * Sun Mar 10 19:04:50 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "combobox.h" + +#include "painter.h" +#include "font.h" + +#include + +#define BORDER 10 + +namespace GUI +{ + +void ComboBox::listboxSelectHandler() +{ + ButtonEvent buttonEvent; + buttonEvent.direction = Direction::down; + this->buttonEvent(&buttonEvent); +} + +ComboBox::ComboBox(Widget* parent) + : Widget(parent) + , listbox(parent) +{ + CONNECT(&listbox, selectionNotifier, this, &ComboBox::listboxSelectHandler); + CONNECT(&listbox, clickNotifier, this, &ComboBox::listboxSelectHandler); + + listbox.hide(); +} + +ComboBox::~ComboBox() +{ +} + +void ComboBox::addItem(std::string name, std::string value) +{ + listbox.addItem(name, value); +} + +void ComboBox::clear() +{ + listbox.clear(); + redraw(); +} + +bool ComboBox::selectItem(int index) +{ + listbox.selectItem(index); + redraw(); + return true; +} + +std::string ComboBox::selectedName() +{ + return listbox.selectedName(); +} + +std::string ComboBox::selectedValue() +{ + return listbox.selectedValue(); +} + +static void drawArrow(Painter &p, int x, int y, int w, int h) +{ + p.drawLine(x, y, x+(w/2), y+h); + p.drawLine(x+(w/2), y+h, x+w, y); + + y++; + p.drawLine(x, y, x+(w/2), y+h); + p.drawLine(x+(w/2), y+h, x+w, y); +} + +void ComboBox::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + std::string _text = selectedName(); + + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } + + box.setSize(w, h); + p.drawImage(0, 0, box); + + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0/255.0f, 1.0f)); + p.drawText(BORDER - 4 + 3, height()/2+5 + 1 + 1, font, _text); + + // p.setColour(Colour(1, 1, 1)); + // p.drawText(BORDER - 4, (height()+font.textHeight()) / 2 + 1, font, _text); + + //int n = height() / 2; + + // p.drawLine(width() - n - 6, 1 + 6, width() - 1 - 6, 1 + 6); + { + int w = 10; + int h = 6; + drawArrow(p, width() - 6 - 4 - w, (height() - h) / 2, w, h); + p.drawLine(width() - 6 - 4 - w - 4, 7, + width() - 6 - 4 - w - 4, height() - 8); + } +} + +void ComboBox::scrollEvent(ScrollEvent* scrollEvent) +{ + /* + scroll_offset += e->delta; + if(scroll_offset < 0) + { + scroll_offset = 0; + } + if(scroll_offset > (items.size() - 1)) + { + scroll_offset = (items.size() - 1); + } + redraw(); + */ +} + +void ComboBox::keyEvent(KeyEvent* keyEvent) +{ + if(keyEvent->direction != Direction::up) + { + return; + } + + /* + switch(keyEvent->keycode) { + case Key::up: + { + selected--; + if(selected < 0) + { + selected = 0; + } + if(selected < scroll_offset) + { + scroll_offset = selected; + if(scroll_offset < 0) + { + scroll_offset = 0; + } + } + } + break; + case Key::down: + { + // Number of items that can be displayed at a time. + int numitems = height() / (font.textHeight() + padding); + + selected++; + if(selected > (items.size() - 1)) + { + selected = (items.size() - 1); + } + if(selected > (scroll_offset + numitems - 1)) + { + scroll_offset = selected - numitems + 1; + if(scroll_offset > (items.size() - 1)) + { + scroll_offset = (items.size() - 1); + } + } + } + break; + case Key::home: + selected = 0; + break; + case Key::end: + selected = items.size() - 1; + break; + default: + break; + } + + redraw(); + */ +} + +void ComboBox::buttonEvent(ButtonEvent* buttonEvent) +{ + // Ignore everything except left clicks. + if(buttonEvent->button != MouseButton::left) + { + return; + } + + if(buttonEvent->direction != Direction::down) + { + return; + } + + if(!listbox.visible()) + { + listbox.resize(width() - 10, 100); + listbox.move(x() + 5, y() + height() - 7); + } + else + { + valueChangedNotifier(listbox.selectedName(), listbox.selectedValue()); + } + + listbox.setVisible(!listbox.visible()); +} + +} // GUI:: diff --git a/dggui/combobox.h b/dggui/combobox.h new file mode 100644 index 0000000..778d54c --- /dev/null +++ b/dggui/combobox.h @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * combobox.h + * + * Sun Mar 10 19:04:50 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include "widget.h" +#include "font.h" +#include "listboxthin.h" +#include "painter.h" +#include "texturedbox.h" + +namespace GUI +{ + +class ComboBox + : public Widget +{ +public: + ComboBox(Widget* parent); + virtual ~ComboBox(); + + void addItem(std::string name, std::string value); + + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); + + // From Widget: + bool isFocusable() override { return true; } + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void scrollEvent(ScrollEvent* scrollEvent) override; + virtual void keyEvent(KeyEvent* keyEvent) override; + + Notifier valueChangedNotifier; + +private: + TexturedBox box{getImageCache(), ":resources/widget.png", + 0, 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 7, 63, 7}; // dy1, dy2, dy3 + + void listboxSelectHandler(); + + Font font; + ListBoxThin listbox; +}; + +} // GUI:: diff --git a/dggui/dialog.cc b/dggui/dialog.cc new file mode 100644 index 0000000..9ba579d --- /dev/null +++ b/dggui/dialog.cc @@ -0,0 +1,54 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * dialog.cc + * + * Sun Apr 16 10:31:04 CEST 2017 + * Copyright 2017 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "dialog.h" + +namespace GUI +{ + +Dialog::Dialog(Widget* parent, bool modal) + : parent(parent) +{ + parent->window()->eventHandler()->registerDialog(this); + setModal(modal); +} + +Dialog::~Dialog() +{ + parent->window()->eventHandler()->unregisterDialog(this); +} + +void Dialog::setModal(bool modal) +{ + is_modal = modal; +} + +bool Dialog::isModal() const +{ + return is_modal; +} + +} // GUI:: diff --git a/dggui/dialog.h b/dggui/dialog.h new file mode 100644 index 0000000..1b0c6da --- /dev/null +++ b/dggui/dialog.h @@ -0,0 +1,63 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * dialog.h + * + * Sun Apr 16 10:31:04 CEST 2017 + * Copyright 2017 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "window.h" + +namespace GUI +{ + +//! This class is used the base window for pop-up dialogs, such as a file +//! browser. +class Dialog + : public Window +{ +public: + //! - The dialog is placed near the parent window. + //! - The parent window event handler will call the dialog event handler + //! - While the dialog is visible, all mouse click and keyboard events + //! are ignored by the parent event handler. + //! - The Dialog registers itself in the parent event handler when contructed + //! and removes itself when destructed. + //! - The parent event handler will delete all registered Dialogs when itself + //! deleted. + Dialog(Widget* parent, bool modal = false); + + ~Dialog(); + + //! Change modality. + void setModal(bool modal); + + //! Get current modality state. + bool isModal() const; + +private: + bool is_modal{false}; + Widget* parent{nullptr}; +}; + +} // GUI:: diff --git a/dggui/drawable.h b/dggui/drawable.h new file mode 100644 index 0000000..95492d6 --- /dev/null +++ b/dggui/drawable.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * drawable.h + * + * Sat Jun 4 21:39:38 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +namespace GUI +{ + +class Colour; + +class Drawable +{ +public: + virtual ~Drawable() = default; + + virtual std::size_t width() const = 0; + virtual std::size_t height() const = 0; + + virtual const Colour& getPixel(std::size_t x, std::size_t y) const = 0; + virtual const std::uint8_t* line(std::size_t y, + std::size_t x_offset = 0) const = 0; + + virtual bool hasAlpha() const = 0; +}; + +} // GUI:: diff --git a/dggui/eventhandler.cc b/dggui/eventhandler.cc new file mode 100644 index 0000000..fd333b8 --- /dev/null +++ b/dggui/eventhandler.cc @@ -0,0 +1,297 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * eventhandler.cc + * + * Sun Oct 9 18:58:29 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "eventhandler.h" + +#include "window.h" +#include "painter.h" +#include "dialog.h" + +namespace GUI +{ + +EventHandler::EventHandler(NativeWindow& nativeWindow, Window& window) + : window(window) + , nativeWindow(nativeWindow) + , lastWasDoubleClick(false) +{} + +bool EventHandler::hasEvent() +{ + return !events.empty(); +} + +bool EventHandler::queryNextEventType(EventType type) +{ + return !events.empty() && + (events.front()->type() == type); +} + +std::shared_ptr EventHandler::getNextEvent() +{ + if(events.empty()) + { + return nullptr; + } + + auto event = events.front(); + events.pop_front(); + return event; +} + +void EventHandler::processEvents() +{ + bool block_interaction{false}; + for(auto dialog : dialogs) + { + // Check if the dialog nativewindow (not the contained widget) is visible + if(dialog->native->visible()) + { + block_interaction |= dialog->isModal(); + dialog->eventHandler()->processEvents(); + } + } + + events = nativeWindow.getEvents(); + + while(hasEvent()) + { + auto event = getNextEvent(); + + if(event == nullptr) + { + continue; + } + + switch(event->type()) { + case EventType::repaint: + break; + + case EventType::move: + { + auto moveEvent = static_cast(event.get()); + window.moved(moveEvent->x, moveEvent->y); + } + break; + + case EventType::resize: + { + auto resizeEvent = static_cast(event.get()); + if((resizeEvent->width != window.width()) || + (resizeEvent->height != window.height())) + { + window.resized(resizeEvent->width, resizeEvent->height); + } + } + break; + + case EventType::mouseMove: + { + // Skip all consecutive mouse move events and handle only the last one. + while(queryNextEventType(EventType::mouseMove)) + { + event = getNextEvent(); + } + + auto moveEvent = static_cast(event.get()); + + auto widget = window.find(moveEvent->x, moveEvent->y); + auto oldwidget = window.mouseFocus(); + if(widget != oldwidget) + { + // Send focus leave to oldwidget + if(oldwidget) + { + oldwidget->mouseLeaveEvent(); + } + + // Send focus enter to widget + if(widget) + { + widget->mouseEnterEvent(); + } + + window.setMouseFocus(widget); + } + + if(window.buttonDownFocus()) + { + auto widget = window.buttonDownFocus(); + moveEvent->x -= widget->translateToWindowX(); + moveEvent->y -= widget->translateToWindowY(); + + window.buttonDownFocus()->mouseMoveEvent(moveEvent); + break; + } + + if(widget) + { + moveEvent->x -= widget->translateToWindowX(); + moveEvent->y -= widget->translateToWindowY(); + widget->mouseMoveEvent(moveEvent); + } + } + break; + + case EventType::button: + { + if(block_interaction) + { + continue; + } + + auto buttonEvent = static_cast(event.get()); + if(lastWasDoubleClick && (buttonEvent->direction == Direction::down)) + { + lastWasDoubleClick = false; + continue; + } + + lastWasDoubleClick = buttonEvent->doubleClick; + + auto widget = window.find(buttonEvent->x, buttonEvent->y); + + if(window.buttonDownFocus()) + { + if(buttonEvent->direction == Direction::up) + { + auto widget = window.buttonDownFocus(); + buttonEvent->x -= widget->translateToWindowX(); + buttonEvent->y -= widget->translateToWindowY(); + + widget->buttonEvent(buttonEvent); + window.setButtonDownFocus(nullptr); + break; + } + } + + if(widget) + { + buttonEvent->x -= widget->translateToWindowX(); + buttonEvent->y -= widget->translateToWindowY(); + + widget->buttonEvent(buttonEvent); + + if((buttonEvent->direction == Direction::down) && + widget->catchMouse()) + { + window.setButtonDownFocus(widget); + } + + if(widget->isFocusable()) + { + window.setKeyboardFocus(widget); + } + } + } + break; + + case EventType::scroll: + { + if(block_interaction) + { + continue; + } + + auto scrollEvent = static_cast(event.get()); + + auto widget = window.find(scrollEvent->x, scrollEvent->y); + if(widget) + { + scrollEvent->x -= widget->translateToWindowX(); + scrollEvent->y -= widget->translateToWindowY(); + + widget->scrollEvent(scrollEvent); + } + } + break; + + case EventType::key: + { + if(block_interaction) + { + continue; + } + + // TODO: Filter out multiple arrow events. + + auto keyEvent = static_cast(event.get()); + if(window.keyboardFocus()) + { + window.keyboardFocus()->keyEvent(keyEvent); + } + } + break; + + case EventType::close: + if(block_interaction) + { + continue; + } + + closeNotifier(); + break; + + case EventType::mouseEnter: + { + auto enterEvent = static_cast(event.get()); + auto widget = window.find(enterEvent->x, enterEvent->y); + if(widget) + { + widget->mouseEnterEvent(); + } + } + break; + + case EventType::mouseLeave: + { + auto widget = window.mouseFocus(); + if(widget) + { + widget->mouseLeaveEvent(); + } + } + break; + } + } + + // Probe window and children to redraw as needed. + // NOTE: This method will invoke native->redraw() if a redraw is needed. + window.updateBuffer(); +} + +void EventHandler::registerDialog(Dialog* dialog) +{ + dialogs.push_back(dialog); +} + +void EventHandler::unregisterDialog(Dialog* dialog) +{ + dialogs.remove(dialog); +} + + +} // GUI:: diff --git a/dggui/eventhandler.h b/dggui/eventhandler.h new file mode 100644 index 0000000..8d6f492 --- /dev/null +++ b/dggui/eventhandler.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * eventhandler.h + * + * Sun Oct 9 18:58:29 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include +#include +#include + +#include "guievent.h" +#include "nativewindow.h" + +namespace GUI +{ + +class Window; +class Dialog; + +class EventHandler +{ +public: + EventHandler(NativeWindow& nativeWindow, Window& window); + + //! Process all events currently in the event queue. + void processEvents(); + + //! Query if any events are currently in the event queue. + bool hasEvent(); + + //! Query if the topmost event in the event queue is of type. + bool queryNextEventType(EventType type); + + //! Get a single event from the event queue. + //! \return A pointer to the event or nullptr if there are none. + std::shared_ptr getNextEvent(); + + void registerDialog(Dialog* dialog); + void unregisterDialog(Dialog* dialog); + + Notifier<> closeNotifier; + +private: + Window& window; + NativeWindow& nativeWindow; + + // Used to ignore mouse button release after a double click. + bool lastWasDoubleClick; + + EventQueue events; + + std::list dialogs; +}; + +} // GUI:: diff --git a/dggui/font.cc b/dggui/font.cc new file mode 100644 index 0000000..0500e81 --- /dev/null +++ b/dggui/font.cc @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * font.cc + * + * Sat Nov 12 11:13:41 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "font.h" + +#include + +namespace GUI +{ + +Font::Font(const std::string& fontfile) + : img_font(fontfile) +{ + std::size_t px = 0; + std::size_t c; + + for(c = 0; c < characters.size() && px < img_font.width(); ++c) + { + auto& character = characters[c]; + character.offset = px + 1; + + if(c > 0) + { + assert(character.offset >= characters[c - 1].offset); + characters[c - 1].width = character.offset - characters[c - 1].offset; + if(characters[c].offset != characters[c - 1].offset) + { + --characters[c - 1].width; + } + } + + ++px; + + while(px < img_font.width()) + { + auto& pixel = img_font.getPixel(px, 0); + + // Find next purple pixel in top row: + if((pixel.red() == 255) && (pixel.green() == 0) && + (pixel.blue() == 255) && (pixel.alpha() == 255)) + { + break; + } + + ++px; + } + + characters[c] = character; + } + + --c; + + assert(characters[c].offset >= characters[c - 1].offset); + characters[c - 1].width = characters[c].offset - characters[c - 1].offset; + if(characters[c].offset != characters[c - 1].offset) + { + --characters[c - 1].width; + } +} + +size_t Font::textWidth(const std::string& text) const +{ + size_t len = 0; + + for(unsigned char cha : text) + { + auto& character = characters[cha]; + len += character.width + spacing + character.post_bias; + } + + return len; +} + +size_t Font::textHeight(const std::string& text) const +{ + return img_font.height(); +} + +void Font::setLetterSpacing(int letterSpacing) +{ + spacing = letterSpacing; +} + +int Font::letterSpacing() const +{ + return spacing; +} + +PixelBufferAlpha *Font::render(const std::string& text) const +{ + PixelBufferAlpha *pb = + new PixelBufferAlpha(textWidth(text), textHeight(text)); + + int x_offset = 0; + for(std::size_t i = 0; i < text.length(); ++i) + { + unsigned char cha = text[i]; + auto& character = characters.at(cha); + for(size_t x = 0; x < character.width; ++x) + { + for(size_t y = 0; y < img_font.height(); ++y) + { + auto& c = img_font.getPixel(x + character.offset, y); + pb->setPixel(x + x_offset + character.pre_bias, y, c); + } + } + x_offset += character.width + spacing + character.post_bias; + } + + return pb; +} + +} // GUI:: diff --git a/dggui/font.h b/dggui/font.h new file mode 100644 index 0000000..2e3f87a --- /dev/null +++ b/dggui/font.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * font.h + * + * Sat Nov 12 11:13:41 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include "pixelbuffer.h" +#include "image.h" + +namespace GUI { + +class Font { +public: + Font(const std::string& fontfile = ":resources/font.png"); + + size_t textWidth(const std::string& text) const; + size_t textHeight(const std::string& text = "") const; + + void setLetterSpacing(int letterSpacing); + int letterSpacing() const; + + PixelBufferAlpha *render(const std::string& text) const; + +private: + Image img_font; + + class Character { + public: + std::size_t offset{0}; + std::size_t width{0}; + int pre_bias{0}; + int post_bias{0}; + }; + + std::array characters; + int spacing{1}; +}; + +} // GUI:: diff --git a/dggui/frame.cc b/dggui/frame.cc new file mode 100644 index 0000000..d375b6d --- /dev/null +++ b/dggui/frame.cc @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * frame.cc + * + * Tue Feb 7 21:07:56 CET 2017 + * Copyright 2017 André Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "frame.h" + +#include "painter.h" + +namespace GUI +{ + +FrameWidget::FrameWidget(Widget* parent, bool has_switch, bool has_help_text) + : Widget(parent) + , is_switched_on(!has_switch) + , bar_height(24) +{ + if(has_switch) + { + // We only have to set this once as nothing happens on a resize + power_button.move(4, 4); + power_button.resize(16, 16); + + power_button.setChecked(is_switched_on); + CONNECT(&power_button, stateChangedNotifier, this, + &FrameWidget::powerButtonStateChanged); + } + power_button.setVisible(has_switch); + + if(has_help_text) + { + // We only have to set this once as nothing happens on a resize + help_button.resize(16, 16); + help_button.move(width() - 4 - 16, 4); + help_button.setText("?"); + } + help_button.setVisible(has_help_text); + + CONNECT(this, sizeChangeNotifier, this, &FrameWidget::sizeChanged); +} + +void FrameWidget::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + int center_x = width() / 2; + auto title_buf = title.c_str(); + + // draw the dark grey box + p.setColour(enabled ? grey_box_colour : grey_box_colour_disabled); + p.drawFilledRectangle(1, 1, width() - 2, bar_height); + + // frame + p.setColour(frame_colour_top); + p.drawLine(0, 0, width() - 1, 0); + p.setColour(frame_colour_bottom); + p.drawLine(0, height() - 1, width() - 1, height() - 1); + p.setColour(frame_colour_side); + p.drawLine(0, 0, 0, height() - 1); + p.drawLine(width() - 1, 0, width() - 1, height() - 1); + + // background + p.setColour(background_colour); + p.drawFilledRectangle(1, bar_height, width() - 2, height() - 2); + + // draw the label + p.setColour(enabled ? label_colour : label_colour_disabled); + p.drawText(center_x - label_width, bar_height - 4, font, title_buf); + power_button.setEnabled(enabled); +} + +void FrameWidget::powerButtonStateChanged(bool new_state) +{ + is_switched_on = new_state; + onSwitchChangeNotifier(is_switched_on); +} + +void FrameWidget::setTitle(std::string const& title) +{ + this->title = title; + label_width = font.textWidth(title.c_str()) / 2 + 1; +} + +void FrameWidget::setHelpText(const std::string& help_text) +{ + help_button.setHelpText(help_text); +} + +void FrameWidget::setContent(Widget* content) +{ + this->content = content; + content->reparent(this); +} + +void FrameWidget::setOnSwitch(bool on) +{ + is_switched_on = on; + power_button.setChecked(is_switched_on); +} + +void FrameWidget::setEnabled(bool enabled) +{ + this->enabled = enabled; + onEnabledChanged(enabled); + + redraw(); +} + +void FrameWidget::sizeChanged(int width, int height) +{ + if(content) + { + content_start_x = content_margin; + content_start_y = bar_height + content_margin; + content_width = std::max((int)width - 2 * content_margin, 0); + content_height = std::max((int)height - (bar_height + 2 * content_margin), 0); + + content->move(content_start_x, content_start_y); + content->resize(content_width, content_height); + } + + help_button.move(width - 4 - 16, help_button.y()); +} + +} // GUI:: diff --git a/dggui/frame.h b/dggui/frame.h new file mode 100644 index 0000000..db26ea9 --- /dev/null +++ b/dggui/frame.h @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * frame.h + * + * Tue Feb 7 21:07:56 CET 2017 + * Copyright 2017 André Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "font.h" +#include "powerbutton.h" +#include "helpbutton.h" +#include "widget.h" + +namespace GUI +{ + +class FrameWidget + : public Widget +{ +public: + FrameWidget(Widget* parent, bool has_switch = false, bool has_help_text = false); + virtual ~FrameWidget() = default; + + // From Widget: + virtual bool isFocusable() override { return false; } + virtual bool catchMouse() override { return false; } + + bool isSwitchedOn() { return is_switched_on; } + + void setTitle(const std::string& title); + void setHelpText(const std::string& help_text); + void setContent(Widget* content); + + void setOnSwitch(bool on); + void setEnabled(bool enabled); + + Notifier onSwitchChangeNotifier; // (bool on) + Notifier onEnabledChanged; // (bool enabled) + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + + //! Callback for Widget::sizeChangeNotifier + void sizeChanged(int width, int height); + + bool enabled = true; + +private: + // + // upper bar + // + + // label + Font font; + std::string title; + GUI::Colour label_colour{0.1}; + GUI::Colour label_colour_disabled{0.5}; + std::size_t label_width; + + // switch + bool is_switched_on; + PowerButton power_button{this}; + HelpButton help_button{this}; + + void powerButtonStateChanged(bool clicked); + + // grey box + int bar_height; + GUI::Colour grey_box_colour{0.7}; + GUI::Colour grey_box_colour_disabled{0.7}; + GUI::Colour background_colour{0.85, 0.8}; + + // + // content + // + + // content frame + GUI::Colour frame_colour_top{0.95}; + GUI::Colour frame_colour_bottom{0.4}; + GUI::Colour frame_colour_side{0.6}; + + // content box + Widget* content{nullptr}; + int content_margin{12}; + + int content_start_x; + int content_start_y; + int content_width; + int content_height; +}; + +} // GUI:: diff --git a/dggui/guievent.h b/dggui/guievent.h new file mode 100644 index 0000000..4ad0798 --- /dev/null +++ b/dggui/guievent.h @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * event.h + * + * Sun Oct 9 16:11:47 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include +#include + +namespace GUI +{ + +enum class EventType +{ + mouseMove, + repaint, + button, + scroll, + key, + close, + resize, + move, + mouseEnter, + mouseLeave, +}; + +class Event +{ +public: + virtual ~Event() {} + + virtual EventType type() = 0; +}; + +class MouseMoveEvent + : public Event +{ +public: + EventType type() { return EventType::mouseMove; } + + int x; + int y; +}; + + +enum class Direction +{ + up, + down, +}; + +enum class MouseButton +{ + right, + middle, + left, +}; + +class ButtonEvent + : public Event +{ +public: + EventType type() { return EventType::button; } + + int x; + int y; + + Direction direction; + MouseButton button; + + bool doubleClick; +}; + +class ScrollEvent + : public Event +{ +public: + EventType type() { return EventType::scroll; } + + int x; + int y; + + float delta; +}; + +class RepaintEvent + : public Event +{ +public: + EventType type() { return EventType::repaint; } + + int x; + int y; + size_t width; + size_t height; +}; + +enum class Key +{ + unknown, + left, + right, + up, + down, + deleteKey, + backspace, + home, + end, + pageDown, + pageUp, + enter, + character, //!< The actual character is stored in KeyEvent::text +}; + +class KeyEvent + : public Event +{ +public: + EventType type() { return EventType::key; } + + Direction direction; + + Key keycode; + std::string text; +}; + +class CloseEvent + : public Event +{ +public: + EventType type() { return EventType::close; } +}; + +class ResizeEvent + : public Event +{ +public: + EventType type() { return EventType::resize; } + + size_t width; + size_t height; +}; + +class MoveEvent + : public Event +{ +public: + EventType type() { return EventType::move; } + + int x; + int y; +}; + +class MouseEnterEvent + : public Event +{ +public: + EventType type() { return EventType::mouseEnter; } + + int x; + int y; +}; + +class MouseLeaveEvent + : public Event +{ +public: + EventType type() { return EventType::mouseLeave; } + + int x; + int y; +}; + +using EventQueue = std::list>; + +struct Rect +{ + std::size_t x1; + std::size_t y1; + std::size_t x2; + std::size_t y2; + + bool empty() const + { + return x1 == x2 && y1 == y2; + } +}; + +} // GUI:: diff --git a/dggui/helpbutton.cc b/dggui/helpbutton.cc new file mode 100644 index 0000000..fa061a6 --- /dev/null +++ b/dggui/helpbutton.cc @@ -0,0 +1,75 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * helpbutton.cc + * + * Wed May 8 17:10:08 CEST 2019 + * Copyright 2019 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "helpbutton.h" + +#include "painter.h" + +#include + +namespace GUI +{ + +HelpButton::HelpButton(Widget* parent) + : ButtonBase(parent) + , tip(this) +{ + CONNECT(this, clickNotifier, this, &HelpButton::showHelpText); + tip.hide(); +} + +void HelpButton::setHelpText(const std::string& help_text) +{ + tip.setText(help_text); +} + +void HelpButton::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + bool state = true; + + // enabled and on + if(state) + { + if(button_state == ButtonBase::State::Down) + { + p.drawImage(0, 0, pushed); + } + else + { + p.drawImage(0, 0, normal); + } + return; + } +} + +void HelpButton::showHelpText() +{ + tip.show(); +} + +} // GUI:: diff --git a/dggui/helpbutton.h b/dggui/helpbutton.h new file mode 100644 index 0000000..6e97eca --- /dev/null +++ b/dggui/helpbutton.h @@ -0,0 +1,58 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * helpbutton.h + * + * Wed May 8 17:10:08 CEST 2019 + * Copyright 2019 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "texture.h" +#include "button_base.h" +#include "tooltip.h" + +namespace GUI +{ + +class HelpButton + : public ButtonBase +{ +public: + HelpButton(Widget* parent); + virtual ~HelpButton() = default; + + void setHelpText(const std::string& help_text); + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + void showHelpText(); + + Texture normal{getImageCache(), ":resources/help_button.png", 0, 0, 16, 16}; + Texture pushed{getImageCache(), ":resources/help_button.png", 16, 0, 16, 16}; + + Tooltip tip; +}; + +} // GUI:: diff --git a/dggui/image.cc b/dggui/image.cc new file mode 100644 index 0000000..118203e --- /dev/null +++ b/dggui/image.cc @@ -0,0 +1,216 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * image.cc + * + * Sat Mar 16 15:05:09 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "image.h" + +#include +#include +#include +#include + +#include + +#include "resource.h" +#include "lodepng/lodepng.h" + +namespace GUI +{ + +Image::Image(const char* data, size_t size) +{ + load(data, size); +} + +Image::Image(const std::string& filename) + : filename(filename) +{ + Resource rc(filename); + if(!rc.valid()) + { + setError(); + return; + } + load(rc.data(), rc.size()); +} + +Image::Image(Image&& other) + : _width(other._width) + , _height(other._height) + , image_data(std::move(other.image_data)) + , image_data_raw(std::move(other.image_data_raw)) + , filename(other.filename) +{ + other._width = 0; + other._height = 0; +} + +Image::~Image() +{ +} + +Image& Image::operator=(Image&& other) +{ + image_data.clear(); + image_data = std::move(other.image_data); + image_data_raw.clear(); + image_data_raw = std::move(other.image_data_raw); + _width = other._width; + _height = other._height; + valid = other.valid; + + other._width = 0; + other._height = 0; + other.valid = false; + return *this; +} + +void Image::setError() +{ + valid = false; + Resource rc(":resources/png_error"); + if(!rc.valid()) + { + _width = _height = 0u; + return; + } + + const unsigned char* ptr = (const unsigned char*)rc.data(); + + std::uint32_t iw, ih; + + iw = (uint32_t) ptr[0] | + (uint32_t) ptr[1] << 8 | + (uint32_t) ptr[2] << 16 | + (uint32_t) ptr[3] << 24; + ptr += sizeof(uint32_t); + + ih = (uint32_t) ptr[0] | + (uint32_t) ptr[1] << 8 | + (uint32_t) ptr[2] << 16 | + (uint32_t) ptr[3] << 24; + ptr += sizeof(uint32_t); + + _width = iw; + _height = ih; + + image_data.clear(); + image_data.reserve(_width * _height); + + image_data_raw.clear(); + image_data_raw.reserve(_width * _height * 4); + memcpy(image_data_raw.data(), ptr, _height * _width); + + for(std::size_t y = 0; y < _height; ++y) + { + for(std::size_t x = 0; x < _width; ++x) + { + image_data.emplace_back(Colour{ptr[0] / 255.0f, ptr[1] / 255.0f, + ptr[2] / 255.0f, ptr[3] / 255.0f}); + } + } + + assert(image_data.size() == (_width * _height)); +} + +void Image::load(const char* data, size_t size) +{ + has_alpha = false; + unsigned int iw{0}, ih{0}; + std::uint8_t* char_image_data{nullptr}; + unsigned int res = lodepng_decode32((std::uint8_t**)&char_image_data, + &iw, &ih, + (const std::uint8_t*)data, size); + + if(res != 0) + { + ERR(image, "Error in lodepng_decode32: %d while loading '%s'", + res, filename.c_str()); + setError(); + return; + } + + _width = iw; + _height = ih; + + image_data.clear(); + image_data.reserve(_width * _height); + + image_data_raw.clear(); + image_data_raw.reserve(_width * _height * 4); + memcpy(image_data_raw.data(), char_image_data, _height * _width * 4); + + for(std::size_t y = 0; y < _height; ++y) + { + for(std::size_t x = 0; x < _width; ++x) + { + std::uint8_t* ptr = &char_image_data[(x + y * _width) * 4]; + image_data.emplace_back(Colour{ptr[0], ptr[1], ptr[2], ptr[3]}); + has_alpha |= ptr[3] != 0xff; + } + } + + assert(image_data.size() == (_width * _height)); + + std::free(char_image_data); + valid = true; +} + +size_t Image::width() const +{ + return _width; +} + +size_t Image::height() const +{ + return _height; +} + +const Colour& Image::getPixel(size_t x, size_t y) const +{ + if(x > _width || y > _height) + { + return out_of_range; + } + + return image_data[x + y * _width]; +} + +const std::uint8_t* Image::line(std::size_t y, std::size_t x_offset) const +{ + return image_data_raw.data() + y * _width * 4 + x_offset * 4; +} + +bool Image::hasAlpha() const +{ + return has_alpha; +} + +bool Image::isValid() const +{ + return valid; +} + +} // GUI:: diff --git a/dggui/image.h b/dggui/image.h new file mode 100644 index 0000000..d162a75 --- /dev/null +++ b/dggui/image.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * image.h + * + * Sat Mar 16 15:05:08 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include "drawable.h" +#include "colour.h" +#include "resource.h" + +namespace GUI { + +class Image + : public Drawable +{ +public: + Image(const char* data, size_t size); + Image(const std::string& filename); + Image(Image&& other); + virtual ~Image(); + + Image& operator=(Image&& other); + + size_t width() const override; + size_t height() const override; + + const Colour& getPixel(size_t x, size_t y) const override; + const std::uint8_t* line(std::size_t y, + std::size_t x_offset = 0) const override; + + bool hasAlpha() const override; + + bool isValid() const; + +protected: + void setError(); + bool valid{false}; + + void load(const char* data, size_t size); + + std::size_t _width{0}; + std::size_t _height{0}; + std::vector image_data; + std::vector image_data_raw; + Colour out_of_range{0.0f, 0.0f, 0.0f, 0.0f}; + std::string filename; + bool has_alpha{false}; +}; + +} // GUI:: diff --git a/dggui/imagecache.cc b/dggui/imagecache.cc new file mode 100644 index 0000000..d3130fe --- /dev/null +++ b/dggui/imagecache.cc @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * imagecache.cc + * + * Thu Jun 2 17:12:05 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "imagecache.h" + +#include + +#include "image.h" + +namespace GUI +{ + +ScopedImageBorrower::ScopedImageBorrower(ImageCache& imageCache, + const std::string& filename) + : imageCache(imageCache) + , filename(filename) + , image(imageCache.borrow(filename)) +{ +} + +ScopedImageBorrower::ScopedImageBorrower(ScopedImageBorrower&& other) + : imageCache(other.imageCache) + , filename(other.filename) + , image(other.image) +{ + other.filename.clear(); +} + +ScopedImageBorrower::~ScopedImageBorrower() +{ + if(!filename.empty()) + { + imageCache.giveBack(filename); + } +} + +Image& ScopedImageBorrower::operator*() +{ + return image; +} + +Image& ScopedImageBorrower::operator()() +{ + return image; +} + +ScopedImageBorrower ImageCache::getImage(const std::string& filename) +{ + return ScopedImageBorrower(*this, filename); +} + +Image& ImageCache::borrow(const std::string& filename) +{ + auto cacheIterator = imageCache.find(filename); + if(cacheIterator == imageCache.end()) + { + Image image(filename); + auto insertValue = + imageCache.emplace(filename, std::make_pair(0, std::move(image))); + cacheIterator = insertValue.first; + } + + auto& cacheEntry = cacheIterator->second; + ++cacheEntry.first; + return cacheEntry.second; +} + +void ImageCache::giveBack(const std::string& filename) +{ + auto cacheIterator = imageCache.find(filename); + assert(cacheIterator != imageCache.end()); + auto& cacheEntry = cacheIterator->second; + --cacheEntry.first; + if(cacheEntry.first == 0) + { + imageCache.erase(cacheIterator); + } +} + +} // GUI:: diff --git a/dggui/imagecache.h b/dggui/imagecache.h new file mode 100644 index 0000000..d31a844 --- /dev/null +++ b/dggui/imagecache.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * imagecache.h + * + * Thu Jun 2 17:12:05 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include +#include + +namespace GUI +{ + +class Image; +class ImageCache; + +class ScopedImageBorrower +{ +public: + ScopedImageBorrower(ImageCache& imageCache, const std::string& filename); + ScopedImageBorrower(ScopedImageBorrower&& other); + virtual ~ScopedImageBorrower(); + + ScopedImageBorrower& operator=(ScopedImageBorrower&& other); + + Image& operator*(); + Image& operator()(); + +protected: + ImageCache& imageCache; + std::string filename; + Image& image; +}; + +class ImageCache +{ +public: + ScopedImageBorrower getImage(const std::string& filename); + +private: + friend class ScopedImageBorrower; + + Image& borrow(const std::string& filename); + void giveBack(const std::string& filename); + +protected: + std::map> imageCache; +}; + +} // GUI:: diff --git a/dggui/knob.cc b/dggui/knob.cc new file mode 100644 index 0000000..25200a7 --- /dev/null +++ b/dggui/knob.cc @@ -0,0 +1,255 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * knob.cc + * + * Thu Feb 28 07:37:27 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "knob.h" + +#include "painter.h" + +#include +#include + +namespace +{ +const double pi = std::atan(1.0) * 4.0; +} + +namespace GUI +{ + +Knob::Knob(Widget *parent) + : Widget(parent) + , img_knob(getImageCache(), ":resources/knob.png") +{ + state = up; + + maximum = 1.0; + minimum = 0.0; + + current_value = 0.0; + + mouse_offset_x = 0; +} + +void Knob::setValue(float value) +{ + value -= minimum; + value /= (maximum - minimum); + internalSetValue(value); +} + +void Knob::setDefaultValue(float value) +{ + default_value = value; +} + +void Knob::setRange(float minimum, float maximum) +{ + this->minimum = minimum; + this->maximum = maximum; + internalSetValue(current_value); +} + +float Knob::value() +{ + return current_value * (maximum - minimum) + minimum; +} + +void Knob::showValue(bool show_value) +{ + this->show_value = show_value; +} + +void Knob::scrollEvent(ScrollEvent* scrollEvent) +{ + float value = (current_value - (scrollEvent->delta / 200.0)); + internalSetValue(value); +} + +void Knob::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) +{ + if(state == down) + { + if(mouse_offset_x == (mouseMoveEvent->x + (-1 * mouseMoveEvent->y))) + { + return; + } + + float dval = + mouse_offset_x - (mouseMoveEvent->x + (-1 * mouseMoveEvent->y)); + float value = current_value - (dval / 300.0); + + internalSetValue(value); + + mouse_offset_x = mouseMoveEvent->x + (-1 * mouseMoveEvent->y); + } +} + +void Knob::keyEvent(KeyEvent* keyEvent) +{ + if(keyEvent->direction != Direction::up) + { + return; + } + + float value = current_value; + switch(keyEvent->keycode) { + case Key::up: + value += 0.01; + break; + case Key::down: + value -= 0.01; + break; + case Key::right: + value += 0.01; + break; + case Key::left: + value -= 0.01; + break; + case Key::home: + value = 0; + break; + case Key::end: + value = 1; + break; + default: + break; + } + + internalSetValue(value); +} + +void Knob::buttonEvent(ButtonEvent* buttonEvent) +{ + // Ignore everything except left clicks. + if(buttonEvent->button != MouseButton::left) + { + return; + } + + if(buttonEvent->doubleClick) + { + float value = default_value; + value -= minimum; + value /= (maximum - minimum); + internalSetValue(value); + return; + } + + if(buttonEvent->direction == Direction::down) + { + state = down; + mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y); + return; + } + + if(buttonEvent->direction == Direction::up) + { + state = up; + mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y); + clicked(); + return; + } +} + +void Knob::repaintEvent(RepaintEvent* repaintEvent) +{ + int diameter = (width()>height()?height():width()); + int radius = diameter / 2; + int center_x = width() / 2; + int center_y = height() / 2; + + Painter p(*this); + p.clear(); + + p.drawImageStretched(0, 0, img_knob, diameter, diameter); + + float range = maximum - minimum; + + if (show_value) { + // Show 0, 1 or 2 decimal point depending on the size of the range + char buf[64]; + if(range> 100.0f) + { + sprintf(buf, "%.0f", current_value * range + minimum); + } + else if(range > 10.0f) + { + sprintf(buf, "%.1f", current_value * range + minimum); + } + else + { + sprintf(buf, "%.2f", current_value * range + minimum); + } + p.drawText(center_x - font.textWidth(buf) / 2 + 1, + center_y + font.textHeight(buf) / 2 + 1, font, buf); + } + + // Make it start from 20% and stop at 80% + double padval = current_value * 0.8 + 0.1; + + double from_x = sin((-1 * padval + 1) * 2 * pi) * radius * 0.6; + double from_y = cos((-1 * padval + 1) * 2 * pi) * radius * 0.6; + + double to_x = sin((-1 * padval + 1) * 2 * pi) * radius * 0.8; + double to_y = cos((-1 * padval + 1) * 2 * pi) * radius * 0.8; + + // Draw "fat" line by drawing 9 lines with moved start/ending points. + p.setColour(Colour(1.0f, 0.0f, 0.0f, 1.0f)); + for(int _x = -1; _x < 2; _x++) + { + for(int _y = -1; _y < 2; _y++) + { + p.drawLine(from_x + center_x + _x, + from_y + center_y + _y, + to_x + center_x + _x, + to_y + center_y + _y); + } + } +} + +void Knob::internalSetValue(float new_value) +{ + if(new_value < 0.0) + { + new_value = 0.0; + } + + if(new_value > 1.0) + { + new_value = 1.0; + } + + if(new_value == current_value) + { + return; + } + + current_value = new_value; + valueChangedNotifier(value()); + redraw(); +} + +} // GUI:: diff --git a/dggui/knob.h b/dggui/knob.h new file mode 100644 index 0000000..fc71511 --- /dev/null +++ b/dggui/knob.h @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * knob.h + * + * Thu Feb 28 07:37:27 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "widget.h" +#include "texture.h" +#include "font.h" + +namespace GUI { + +class Knob : public Widget { +public: + Knob(Widget *parent); + virtual ~Knob() = default; + + // From Widget: + bool catchMouse() override { return true; } + bool isFocusable() override { return true; } + + void setValue(float value); + void setDefaultValue(float value); + void setRange(float minimum, float maximum); + float value(); + void showValue(bool show_value); + + Notifier valueChangedNotifier; // (float newValue) + +protected: + virtual void clicked() {} + + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; + virtual void scrollEvent(ScrollEvent* scrollEvent) override; + virtual void keyEvent(KeyEvent* keyEvent) override; + +private: + //! Sets the internal value and sends out the changed notification. + void internalSetValue(float value); + + typedef enum { + up, + down + } state_t; + + state_t state; + + float current_value; + float default_value = 0.0; + float maximum; + float minimum; + + bool show_value{true}; + + Texture img_knob; + + int mouse_offset_x; + Font font; +}; + +} // GUI:: diff --git a/dggui/label.cc b/dggui/label.cc new file mode 100644 index 0000000..b5239ec --- /dev/null +++ b/dggui/label.cc @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * label.cc + * + * Sun Oct 9 13:02:18 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "label.h" + +#include "painter.h" +#include "guievent.h" + +#include + +namespace GUI { + +Label::Label(Widget *parent) + : Widget(parent) +{ +} + +void Label::setText(const std::string& text) +{ + _text = text; + redraw(); +} + +void Label::setAlignment(TextAlignment alignment) +{ + this->alignment = alignment; +} + +void Label::setColour(Colour colour) +{ + this->colour = std::make_unique(colour); + redraw(); +} + +void Label::resetColour() +{ + colour.release(); + redraw(); +} + +void Label::resizeToText() +{ + resize(font.textWidth(_text) + border, font.textHeight()); +} + +void Label::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + p.clear(); + + int offset = 0; + switch(alignment) { + case TextAlignment::left: + offset = border; + break; + case TextAlignment::center: + offset = (width() - font.textWidth(_text)) / 2; + break; + case TextAlignment::right: + offset = width() - font.textWidth(_text) - border; + break; + } + + if (colour) { + p.setColour(*colour); + p.drawText(offset, (height() + font.textHeight()) / 2, font, _text); + } + else { + p.drawText(offset, (height() + font.textHeight()) / 2, font, _text, true); + } +} + +} // GUI:: diff --git a/dggui/label.h b/dggui/label.h new file mode 100644 index 0000000..45b4176 --- /dev/null +++ b/dggui/label.h @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * label.h + * + * Sun Oct 9 13:02:17 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "widget.h" + +#include "font.h" + +#include +#include + +namespace GUI { + +enum class TextAlignment { + left, + center, + right, +}; + +class Label : public Widget { +public: + Label(Widget *parent); + virtual ~Label() = default; + + void setText(const std::string& text); + void setAlignment(TextAlignment alignment); + void setColour(Colour colour); + void resetColour(); + void resizeToText(); + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + std::string _text; + Font font{":resources/fontemboss.png"}; + TextAlignment alignment{TextAlignment::left}; + int border{0}; + + // optional colour + std::unique_ptr colour; +}; + +} // GUI:: diff --git a/dggui/layout.cc b/dggui/layout.cc new file mode 100644 index 0000000..61e4f77 --- /dev/null +++ b/dggui/layout.cc @@ -0,0 +1,386 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * layout.cc + * + * Sat Mar 21 15:12:36 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "layout.h" + +#include "widget.h" + +#include + +namespace GUI +{ + +LayoutItem::LayoutItem() + : parent(nullptr) +{ +} + +LayoutItem::~LayoutItem() +{ + setLayoutParent(nullptr); // Will disconnect from layout if any. +} + +void LayoutItem::setLayoutParent(Layout* p) +{ + if(this->parent) + { + this->parent->removeItem(this); + } + + this->parent = p; +} + +Layout::Layout(LayoutItem* parent) : parent(parent) +{ + auto widget = dynamic_cast(parent); + if(widget) + { + CONNECT(widget, sizeChangeNotifier, this, &Layout::sizeChanged); + } +} + +void Layout::addItem(LayoutItem* item) +{ + items.push_back(item); + item->setLayoutParent(this); + layout(); +} + +void Layout::removeItem(LayoutItem* item) +{ + auto new_end = std::remove(items.begin(), items.end(), item); + items.erase(new_end, items.end()); + + layout(); +} + +void Layout::sizeChanged(int width, int height) +{ + layout(); +} + +// +// BoxLayout +// + +BoxLayout::BoxLayout(LayoutItem* parent) : Layout(parent) +{ +} + +void BoxLayout::setResizeChildren(bool resizeChildren) +{ + this->resizeChildren = resizeChildren; + layout(); +} + +void BoxLayout::setSpacing(size_t spacing) +{ + this->spacing = spacing; + layout(); +} + +// +// VBoxLayout +// + +VBoxLayout::VBoxLayout(LayoutItem* parent) + : BoxLayout(parent) + , align(HAlignment::center) +{ +} + +void VBoxLayout::layout() +{ + size_t y = 0; + size_t w = parent->width(); + // size_t h = parent->height() / items.size(); + + LayoutItemList::iterator i = items.begin(); + while(i != items.end()) + { + LayoutItem* item = *i; + + if(resizeChildren) + { + auto num_items = items.size(); + auto empty_space = (num_items - 1) * spacing; + auto available_space = parent->height(); + + if(available_space >= empty_space) + { + auto item_height = (available_space - empty_space) / num_items; + item->resize(w, item_height); + } + else + { + // TODO: Should this case be handled differently? + item->resize(w, 0); + } + } + + size_t x = 0; + switch(align) + { + case HAlignment::left: + x = 0; + break; + case HAlignment::center: + x = (w / 2) - (item->width() / 2); + break; + case HAlignment::right: + x = w - item->width(); + break; + } + + item->move(x, y); + y += item->height() + spacing; + ++i; + } +} + +void VBoxLayout::setHAlignment(HAlignment alignment) +{ + align = alignment; +} + +// +// HBoxLayout +// + +HBoxLayout::HBoxLayout(LayoutItem* parent) + : BoxLayout(parent) + , align(VAlignment::center) +{ +} + +void HBoxLayout::layout() +{ + if(items.empty()) + { + return; + } + + // size_t w = parent->width() / items.size(); + size_t h = parent->height(); + size_t x = 0; + + LayoutItemList::iterator i = items.begin(); + while(i != items.end()) + { + LayoutItem* item = *i; + if(resizeChildren) + { + auto num_items = items.size(); + auto empty_space = (num_items - 1) * spacing; + auto available_space = parent->width(); + + if(available_space >= empty_space) + { + auto item_width = (available_space - empty_space) / num_items; + item->resize(item_width, h); + } + else + { + // TODO: Should this case be handled differently? + item->resize(0, h); + } + + item->move(x, 0); + } + else + { + size_t y = 0; + switch(align) + { + case VAlignment::top: + y = 0; + break; + case VAlignment::center: + y = (h / 2) - (item->height() / 2); + break; + case VAlignment::bottom: + y = h - item->height(); + break; + } + + int diff = 0; // w - item->width(); + item->move(x + diff / 2, y); + } + x += item->width() + spacing; + ++i; + } +} + +void HBoxLayout::setVAlignment(VAlignment alignment) +{ + align = alignment; +} + +// +// GridLayout +// + +GridLayout::GridLayout(LayoutItem* parent, std::size_t number_of_columns, + std::size_t number_of_rows) + : BoxLayout(parent) + , number_of_columns(number_of_columns) + , number_of_rows(number_of_rows) +{ +} + +void GridLayout::removeItem(LayoutItem* item) +{ + // manually remove from grid_ranges as remove_if doesn't work on an + // unordered_map. + auto it = grid_ranges.begin(); + while(it != grid_ranges.end()) + { + if(it->first == item) + { + it = grid_ranges.erase(it); + } + else + { + ++it; + } + } + + Layout::removeItem(item); +} + +void GridLayout::layout() +{ + if(grid_ranges.empty()) + { + return; + } + + // Calculate cell sizes + auto cell_size = calculateCellSize(); + + for(auto const& pair : grid_ranges) + { + auto& item = *pair.first; + auto const& range = pair.second; + + moveAndResize(item, range, cell_size); + } +} + +void GridLayout::setPosition(LayoutItem* item, GridRange const& range) +{ + grid_ranges[item] = range; +} + +int GridLayout::lastUsedRow(int column) const +{ + int last_row = -1; + + for (auto const& grid_range : grid_ranges) + { + auto const& range = grid_range.second; + if (column >= range.column_begin && column < range.column_end) + { + last_row = std::max(last_row, range.row_end - 1); + } + } + + return last_row; +} + +int GridLayout::lastUsedColumn(int row) const +{ + int last_column = -1; + + for (auto const& grid_range : grid_ranges) + { + auto const& range = grid_range.second; + if (row >= range.row_begin && row < range.row_end) + { + last_column = std::max(last_column, range.column_end - 1); + } + } + + return last_column; + +} + +auto GridLayout::calculateCellSize() const -> CellSize +{ + auto empty_width = (number_of_columns - 1) * spacing; + auto available_width = parent->width(); + auto empty_height = (number_of_rows - 1) * spacing; + auto available_height = parent->height(); + + CellSize cell_size; + if(available_width > empty_width && available_height > empty_height) + { + cell_size.width = (available_width - empty_width) / number_of_columns; + cell_size.height = (available_height - empty_height) / number_of_rows; + } + else + { + cell_size.width = 0; + cell_size.height = 0; + } + + return cell_size; +} + +void GridLayout::moveAndResize( + LayoutItem& item, GridRange const& range, CellSize cell_size) const +{ + std::size_t x = range.column_begin * (cell_size.width + spacing); + std::size_t y = range.row_begin * (cell_size.height + spacing); + + std::size_t column_count = (range.column_end - range.column_begin); + std::size_t row_count = (range.row_end - range.row_begin); + std::size_t width = column_count * (cell_size.width + spacing) - spacing; + std::size_t height = row_count * (cell_size.height + spacing) - spacing; + + if(resizeChildren) + { + item.move(x, y); + + if(cell_size.width * cell_size.height != 0) + { + item.resize(width, height); + } + else + { + item.resize(0, 0); + } + } + else + { + auto x_new = (item.width() > width) ? x : x + (width - item.width()) / 2; + auto y_new = (item.height() > height) ? y : y + (height - item.height()) / 2; + + item.move(x_new, y_new); + } +} + +} // GUI:: diff --git a/dggui/layout.h b/dggui/layout.h new file mode 100644 index 0000000..210c86e --- /dev/null +++ b/dggui/layout.h @@ -0,0 +1,195 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * layout.h + * + * Sat Mar 21 15:12:36 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include +#include + +#include + +namespace GUI +{ + +class Layout; + +class LayoutItem +{ +public: + LayoutItem(); + virtual ~LayoutItem(); + + void setLayoutParent(Layout* parent); + + virtual void resize(std::size_t width, std::size_t height) = 0; + virtual void move(int x, int y) = 0; + virtual int x() const = 0; + virtual int y() const = 0; + virtual std::size_t width() const = 0; + virtual std::size_t height() const = 0; + +private: + Layout* parent; +}; + +//! \brief Abtract Layout class. +class Layout : public Listener +{ +public: + Layout(LayoutItem* parent); + virtual ~Layout() + { + } + + virtual void addItem(LayoutItem* item); + virtual void removeItem(LayoutItem* item); + + //! \brief Reimplement this method to create a new Layout rule. + virtual void layout() = 0; + +protected: + void sizeChanged(int width, int height); + + LayoutItem* parent; + typedef std::list LayoutItemList; + LayoutItemList items; +}; + +//! \brief Abstract box layout +class BoxLayout : public Layout +{ +public: + BoxLayout(LayoutItem* parent); + + //! \brief Set to false to only move the items, not scale them. + void setResizeChildren(bool resize_children); + + void setSpacing(size_t spacing); + + // From Layout: + virtual void layout() override = 0; + +protected: + bool resizeChildren{false}; + size_t spacing{0}; +}; + +enum class HAlignment +{ + left, + center, + right, +}; + +//! \brief A Layout that lays out its elements vertically. +class VBoxLayout : public BoxLayout +{ +public: + VBoxLayout(LayoutItem* parent); + + void setHAlignment(HAlignment alignment); + + // From BoxLayout: + virtual void layout() override; + +protected: + HAlignment align; +}; + +enum class VAlignment +{ + top, + center, + bottom, +}; + +//! \brief A Layout that lays out its elements vertically. +class HBoxLayout : public BoxLayout +{ +public: + HBoxLayout(LayoutItem* parent); + + void setVAlignment(VAlignment alignment); + + // From BoxLayout: + virtual void layout() override; + +protected: + VAlignment align; +}; + +//! \brief A Layout class which places the items in a regular grid. An item can +//! span multiple rows/columns. +class GridLayout : public BoxLayout +{ +public: + // The range is open, i.e. end is one past the last one. + struct GridRange + { + int column_begin; + int column_end; + int row_begin; + int row_end; + }; + + GridLayout(LayoutItem* parent, std::size_t number_of_columns, + std::size_t number_of_rows); + + virtual ~GridLayout() + { + } + + // From Layout: + virtual void removeItem(LayoutItem* item); + virtual void layout(); + + void setPosition(LayoutItem* item, GridRange const& range); + + int lastUsedRow(int column) const; + int lastUsedColumn(int row) const; + +protected: + std::size_t number_of_columns; + std::size_t number_of_rows; + + // Note: Yes, this is somewhat redundant to the LayoutItemList of the Layout + // class. However, this was the best idea I had such that I could still + // derive from Layout. If you find this ugly, feel free to fix it. + std::unordered_map grid_ranges; + +private: + struct CellSize { + std::size_t width; + std::size_t height; + }; + + CellSize calculateCellSize() const; + void moveAndResize( + LayoutItem& item, GridRange const& range, CellSize cell_size) const; +}; + +} // GUI:: diff --git a/dggui/led.cc b/dggui/led.cc new file mode 100644 index 0000000..f77e31a --- /dev/null +++ b/dggui/led.cc @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * led.cc + * + * Sat Oct 15 19:12:33 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "led.h" + +#include "painter.h" + +namespace GUI { + +LED::LED(Widget *parent) + : Widget(parent) + , state(Off) +{ +} + +void LED::setState(state_t state) +{ + if(this->state != state) + { + this->state = state; + redraw(); + } +} + +void LED::repaintEvent(RepaintEvent* repaintEvent) +{ + size_t h = height() - 1; + size_t w = width() - 1; + + Painter p(*this); + float alpha = 0.9; + switch(state) { + case Red: + p.setColour(Colour(1, 0, 0,alpha)); + break; + case Green: + p.setColour(Colour(0, 1, 0, alpha)); + break; + case Blue: + p.setColour(Colour(0, 0, 1, alpha)); + break; + case Off: + p.setColour(Colour(0.2, 0.2, 0.2, alpha)); + break; + } + + size_t size = w / 2; + if((h / 2) < size) + { + size = h / 2; + } + p.drawFilledCircle(w / 2, h / 2, size); + + switch(state) { + case Red: + p.setColour(Colour(0.4, 0, 0, alpha)); + break; + case Green: + p.setColour(Colour(0, 0.4, 0, alpha)); + break; + case Blue: + p.setColour(Colour(0, 0, 0.4, alpha)); + break; + case Off: + p.setColour(Colour(0.1, 0.1, 0.1, alpha)); + break; + } + p.drawCircle(w / 2, h / 2, size); + + p.setColour(Colour(1, alpha)); + p.drawFilledCircle(w / 3, h / 3, size / 6); +} + +} // GUI:: diff --git a/dggui/led.h b/dggui/led.h new file mode 100644 index 0000000..14ab6ef --- /dev/null +++ b/dggui/led.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * led.h + * + * Sat Oct 15 19:12:33 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "widget.h" + +namespace GUI { + +class LED : public Widget { +public: + typedef enum { + Red, + Green, + Blue, + Off + } state_t; + + LED(Widget *parent); + + void setState(state_t state); + +protected: + // From Widget: + void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + state_t state; +}; + +} // GUI:: diff --git a/dggui/lineedit.cc b/dggui/lineedit.cc new file mode 100644 index 0000000..14cc234 --- /dev/null +++ b/dggui/lineedit.cc @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * lineedit.cc + * + * Sun Oct 9 13:01:52 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "lineedit.h" + +#include +#include + +#define BORDER 10 + +namespace GUI { + +LineEdit::LineEdit(Widget *parent) + : Widget(parent) +{ + setReadOnly(false); +} + +LineEdit::~LineEdit() +{ +} + +void LineEdit::setReadOnly(bool ro) +{ + readonly = ro; +} + +bool LineEdit::readOnly() +{ + return readonly; +} + +void LineEdit::setText(const std::string& text) +{ + _text = text; + pos = text.size(); + + visibleText = _text; + offsetPos = 0; + + redraw(); + textChanged(); +} + +std::string LineEdit::getText() +{ + return _text; +} + +void LineEdit::buttonEvent(ButtonEvent *buttonEvent) +{ + if(readOnly()) + { + return; + } + + // Ignore everything except left clicks. + if(buttonEvent->button != MouseButton::left) + { + return; + } + + if(buttonEvent->direction == Direction::down) + { + for(int i = 0; i < (int)visibleText.length(); ++i) + { + int textWidth = font.textWidth(visibleText.substr(0, i)); + if(buttonEvent->x < (textWidth + BORDER)) + { + pos = i + offsetPos; + break; + } + } + redraw(); + } +} + +void LineEdit::keyEvent(KeyEvent *keyEvent) +{ + if(readOnly()) + { + return; + } + + bool change = false; + + if(keyEvent->direction == Direction::down) + { + switch(keyEvent->keycode) { + case Key::left: + if(pos == 0) + { + return; + } + + pos--; + + if(offsetPos >= pos) + { + walkstate = WalkLeft; + } + break; + + case Key::right: + if(pos == _text.length()) + { + return; + } + + pos++; + + if((pos < _text.length()) && ((offsetPos + visibleText.length()) <= pos)) + { + walkstate = WalkRight; + } + break; + + case Key::home: + pos = 0; + visibleText = _text; + offsetPos = 0; + break; + + case Key::end: + pos = _text.length(); + visibleText = _text; + offsetPos = 0; + break; + + case Key::deleteKey: + if(pos < _text.length()) + { + std::string t = _text.substr(0, pos); + t += _text.substr(pos + 1, std::string::npos); + _text = t; + change = true; + } + break; + + case Key::backspace: + if(pos > 0) + { + std::string t = _text.substr(0, pos - 1); + t += _text.substr(pos, std::string::npos); + _text = t; + pos--; + change = true; + } + break; + + case Key::character: + { + std::string pre = _text.substr(0, pos); + std::string post = _text.substr(pos, std::string::npos); + _text = pre + keyEvent->text + post; + change = true; + pos++; + } + break; + + case Key::enter: + enterPressedNotifier(); + break; + + default: + break; + } + + redraw(); + } + + if(change) + { + textChanged(); + } +} + +void LineEdit::repaintEvent(RepaintEvent *repaintEvent) +{ + Painter p(*this); + + int w = width(); + int h = height(); + if((w == 0) || (h == 0)) + { + return; + } + + box.setSize(w, h); + p.drawImage(0, 0, box); + + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); + + switch(walkstate) { + case WalkLeft: + visibleText = _text.substr(pos, std::string::npos); + offsetPos = pos; + break; + + case WalkRight: + { + int delta = (offsetPos < _text.length()) ? 1 : 0; + visibleText = _text.substr(offsetPos + delta); + offsetPos = offsetPos + delta; + } + break; + + case Noop: + visibleText = _text; + offsetPos = 0; + break; + } + + while(true) + { + int textWidth = font.textWidth(visibleText); + if(textWidth <= std::max(w - BORDER - 4 + 3, 0)) + { + break; + } + + switch(walkstate) { + case WalkLeft: + visibleText = visibleText.substr(0, visibleText.length() - 1); + break; + + case WalkRight: + visibleText = visibleText.substr(0, visibleText.length() - 1); + break; + + case Noop: + if(offsetPos < pos) + { + visibleText = visibleText.substr(1); + offsetPos++; + } + else + { + visibleText = visibleText.substr(0, visibleText.length() - 1); + } + break; + } + } + + walkstate = Noop; + + p.drawText(BORDER - 4 + 3, height() / 2 + 5 + 1 + 1 + 1, font, visibleText); + + if(readOnly()) + { + return; + } + + if(hasKeyboardFocus()) + { + size_t px = font.textWidth(visibleText.substr(0, pos - offsetPos)); + p.drawLine(px + BORDER - 1 - 4 + 3, 6, + px + BORDER - 1 - 4 + 3, height() - 7); + } +} + +} // GUI:: diff --git a/dggui/lineedit.h b/dggui/lineedit.h new file mode 100644 index 0000000..86ad986 --- /dev/null +++ b/dggui/lineedit.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * lineedit.h + * + * Sun Oct 9 13:01:52 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "widget.h" +#include "font.h" +#include "painter.h" +#include "texturedbox.h" + +namespace GUI +{ + +class LineEdit + : public Widget +{ +public: + LineEdit(Widget *parent); + virtual ~LineEdit(); + + bool isFocusable() override { return true; } + + std::string getText(); + void setText(const std::string& text); + + void setReadOnly(bool readonly); + bool readOnly(); + + Notifier<> enterPressedNotifier; + + //protected: + virtual void keyEvent(KeyEvent *keyEvent) override; + virtual void repaintEvent(RepaintEvent *repaintEvent) override; + virtual void buttonEvent(ButtonEvent *buttonEvent) override; + +protected: + virtual void textChanged() {} + +private: + TexturedBox box{getImageCache(), ":resources/widget.png", + 0, 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 7, 63, 7}; // dy1, dy2, dy3 + + Font font; + + std::string _text; + size_t pos{0}; + std::string visibleText; + size_t offsetPos{0}; + + enum state_t { + Noop, + WalkLeft, + WalkRight, + }; + state_t walkstate{Noop}; + + bool readonly; +}; + +} // GUI:: diff --git a/dggui/listbox.cc b/dggui/listbox.cc new file mode 100644 index 0000000..28c074e --- /dev/null +++ b/dggui/listbox.cc @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listbox.cc + * + * Mon Feb 25 21:21:41 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "listbox.h" + +#include "painter.h" +#include "font.h" + +namespace GUI { + +ListBox::ListBox(Widget *parent) + : Widget(parent) + , selectionNotifier(basic.selectionNotifier) + , clickNotifier(basic.clickNotifier) + , valueChangedNotifier(basic.valueChangedNotifier) + , basic(this) +{ + basic.move(7, 7); +} + +ListBox::~ListBox() +{ +} + +void ListBox::addItem(std::string name, std::string value) +{ + basic.addItem(name, value); +} + +void ListBox::addItems(std::vector &items) +{ + basic.addItems(items); +} + +void ListBox::clear() +{ + basic.clear(); +} + +bool ListBox::selectItem(int index) +{ + return basic.selectItem(index); +} + +std::string ListBox::selectedName() +{ + return basic.selectedName(); +} + +std::string ListBox::selectedValue() +{ + return basic.selectedValue(); +} + +void ListBox::clearSelectedValue() +{ + basic.clearSelectedValue(); +} + +void ListBox::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } + + box.setSize(w, h); + p.drawImage(0, 0, box); +} + +void ListBox::resize(std::size_t width, std::size_t height) +{ + Widget::resize(width, height); + basic.resize(width - (7 + 7), + height - (7 + 7)); +} + +} // GUI:: diff --git a/dggui/listbox.h b/dggui/listbox.h new file mode 100644 index 0000000..0d9ad4d --- /dev/null +++ b/dggui/listbox.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listbox.h + * + * Mon Feb 25 21:21:40 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include "widget.h" +#include "painter.h" +#include "listboxbasic.h" +#include "texturedbox.h" + +namespace GUI +{ + +class ListBox + : public Widget +{ +public: + ListBox(Widget *parent); + virtual ~ListBox(); + + void addItem(std::string name, std::string value); + void addItems(std::vector &items); + + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); + void clearSelectedValue(); + + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void resize(std::size_t width, std::size_t height) override; + + // Forwarded notifiers from ListBoxBasic::basic + Notifier<>& selectionNotifier; + Notifier<>& clickNotifier; + Notifier<>& valueChangedNotifier; + +private: + ListBoxBasic basic; + + TexturedBox box{getImageCache(), ":resources/widget.png", + 0, 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 7, 63, 7}; // dy1, dy2, dy3 +}; + +} // GUI:: diff --git a/dggui/listboxbasic.cc b/dggui/listboxbasic.cc new file mode 100644 index 0000000..b2637eb --- /dev/null +++ b/dggui/listboxbasic.cc @@ -0,0 +1,362 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listboxbasic.cc + * + * Thu Apr 4 20:28:10 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "listboxbasic.h" + +#include "painter.h" +#include "font.h" + +namespace GUI { + +ListBoxBasic::ListBoxBasic(Widget *parent) + : Widget(parent) + , scroll(this) +{ + scroll.move(0,0); + scroll.resize(16, 100); + + CONNECT(&scroll, valueChangeNotifier, + this, &ListBoxBasic::onScrollBarValueChange); + + padding = 4; + btn_size = 18; + + selected = -1; + marked = -1; +} + +ListBoxBasic::~ListBoxBasic() +{ +} + +void ListBoxBasic::setSelection(int index) +{ + selected = index; + if(marked == -1) + { + marked = index; + } + valueChangedNotifier(); +} + +void ListBoxBasic::addItem(const std::string& name, const std::string& value) +{ + std::vector items; + ListBoxBasic::Item item; + item.name = name; + item.value = value; + items.push_back(item); + addItems(items); +} + +void ListBoxBasic::addItems(const std::vector& newItems) +{ + for(auto& item : newItems) + { + items.push_back(item); + } + + if(selected == -1) + { + //setSelection((int)items.size() - 1); + setSelection(0); + } + redraw(); +} + +void ListBoxBasic::clear() +{ + items.clear(); + setSelection(-1); + marked = -1; + scroll.setValue(0); + redraw(); +} + +bool ListBoxBasic::selectItem(int index) +{ + if(index < 0 || (index > (int)items.size() - 1)) + { + return false; + } + + setSelection(index); + redraw(); + + return true; +} + +std::string ListBoxBasic::selectedName() +{ + if(selected < 0 || (selected > (int)items.size() - 1)) + { + return ""; + } + + return items[selected].name; +} + +std::string ListBoxBasic::selectedValue() +{ + if(selected < 0 || (selected > (int)items.size() - 1)) + { + return ""; + } + + return items[selected].value; +} + +void ListBoxBasic::clearSelectedValue() +{ + setSelection(-1); +} + +void ListBoxBasic::onScrollBarValueChange(int value) +{ + redraw(); +} + +void ListBoxBasic::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + int w = width(); + int h = height(); + + if((w == 0) || (h == 0)) + { + return; + } + + p.drawImageStretched(0, 0, bg_img, w, h); + + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); + + int yoffset = padding / 2; + int skip = scroll.value(); + int numitems = height() / (font.textHeight() + padding) + 1; + for(int idx = skip; (idx < (int)items.size()) && (idx < (skip + numitems)); + idx++) + { + auto& item = items[idx]; + if(idx == selected) + { + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 0.5f)); + p.drawFilledRectangle(0, + yoffset - (padding / 2), + width() - 1, + yoffset + (font.textHeight() + 1)); + } + + if(idx == marked) + { + p.drawRectangle(0, + yoffset - (padding / 2), + width() - 1, + yoffset + (font.textHeight() + 1)); + } + + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); + + p.drawText(2, yoffset + font.textHeight(), font, item.name); + yoffset += font.textHeight() + padding; + } + + scroll.setRange(numitems); + scroll.setMaximum(items.size()); +} + +void ListBoxBasic::scrollEvent(ScrollEvent* scrollEvent) +{ + // forward scroll event to scroll bar. + scroll.scrollEvent(scrollEvent); +} + +void ListBoxBasic::keyEvent(KeyEvent* keyEvent) +{ + if(keyEvent->direction != Direction::down) + { + return; + } + + switch(keyEvent->keycode) { + case Key::up: + if(marked == 0) + { + return; + } + + marked--; + + if(marked < scroll.value()) + { + scroll.setValue(marked); + } + break; + + case Key::down: + { + // Number of items that can be displayed at a time. + int numitems = height() / (font.textHeight() + padding); + + if(marked == ((int)items.size() - 1)) + { + return; + } + + marked++; + + if(marked > (scroll.value() + numitems - 1)) + { + scroll.setValue(marked - numitems + 1); + } + } + break; + + case Key::home: + marked = 0; + if(marked < scroll.value()) + { + scroll.setValue(marked); + } + break; + + case Key::end: + { + // Number of items that can be displayed at a time. + int numitems = height() / (font.textHeight() + padding); + + marked = (int)items.size() - 1; + if(marked > (scroll.value() + numitems - 1)) + { + scroll.setValue(marked - numitems + 1); + } + } + break; + + case Key::character: + if(keyEvent->text == " ") + { + setSelection(marked); + //selectionNotifier(); + } + break; + + case Key::enter: + setSelection(marked); + selectionNotifier(); + break; + + default: + break; + } + + redraw(); +} + +void ListBoxBasic::buttonEvent(ButtonEvent* buttonEvent) +{ + // Ignore everything except left clicks. + if(buttonEvent->button != MouseButton::left) + { + return; + } + + if((buttonEvent->x > ((int)width() - btn_size)) && + (buttonEvent->y < ((int)width() - 1))) + { + if(buttonEvent->y > 0 && buttonEvent->y < btn_size) + { + if(buttonEvent->direction == Direction::up) + { + return; + } + scroll.setValue(scroll.value() - 1); + return; + } + + if(buttonEvent->y > ((int)height() - btn_size) && + buttonEvent->y < ((int)height() - 1)) + { + if(buttonEvent->direction == Direction::up) + { + return; + } + scroll.setValue(scroll.value() + 1); + return; + } + } + + if(buttonEvent->direction == Direction::up) + { + int skip = scroll.value(); + size_t yoffset = padding / 2; + for(int idx = skip; idx < (int)items.size(); idx++) + { + yoffset += font.textHeight() + padding; + if(buttonEvent->y < (int)yoffset - (padding / 2)) + { + setSelection(idx); + marked = selected; + clickNotifier(); + break; + } + } + + redraw(); + } + + if(buttonEvent->direction != Direction::up) + { + int skip = scroll.value(); + size_t yoffset = padding / 2; + for(int idx = skip; idx < (int)items.size(); idx++) + { + yoffset += font.textHeight() + padding; + if(buttonEvent->y < ((int)yoffset - (padding / 2))) + { + marked = idx; + break; + } + } + + redraw(); + } + + if(buttonEvent->doubleClick) + { + selectionNotifier(); + } +} + +void ListBoxBasic::resize(std::size_t width, std::size_t height) +{ + Widget::resize(width, height); + scroll.move(width - scroll.width(), 0); + scroll.resize(scroll.width(), height); +} + +} // GUI:: diff --git a/dggui/listboxbasic.h b/dggui/listboxbasic.h new file mode 100644 index 0000000..27822e6 --- /dev/null +++ b/dggui/listboxbasic.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listboxbasic.h + * + * Thu Apr 4 20:28:10 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include + +#include "widget.h" +#include "font.h" +#include "painter.h" +#include "scrollbar.h" + +namespace GUI { + +class ListBoxBasic : public Widget { +public: + class Item { + public: + std::string name; + std::string value; + }; + + ListBoxBasic(Widget *parent); + virtual ~ListBoxBasic(); + + void addItem(const std::string& name, const std::string& value); + void addItems(const std::vector& items); + + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); + + void clearSelectedValue(); + + Notifier<> selectionNotifier; + Notifier<> clickNotifier; + Notifier<> valueChangedNotifier; + + // From Widget: + virtual void resize(std::size_t width, std::size_t height) override; + +protected: + void onScrollBarValueChange(int value); + + // From Widget: + bool isFocusable() override { return true; } + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void keyEvent(KeyEvent* keyEvent) override; + virtual void scrollEvent(ScrollEvent* scrollEvent) override; + + ScrollBar scroll; + + Texture bg_img{getImageCache(), ":resources/widget.png", 7, 7, 1, 63}; + + void setSelection(int index); + + std::vector items; + + int selected; + int marked; + Font font; + int padding; + int btn_size; +}; + +} // GUI:: diff --git a/dggui/listboxthin.cc b/dggui/listboxthin.cc new file mode 100644 index 0000000..d224f11 --- /dev/null +++ b/dggui/listboxthin.cc @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listboxthin.cc + * + * Sun Apr 7 19:39:36 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "listboxthin.h" + +#include "painter.h" +#include "font.h" + +namespace GUI +{ + +ListBoxThin::ListBoxThin(Widget *parent) + : Widget(parent) + , selectionNotifier(basic.selectionNotifier) + , clickNotifier(basic.clickNotifier) + , valueChangedNotifier(basic.valueChangedNotifier) + , basic(this) +{ + basic.move(1, 1); +} + +ListBoxThin::~ListBoxThin() +{ +} + +void ListBoxThin::addItem(std::string name, std::string value) +{ + basic.addItem(name, value); +} + +void ListBoxThin::addItems(std::vector &items) +{ + basic.addItems(items); +} + +void ListBoxThin::clear() +{ + basic.clear(); +} + +bool ListBoxThin::selectItem(int index) +{ + return basic.selectItem(index); +} + +std::string ListBoxThin::selectedName() +{ + return basic.selectedName(); +} + +std::string ListBoxThin::selectedValue() +{ + return basic.selectedValue(); +} + +void ListBoxThin::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } + + box.setSize(w,h); + p.drawImage(0, 0, box); +} + +void ListBoxThin::resize(std::size_t height, std::size_t width) +{ + Widget::resize(width, height); + basic.resize(width - (1 + 1), + height - (1 + 1)); +} + +} // GUI:: diff --git a/dggui/listboxthin.h b/dggui/listboxthin.h new file mode 100644 index 0000000..e861745 --- /dev/null +++ b/dggui/listboxthin.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * listboxthin.h + * + * Sun Apr 7 19:39:35 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include + +#include "widget.h" +#include "painter.h" +#include "listboxbasic.h" +#include "texturedbox.h" + +namespace GUI +{ + +class ListBoxThin + : public Widget +{ +public: + ListBoxThin(Widget *parent); + virtual ~ListBoxThin(); + + void addItem(std::string name, std::string value); + void addItems(std::vector &items); + + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); + + // From Widget: + virtual void repaintEvent(GUI::RepaintEvent* repaintEvent) override; + virtual void resize(std::size_t height, std::size_t width) override; + + // Forwarded notifier from ListBoxBasic::basic + Notifier<>& selectionNotifier; + Notifier<>& clickNotifier; + Notifier<>& valueChangedNotifier; + +private: + ListBoxBasic basic; + + TexturedBox box{getImageCache(), ":resources/thinlistbox.png", + 0, 0, // atlas offset (x, y) + 1, 1, 1, // dx1, dx2, dx3 + 1, 1, 1}; // dy1, dy2, dy3 +}; + +} // GUI:: diff --git a/dggui/lodepng b/dggui/lodepng new file mode 160000 index 0000000..a71964e --- /dev/null +++ b/dggui/lodepng @@ -0,0 +1 @@ +Subproject commit a71964ed5fe4f82a32ac7f8201338900f66e855d diff --git a/dggui/nativewindow.h b/dggui/nativewindow.h new file mode 100644 index 0000000..400ff57 --- /dev/null +++ b/dggui/nativewindow.h @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow.h + * + * Fri Dec 28 18:46:01 CET 2012 + * Copyright 2012 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include +#include +#include +#include + +#include "guievent.h" + +namespace GUI +{ + +struct Point; + +//! Interface class for native window implementations. +class NativeWindow +{ +public: + NativeWindow() {} + virtual ~NativeWindow() {} + + //! Set a fixed size to the window. + //! It resizes the window and disallows user resizing. + virtual void setFixedSize(std::size_t width, std::size_t height) = 0; + + //! Force window to stay on top of other windows + virtual void setAlwaysOnTop(bool always_on_top) = 0; + + //! Set a new size of the window. + virtual void resize(std::size_t width, std::size_t height) = 0; + + //! Query size of the native window. + virtual std::pair getSize() const = 0; + + //! Move the window to a new position. + //! Note: negative value are allowed. + virtual void move(int x, int y) = 0; + + //! Query the screen position of the native window. + //! Note: returned values can be negative. + virtual std::pair getPosition() const = 0; + + //! Show the window if it is hidden. + virtual void show() = 0; + + //! Hides the window. + virtual void hide() = 0; + + //! Return visibility state of the native window. + virtual bool visible() const = 0; + + //! Sets the window caption in the title bar (if it has one). + virtual void setCaption(const std::string &caption) = 0; + + //! Draw the internal rendering buffer to the window buffer. + virtual void redraw(const Rect& dirty_rect) = 0; + + //! Toggle capture mouse mode. + virtual void grabMouse(bool grab) = 0; + + //! Reads all currently enqueued events from the native window system. + //! \return A queue of shared pointers to events. + virtual EventQueue getEvents() = 0; + + //! \returns the native window handle, it HWND on Win32 or Window id on X11 + virtual void* getNativeWindowHandle() const = 0; + + //! Translate a the local native window coordinate to a global screen + //! coordinate. + virtual Point translateToScreen(const Point& point) = 0; +}; + +} // GUI:: diff --git a/dggui/nativewindow_cocoa.h b/dggui/nativewindow_cocoa.h new file mode 100644 index 0000000..8dc73e6 --- /dev/null +++ b/dggui/nativewindow_cocoa.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_cocoa.h + * + * Sun Dec 4 15:55:14 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "nativewindow.h" + +namespace GUI +{ + +class Window; +class NativeWindowCocoa + : public NativeWindow +{ +public: + NativeWindowCocoa(void* native_window, Window& window); + ~NativeWindowCocoa(); + + // From NativeWindow: + virtual void setFixedSize(std::size_t width, std::size_t height) override; + virtual void setAlwaysOnTop(bool always_on_top) override; + virtual void resize(std::size_t width, std::size_t height) override; + virtual std::pair getSize() const override; + virtual void move(int x, int y) override; + virtual std::pair getPosition() const override; + virtual void show() override; + virtual void hide() override; + virtual bool visible() const override; + virtual void setCaption(const std::string &caption) override; + virtual void redraw(const Rect& dirty_rect) override; + virtual void grabMouse(bool grab) override; + virtual EventQueue getEvents() override; + virtual void* getNativeWindowHandle() const override; + virtual Point translateToScreen(const Point& point) override; + + // Expose friend members of Window to ObjC++ implementation. + class Window& getWindow(); + class PixelBuffer& getWindowPixbuf(); + void resized(); + void pushBackEvent(std::shared_ptr event); + +private: + void updateLayerOffset(); + + Window& window; + std::unique_ptr priv; + EventQueue event_queue; + void* native_window{nullptr}; + bool first{true}; + float scale{1.0}; +}; + +} // GUI:: diff --git a/dggui/nativewindow_cocoa.mm b/dggui/nativewindow_cocoa.mm new file mode 100644 index 0000000..7b6ecc8 --- /dev/null +++ b/dggui/nativewindow_cocoa.mm @@ -0,0 +1,832 @@ +/* -*- Mode: ObjC; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_cocoa.mm + * + * Fri Dec 2 20:31:03 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "nativewindow_cocoa.h" + +#include "guievent.h" + +#include +#include + +#import + +#include "window.h" + +#include + +#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED +#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101300 // Before MacOSX 10.13 (High-Sierra) +#define STYLE_MASK \ + (NSClosableWindowMask | \ + NSTitledWindowMask | \ + NSResizableWindowMask) +#define IMAGE_FLAGS \ + (kCGBitmapByteOrder32Big | \ + kCGImageAlphaPremultipliedLast) +#define EVENT_MASK \ + NSAnyEventMask +#else +#define STYLE_MASK \ + (NSWindowStyleMaskClosable | \ + NSWindowStyleMaskTitled | \ + NSWindowStyleMaskResizable) +#define IMAGE_FLAGS \ + (kCGImageByteOrder32Big | \ + kCGImageAlphaPremultipliedLast) +#define EVENT_MASK \ + NSEventMaskAny +#endif + +#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101400 // Before MacOSX 10.14 (Mojave) +// Nothing here yet... +#endif +#endif + +@interface DGListener : NSWindow +{ +@public + NSWindow* window; + GUI::NativeWindowCocoa* native; +} + +- (id) initWithWindow:(NSWindow*)ref + native:(GUI::NativeWindowCocoa*)_native; +- (void) dealloc; +- (void) windowDidResize; +- (void) windowWillResize; +- (void) windowWillClose; +- (void) unbindNative; +@end + +@implementation DGListener +- (id) initWithWindow:(NSWindow*)ref + native:(GUI::NativeWindowCocoa*)_native +{ + [super init]; + + native = _native; + window = ref; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(windowDidResize) + name:NSWindowDidResizeNotification + object:ref]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(windowWillResize) + name:NSWindowWillStartLiveResizeNotification + object:ref]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(windowWillClose) + name:NSWindowWillCloseNotification + object:ref]; + + [self windowWillResize]; // trigger to get the initial size as a size change + + return self; +} + +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)windowDidResize +{ + if(!native) + { + return; + } + + native->resized(); +} + +- (void)windowWillResize +{ + if(!native) + { + return; + } + + native->resized(); +} + +- (void) windowWillClose +{ + if(!native) + { + return; + } + + auto closeEvent = std::make_shared(); + native->pushBackEvent(closeEvent); +} + +- (void) unbindNative +{ + native = nullptr; +} +@end + +@interface DGView : NSView +{ + int colorBits; + int depthBits; + +@private + GUI::NativeWindowCocoa* native; + NSTrackingArea* trackingArea; +} + +//- (id) initWithFrame:(NSRect)frame +// colorBits:(int)numColorBits +// depthBits:(int)numDepthBits; +- (void) updateTrackingAreas; + +- (void) mouseEntered:(NSEvent *)event; +- (void) mouseExited:(NSEvent *)event; +- (void) mouseMoved:(NSEvent*)event; +- (void) mouseDown:(NSEvent*)event; +- (void) mouseUp:(NSEvent*)event; +- (void) rightMouseDown:(NSEvent*)event; +- (void) rightMouseUp:(NSEvent*)event; +- (void) otherMouseDown:(NSEvent*)event; +- (void) otherMouseUp:(NSEvent*)event; +- (void) mouseDragged:(NSEvent*)event; +- (void) rightMouseDragged:(NSEvent*)event; +- (void) otherMouseDragged:(NSEvent*)event; +- (void) scrollWheel:(NSEvent*)event; +- (void) keyDown:(NSEvent*)event; +- (void) keyUp:(NSEvent*)event; + +- (void) dealloc; +- (void) bindNative:(GUI::NativeWindowCocoa*)native; +- (void) unbindNative; +@end + +@implementation DGView +//- (id) initWithFrame:(NSRect)frame +// colorBits:(int)numColorBits +// depthBits:(int)numDepthBits +//{ +// [super init]; +// [self updateTrackingAreas]; +// return self; +//} + +- (void) updateTrackingAreas +{ + if(trackingArea != nil) + { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + } + + int opts = + NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | + NSTrackingActiveAlways; + + trackingArea = + [[NSTrackingArea alloc] initWithRect:[self bounds] + options:opts + owner:self + userInfo:nil]; + [self addTrackingArea:trackingArea]; +} + +- (void) mouseEntered:(NSEvent *)event +{ + [super mouseEntered:event]; + auto frame = [self frame]; + NSPoint loc = [event locationInWindow]; + auto mouseEnterEvent = std::make_shared(); + mouseEnterEvent->x = loc.x - frame.origin.x; + mouseEnterEvent->y = frame.size.height - loc.y - frame.origin.y; + native->pushBackEvent(mouseEnterEvent); + //[[NSCursor pointingHandCursor] set]; +} + +- (void) mouseExited:(NSEvent *)event +{ + [super mouseExited:event]; + auto frame = [self frame]; + NSPoint loc = [event locationInWindow]; + auto mouseLeaveEvent = std::make_shared(); + mouseLeaveEvent->x = loc.x - frame.origin.x; + mouseLeaveEvent->y = frame.size.height - loc.y - frame.origin.y; + native->pushBackEvent(mouseLeaveEvent); + //[[NSCursor arrowCursor] set]; +} + +- (void) mouseMoved:(NSEvent*)event +{ + auto frame = [self frame]; + NSPoint loc = [event locationInWindow]; + auto mouseMoveEvent = std::make_shared(); + mouseMoveEvent->x = loc.x - frame.origin.x; + mouseMoveEvent->y = frame.size.height - loc.y - frame.origin.y; + native->pushBackEvent(mouseMoveEvent); +} + +- (void) mouseDown:(NSEvent*)event +{ + auto frame = [self frame]; + NSPoint loc = [event locationInWindow]; + + auto buttonEvent = std::make_shared(); + buttonEvent->x = loc.x - frame.origin.x; + buttonEvent->y = frame.size.height - loc.y - frame.origin.y; + switch((int)[event buttonNumber]) + { + case 0: + buttonEvent->button = GUI::MouseButton::left; + break; + case 1: + buttonEvent->button = GUI::MouseButton::right; + break; + case 2: + buttonEvent->button = GUI::MouseButton::middle; + break; + default: + return; + } + buttonEvent->direction = GUI::Direction::down; + buttonEvent->doubleClick = [event clickCount] == 2; + native->pushBackEvent(buttonEvent); + + [super mouseDown: event]; +} + +- (void) mouseUp:(NSEvent*)event +{ + auto frame = [self frame]; + NSPoint loc = [event locationInWindow]; + + auto buttonEvent = std::make_shared(); + buttonEvent->x = loc.x - frame.origin.x; + buttonEvent->y = frame.size.height - loc.y - frame.origin.y; + switch((int)[event buttonNumber]) + { + case 0: + buttonEvent->button = GUI::MouseButton::left; + break; + case 1: + buttonEvent->button = GUI::MouseButton::right; + break; + case 2: + buttonEvent->button = GUI::MouseButton::middle; + break; + default: + return; + } + buttonEvent->direction = GUI::Direction::up; + buttonEvent->doubleClick = false; + native->pushBackEvent(buttonEvent); + + [super mouseUp: event]; +} + +- (void) rightMouseDown:(NSEvent*)event +{ + [self mouseDown: event]; + [super rightMouseDown: event]; +} + +- (void) rightMouseUp:(NSEvent*)event +{ + [self mouseUp: event]; + [super rightMouseUp: event]; +} + +- (void) otherMouseDown:(NSEvent*)event +{ + [self mouseDown: event]; + [super otherMouseDown: event]; +} + +- (void) otherMouseUp:(NSEvent*)event +{ + [self mouseUp: event]; + [super otherMouseUp: event]; +} + +- (void) mouseDragged:(NSEvent*)event +{ + [self mouseMoved: event]; + [super mouseDragged: event]; +} + +- (void) rightMouseDragged:(NSEvent*)event +{ + [self mouseMoved: event]; + [super rightMouseDragged: event]; +} + +- (void) otherMouseDragged:(NSEvent*)event +{ + [self mouseMoved: event]; + [super otherMouseDragged: event]; +} + +- (void) scrollWheel:(NSEvent*)event +{ + auto frame = [self frame]; + NSPoint loc = [event locationInWindow]; + + auto scrollEvent = std::make_shared(); + scrollEvent->x = loc.x - frame.origin.x; + scrollEvent->y = frame.size.height - loc.y - frame.origin.y; + scrollEvent->delta = [event deltaY] * -1.0f; + native->pushBackEvent(scrollEvent); + + [super scrollWheel: event]; +} + +- (void) keyDown:(NSEvent*)event +{ + const NSString* chars = [event characters]; + const char* str = [chars UTF8String]; + + auto keyEvent = std::make_shared(); + + switch([event keyCode]) + { + case 123: keyEvent->keycode = GUI::Key::left; break; + case 124: keyEvent->keycode = GUI::Key::right; break; + case 126: keyEvent->keycode = GUI::Key::up; break; + case 125: keyEvent->keycode = GUI::Key::down; break; + case 117: keyEvent->keycode = GUI::Key::deleteKey; break; + case 51: keyEvent->keycode = GUI::Key::backspace; break; + case 115: keyEvent->keycode = GUI::Key::home; break; + case 119: keyEvent->keycode = GUI::Key::end; break; + case 121: keyEvent->keycode = GUI::Key::pageDown; break; + case 116: keyEvent->keycode = GUI::Key::pageUp; break; + case 36: keyEvent->keycode = GUI::Key::enter; break; + default: keyEvent->keycode = GUI::Key::unknown; break; + } + + if(strlen(str) && keyEvent->keycode == GUI::Key::unknown) + { + keyEvent->keycode = GUI::Key::character; + } + + keyEvent->text = str; // TODO: UTF8 decode + keyEvent->direction = GUI::Direction::down; + + native->pushBackEvent(keyEvent); + [super keyDown: event]; +} + +- (void) keyUp:(NSEvent*)event +{ + const NSString* chars = [event characters]; + const char* str = [chars UTF8String]; + auto keyEvent = std::make_shared(); + + switch([event keyCode]) + { + case 123: keyEvent->keycode = GUI::Key::left; break; + case 124: keyEvent->keycode = GUI::Key::right; break; + case 126: keyEvent->keycode = GUI::Key::up; break; + case 125: keyEvent->keycode = GUI::Key::down; break; + case 117: keyEvent->keycode = GUI::Key::deleteKey; break; + case 51: keyEvent->keycode = GUI::Key::backspace; break; + case 115: keyEvent->keycode = GUI::Key::home; break; + case 119: keyEvent->keycode = GUI::Key::end; break; + case 121: keyEvent->keycode = GUI::Key::pageDown; break; + case 116: keyEvent->keycode = GUI::Key::pageUp; break; + case 36: keyEvent->keycode = GUI::Key::enter; break; + default: keyEvent->keycode = GUI::Key::unknown; break; + } + + if(strlen(str) && keyEvent->keycode == GUI::Key::unknown) + { + keyEvent->keycode = GUI::Key::character; + } + + keyEvent->text = str; // TODO: UTF8 decode + keyEvent->direction = GUI::Direction::up; + + native->pushBackEvent(keyEvent); + [super keyUp: event]; +} + +- (void) dealloc +{ + [super dealloc]; +} + +- (void)bindNative:(GUI::NativeWindowCocoa*)_native +{ + native = _native; +} + +- (void) unbindNative +{ + native = nullptr; +} +@end + + +namespace GUI +{ + +struct priv +{ + NSWindow* window; + DGView* view; + id listener; + id parent_view; + std::uint8_t* pixel_buffer{nullptr}; + std::size_t pixel_buffer_width{0}; + std::size_t pixel_buffer_height{0}; +}; + +NativeWindowCocoa::NativeWindowCocoa(void* native_window, Window& window) + : window(window) + , priv(new struct priv()) + , native_window(native_window) +{ + [NSAutoreleasePool new]; + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + + priv->view = [DGView new]; + + [priv->view bindNative:this]; + + if(native_window) + { + if(sizeof(std::size_t) == sizeof(unsigned int)) // 32 bit machine + { + WindowRef ptr = (WindowRef)native_window; + priv->window = [[[NSWindow alloc] initWithWindowRef:ptr] retain]; + priv->parent_view = [priv->window contentView]; + } + else // 64 bit machine + { + priv->parent_view = (NSView*)native_window; + priv->window = [priv->parent_view window]; + } + + [priv->parent_view addSubview:priv->view]; + [priv->view display]; + [priv->parent_view setNeedsDisplay:YES]; + } + else + { + priv->window = + [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 10, 10) + styleMask:STYLE_MASK + backing:NSBackingStoreBuffered + defer:NO] + retain]; + [priv->window setLevel:NSStatusWindowLevel]; + } + + priv->listener = + [[[DGListener alloc] initWithWindow:priv->window + native:this] + retain]; + + if(native_window) + { + [[priv->window contentView] addSubview:priv->view]; + } + else + { + [priv->window setReleasedWhenClosed:NO]; + [priv->window setContentView:priv->view]; + } + + scale = [[NSScreen mainScreen] backingScaleFactor]; + + [priv->view setWantsLayer:YES]; + [priv->view setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft]; + [priv->view updateTrackingAreas]; + + if(!native_window) + { + hide(); + } +} + +NativeWindowCocoa::~NativeWindowCocoa() +{ + // Make the garbage collector able to collect the ObjC objects: + if(visible()) + { + hide(); + } + + [priv->listener unbindNative]; + [priv->listener release]; + + [priv->view unbindNative]; + [priv->view release]; + + if(native_window) + { + if(sizeof(std::size_t) == sizeof(unsigned int)) // 32 bit machine + { + [priv->window release]; + } + else + { + // in 64-bit the window was not created by us + } + } + else + { + [priv->window release]; + } +} + +void NativeWindowCocoa::setFixedSize(std::size_t width, std::size_t height) +{ + resize(width, height); + [priv->window setMinSize:NSMakeSize(width, height + 22)]; + [priv->window setMaxSize:NSMakeSize(width, height + 22)]; +} + +void NativeWindowCocoa::setAlwaysOnTop(bool always_on_top) +{ + if(always_on_top) + { + [priv->window setLevel: NSStatusWindowLevel]; + } + else + { + [priv->window setLevel: NSNormalWindowLevel]; + } +} + +void NativeWindowCocoa::resize(std::size_t width, std::size_t height) +{ + [priv->window setContentSize:NSMakeSize(width, height)]; +} + +std::pair NativeWindowCocoa::getSize() const +{ + if(native_window) + { + auto frame = [priv->parent_view frame]; + return {frame.size.width, frame.size.height - frame.origin.y}; + } + else + { + NSSize size = [priv->view frame].size; + return {size.width, size.height}; + } +} + +void NativeWindowCocoa::move(int x, int y) +{ + NSRect screen = [[NSScreen mainScreen] frame]; + [priv->window setFrameTopLeftPoint:NSMakePoint(x, screen.size.height - y)]; +} + +std::pair NativeWindowCocoa::getPosition() const +{ + NSRect screen = [[NSScreen mainScreen] frame]; + NSPoint pos = [[priv->window contentView] frame].origin; + return {pos.x, screen.size.height - pos.y}; +} + +void NativeWindowCocoa::show() +{ + if(!native_window) + { + [priv->window makeKeyAndOrderFront:priv->window]; + [NSApp activateIgnoringOtherApps:YES]; + } +} + +void NativeWindowCocoa::hide() +{ + if(!native_window) + { + [priv->window orderOut:priv->window]; + } +} + +bool NativeWindowCocoa::visible() const +{ + return [priv->window isVisible]; +} + +void NativeWindowCocoa::redraw(const Rect& dirty_rect) +{ + NSSize size; + if(native_window) + { + size = [priv->parent_view frame].size; + } + else + { + size = [priv->view frame].size; + } + + std::size_t width = size.width; + std::size_t height = size.height; + + if(priv->pixel_buffer == nullptr || + priv->pixel_buffer_width != width || + priv->pixel_buffer_height != height) + { + if(priv->pixel_buffer) delete[] priv->pixel_buffer; + priv->pixel_buffer = new std::uint8_t[width * height * 4]; + priv->pixel_buffer_width = width; + priv->pixel_buffer_height = height; + } + + CGColorSpaceRef rgb = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + CGContextRef gc = + CGBitmapContextCreate(priv->pixel_buffer, width, height, + 8, width * 4, rgb, + IMAGE_FLAGS); + CGColorSpaceRelease(rgb); + + size_t pitch = CGBitmapContextGetBytesPerRow(gc); + uint8_t *buffer = (uint8_t *)CGBitmapContextGetData(gc); + + struct Pixel + { + std::uint8_t red; + std::uint8_t green; + std::uint8_t blue; + std::uint8_t alpha; + }; + std::uint8_t* pixels = window.wpixbuf.buf; + for(std::size_t y = dirty_rect.y1; y < std::min(dirty_rect.y2, height); ++y) + { + Pixel *row = (Pixel *)(buffer + y * pitch); + for(std::size_t x = dirty_rect.x1; x < std::min(dirty_rect.x2, width); ++x) + { + row[x] = *(Pixel*)&pixels[(y * width + x) * 3]; + row[x].alpha = 0xff; + } + } + CGImageRef image = CGBitmapContextCreateImage(gc); + CGContextRelease(gc); + + auto nsImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize]; + + id layerContents = [nsImage layerContentsForContentsScale:scale]; + [[priv->view layer] setContents:layerContents]; + updateLayerOffset(); + [[priv->view layer] setContentsScale:scale]; +} + +void NativeWindowCocoa::setCaption(const std::string &caption) +{ + NSString* title = + [NSString stringWithCString:caption.data() + encoding:[NSString defaultCStringEncoding]]; + [priv->window setTitle:title]; +} + +void NativeWindowCocoa::grabMouse(bool grab) +{ +} + +void NativeWindowCocoa::updateLayerOffset() +{ + if(native_window) + { + //auto r1 = [priv->parent_view frame]; + auto r2 = [priv->view frame]; + + CATransform3D t = [[priv->view layer] transform]; + if(t.m42 != -r2.origin.y) + { + t.m42 = -r2.origin.y; // y + [[priv->view layer] setTransform:t]; + } + } +} + +EventQueue NativeWindowCocoa::getEvents() +{ + if(first) + { + resized(); + first = false; + } + + // If this is the root window, process the events - event processing will + // be handled by the hosting window if the window is embedded. + if(!native_window) + { + NSEvent* event = nil; + do + { + event = [NSApp nextEventMatchingMask:EVENT_MASK + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + [NSApp sendEvent:event]; + } + while(event != nil); + } + + EventQueue events; + std::swap(events, event_queue); + return events; +} + +void* NativeWindowCocoa::getNativeWindowHandle() const +{ + if(sizeof(std::size_t) == sizeof(unsigned int)) // 32 bit machine + { + return [priv->window windowRef]; + } + else // 64 bit machine + { + return [priv->window contentView]; + } +} + +Point NativeWindowCocoa::translateToScreen(const Point& point) +{ + NSRect e = [[NSScreen mainScreen] frame]; + NSRect frame; + if(native_window) + { + frame = [priv->parent_view frame]; + } + else + { + frame = [priv->view frame]; + } + + NSRect rect { { point.x + frame.origin.x, + frame.size.height - point.y + frame.origin.y}, + {0.0, 0.0} }; + rect = [priv->window convertRectToScreen:rect]; + + return { (int)rect.origin.x, (int)(e.size.height - rect.origin.y) }; +} + +Window& NativeWindowCocoa::getWindow() +{ + return window; +} + +PixelBuffer& NativeWindowCocoa::getWindowPixbuf() +{ + window.updateBuffer(); + return window.wpixbuf; +} + +void NativeWindowCocoa::resized() +{ + if(native_window) + { + NSRect frame = [priv->parent_view frame]; + [priv->view setFrame:frame]; + [priv->view updateTrackingAreas]; + updateLayerOffset(); + } + + auto resizeEvent = std::make_shared(); + resizeEvent->width = 42; // size is not actually used + resizeEvent->height = 42; // size is not actually used + pushBackEvent(resizeEvent); +} + +void NativeWindowCocoa::pushBackEvent(std::shared_ptr event) +{ + event_queue.push_back(event); +} + +} // GUI:: diff --git a/dggui/nativewindow_pugl.cc b/dggui/nativewindow_pugl.cc new file mode 100644 index 0000000..f94b82b --- /dev/null +++ b/dggui/nativewindow_pugl.cc @@ -0,0 +1,382 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_pugl.cc + * + * Fri Dec 28 18:45:57 CET 2012 + * Copyright 2012 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "nativewindow_pugl.h" + +#include +#include + +#ifdef __APPLE__ +#include +#else +#include +#include +#include +#endif + +#include "window.h" +#include "guievent.h" + +#include + +namespace GUI +{ + +NativeWindowPugl::NativeWindowPugl(void* native_window, Window& window) + : window(window) +{ + INFO(nativewindow, "Running with PuGL native window\n"); + view = puglInit(nullptr, nullptr); + puglInitContextType(view, PUGL_GL); + if(native_window) + { + puglInitWindowParent(view, (PuglNativeWindow)native_window); + } + puglInitWindowClass(view, "DrumgGizmo"); + puglInitWindowSize(view, 750, 466); + puglInitResizable(view, true); + puglCreateWindow(view, "DrumGizmo"); + + puglSetHandle(view, (PuglHandle)this); + puglSetEventFunc(view, onEvent); +} + +NativeWindowPugl::~NativeWindowPugl() +{ + puglDestroy(view); +} + +void NativeWindowPugl::setFixedSize(std::size_t width, std::size_t height) +{ +// redraw(); +} + +void NativeWindowPugl::resize(std::size_t width, std::size_t height) +{ +// DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height); +// init(); +// redraw(); +} + +std::pair NativeWindowPugl::getSize() const +{ + int width, height; + puglGetSize(view, &width, &height); + return {width, height}; +} + +void NativeWindowPugl::move(int x, int y) +{ +// redraw(); +} + +void NativeWindowPugl::show() +{ + puglShowWindow(view); +} + +void NativeWindowPugl::hide() +{ + puglHideWindow(view); +} + +bool NativeWindowPugl::visible() const +{ + return puglGetVisible(view); +} + +void NativeWindowPugl::redraw(const Rect& dirty_rect) +{ + //puglPostRedisplay(view);// handleBuffer(); + onDisplay(view); +} + +void NativeWindowPugl::setCaption(const std::string &caption) +{ +// redraw(); +} + +void NativeWindowPugl::grabMouse(bool grab) +{ + puglGrabFocus(view); +} + +EventQueue NativeWindowPugl::getEvents() +{ + puglProcessEvents(view); + EventQueue events; + std::swap(events, event_queue); + return events; +} + +void* NativeWindowPugl::getNativeWindowHandle() const +{ + return (void*)puglGetNativeWindow(view); +} + +void NativeWindowPugl::onEvent(PuglView* view, const PuglEvent* event) +{ + NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); + + switch(event->type) + { + case PUGL_NOTHING: + break; + case PUGL_CONFIGURE: + onReshape(view, event->configure.width, event->configure.height); + { + auto resize_event = std::make_shared(); + resize_event->width = event->configure.width; + resize_event->height = event->configure.height; + native->event_queue.push_back(resize_event); + } + break; + case PUGL_EXPOSE: + onDisplay(view); + break; + case PUGL_CLOSE: + //quit = 1; + break; + case PUGL_KEY_PRESS: + fprintf(stderr, "Key %u (char %u) press (%s)%s\n", + event->key.keycode, event->key.character, event->key.utf8, + event->key.filter ? " (filtered)" : ""); + if (event->key.character == 'q' || + event->key.character == 'Q' || + event->key.character == PUGL_CHAR_ESCAPE) { + //quit = 1; + } + break; + case PUGL_KEY_RELEASE: + fprintf(stderr, "Key %u (char %u) release (%s)%s\n", + event->key.keycode, event->key.character, event->key.utf8, + event->key.filter ? " (filtered)" : ""); + break; + case PUGL_MOTION_NOTIFY: + { + auto mouseMoveEvent = std::make_shared(); + mouseMoveEvent->x = event->motion.x; + mouseMoveEvent->y = event->motion.y; + native->event_queue.push_back(mouseMoveEvent); + } + break; + case PUGL_BUTTON_PRESS: + case PUGL_BUTTON_RELEASE: + { + auto buttonEvent = std::make_shared(); + buttonEvent->x = event->button.x; + buttonEvent->y = event->button.y; + switch(event->button.button) { + case 1: + buttonEvent->button = MouseButton::left; + break; + case 2: + buttonEvent->button = MouseButton::middle; + break; + case 3: + buttonEvent->button = MouseButton::right; + break; + default: + WARN(X11, "Unknown button %d, setting to MouseButton::left\n", + event->button.button); + buttonEvent->button = MouseButton::left; + break; + } + + buttonEvent->direction = + (event->type == PUGL_BUTTON_PRESS) ? + Direction::down : Direction::up; + + buttonEvent->doubleClick = + (event->type == PUGL_BUTTON_PRESS) && + ((event->button.time - native->last_click) < 200); + + if(event->type == PUGL_BUTTON_PRESS) + { + native->last_click = event->button.time; + } + native->event_queue.push_back(buttonEvent); + } + fprintf(stderr, "Mouse %d %s at %f,%f ", + event->button.button, + (event->type == PUGL_BUTTON_PRESS) ? "down" : "up", + event->button.x, + event->button.y); + ///printModifiers(view, event->scroll.state); + break; + case PUGL_SCROLL: + { + auto scrollEvent = std::make_shared(); + scrollEvent->x = event->scroll.x; + scrollEvent->y = event->scroll.y; + scrollEvent->delta = event->scroll.dy * -1;//scroll * ((xevent.xbutton.button == 4) ? -1 : 1); + native->event_queue.push_back(scrollEvent); + } + fprintf(stderr, "Scroll %f %f %f %f ", + event->scroll.x, event->scroll.y, event->scroll.dx, event->scroll.dy); + //printModifiers(view, event->scroll.state); + //dist += event->scroll.dy; + //if (dist < 10.0f) { + // dist = 10.0f; + //} + puglPostRedisplay(view); + break; + case PUGL_ENTER_NOTIFY: + fprintf(stderr, "Entered\n"); + break; + case PUGL_LEAVE_NOTIFY: + fprintf(stderr, "Exited\n"); + break; + case PUGL_FOCUS_IN: + fprintf(stderr, "Focus in\n"); + break; + case PUGL_FOCUS_OUT: + fprintf(stderr, "Focus out\n"); + break; + } +} + +void NativeWindowPugl::onReshape(PuglView* view, int width, int height) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glViewport(0, 0, width, height); +} + +void NativeWindowPugl::onDisplay(PuglView* view) +{ + NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); + Window& window = native->window; + //window.redraw(); + + if((window.wpixbuf.width < 16) || (window.wpixbuf.height < 16)) + { + return; + } + + puglEnterContext(view); + + glDisable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, 0.0f); + + GLuint image; + + glGenTextures(1, &image); + + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, + 0, GL_RGBA, + window.wpixbuf.width, + window.wpixbuf.height, + 0, GL_RGB, GL_UNSIGNED_BYTE, + window.wpixbuf.buf); + + glEnable(GL_TEXTURE_2D); + + glBegin(GL_QUADS); + glTexCoord2d(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); + glTexCoord2d(0.0f, -1.0f); glVertex2f(-1.0f, 1.0f); + glTexCoord2d(1.0f, -1.0f); glVertex2f( 1.0f, 1.0f); + glTexCoord2d(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); + glEnd(); + + glDeleteTextures(1, &image); + glDisable(GL_TEXTURE_2D); + glFlush(); + + puglLeaveContext(view, true); +} + +void NativeWindowPugl::onMouse(PuglView* view, int button, bool press, int x, int y) +{ + NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); + + DEBUG(nativewindow_pugl, "Mouse %d %s at (%d,%d)\n", button, + press? "down":"up", x, y); + + ButtonEvent* e = new ButtonEvent(); + e->x = x; + e->y = y; + + switch(button) { + case 1: + e->button = MouseButton::left; + break; + case 2: + e->button = MouseButton::middle; + break; + case 3: + default: + e->button = MouseButton::right; + break; + } + + e->direction = press ? Direction::down : Direction::up; + e->doubleClick = false; + + native->eventq.push_back(e); +} + +void NativeWindowPugl::onKeyboard(PuglView* view, bool press, uint32_t key) +{ + NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); + + KeyEvent* e = new KeyEvent(); + e->direction = press ? Direction::down : Direction::up; + + switch(key) + { + case PUGL_KEY_LEFT: e->keycode = Key::left; break; + case PUGL_KEY_RIGHT: e->keycode = Key::right; break; + case PUGL_KEY_UP: e->keycode = Key::up; break; + case PUGL_KEY_DOWN: e->keycode = Key::down; break; + case PUGL_KEY_PAGE_UP: e->keycode = Key::pageDown; break; + case PUGL_KEY_PAGE_DOWN: e->keycode = Key::pageUp; break; + default: e->keycode = Key::unknown; break; + } + + // TODO: perform character type check + if(e->keycode == Key::unknown) + { + e->keycode = Key::character; + e->text.assign(1, (char)key); + } + + native->eventq.push_back(e); +} + +} // GUI:: diff --git a/dggui/nativewindow_pugl.h b/dggui/nativewindow_pugl.h new file mode 100644 index 0000000..6a667f4 --- /dev/null +++ b/dggui/nativewindow_pugl.h @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_pugl.h + * + * Fri Dec 28 18:45:56 CET 2012 + * Copyright 2012 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "nativewindow.h" +extern "C" +{ +#include +} + +#include + +namespace GUI +{ + +class Event; +class Window; + +class NativeWindowPugl : public NativeWindow { +public: + NativeWindowPugl(void* native_window, Window& window); + ~NativeWindowPugl(); + + void setFixedSize(std::size_t width, std::size_t height) override; + void resize(std::size_t width, std::size_t height) override; + std::pair getSize() const override; + + void move(int x, int y) override; + std::pair getPosition() const override{ return {}; } + + void show() override; + void setCaption(const std::string &caption) override; + void hide() override; + bool visible() const override; + void redraw(const Rect& dirty_rect) override; + void grabMouse(bool grab) override; + + EventQueue getEvents() override; + + void* getNativeWindowHandle() const override; + +private: + Window& window; + PuglView* view{nullptr}; + + std::list eventq; + + // Internal pugl c-callbacks + static void onEvent(PuglView* view, const PuglEvent* event); + static void onReshape(PuglView* view, int width, int height); + static void onDisplay(PuglView* view); + static void onMouse(PuglView* view, int button, bool press, int x, int y); + static void onKeyboard(PuglView* view, bool press, uint32_t key); + + EventQueue event_queue; + std::uint32_t last_click{0}; +}; + +} // GUI:: diff --git a/dggui/nativewindow_win32.cc b/dggui/nativewindow_win32.cc new file mode 100644 index 0000000..4b31130 --- /dev/null +++ b/dggui/nativewindow_win32.cc @@ -0,0 +1,584 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_win32.cc + * + * Fri Dec 28 18:45:52 CET 2012 + * Copyright 2012 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "nativewindow_win32.h" + +#include +#include +#include + +#include "window.h" + +namespace GUI +{ + +static BOOL trackMouse(HWND hwnd) +{ + TRACKMOUSEEVENT ev{}; + ev.cbSize = sizeof(ev); + ev.dwFlags = TME_HOVER | TME_LEAVE; + ev.hwndTrack = hwnd; + ev.dwHoverTime = 1; + return TrackMouseEvent(&ev); +} + +LRESULT CALLBACK NativeWindowWin32::dialogProc(HWND hwnd, UINT msg, + WPARAM wp, LPARAM lp) +{ + NativeWindowWin32* native = + (NativeWindowWin32*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled. + if(!native) + { + return DefWindowProc(hwnd, msg, wp, lp); + } + + Window& window = native->window; + + switch(msg) + { + case WM_SIZE: + if(wp > 4) + { + // Bogus value - ignore + break; + } + { + auto resizeEvent = std::make_shared(); + resizeEvent->width = LOWORD(lp); + resizeEvent->height = HIWORD(lp); + native->event_queue.push_back(resizeEvent); + } + break; + + case WM_MOVE: + { + auto moveEvent = std::make_shared(); + moveEvent->x = (short)LOWORD(lp); + moveEvent->y = (short)HIWORD(lp); + native->event_queue.push_back(moveEvent); + } + break; + + case WM_CLOSE: + { + auto closeEvent = std::make_shared(); + native->event_queue.push_back(closeEvent); + } + return 0; // Do not call DefWindowProc for this event. +// HWND child, old; +// old = 0; + +// numDialogs--; + +// while(old != (child = GetNextDlgGroupItem(hwnd, hwnd, false))) { +// old = child; +// EndDialog(child, 0); +// } + +// if(numDialogs) EndDialog(hwnd, 0); +// else PostQuitMessage(0); +// return 0; + case WM_MOUSEMOVE: + { + trackMouse(native->m_hwnd); + auto mouseMoveEvent = std::make_shared(); + mouseMoveEvent->x = (short)LOWORD(lp); + mouseMoveEvent->y = (short)HIWORD(lp); + native->last_mouse_position = { mouseMoveEvent->x, mouseMoveEvent->y }; + + if(!native->mouse_in_window) + { + auto enterEvent = std::make_shared(); + enterEvent->x = native->last_mouse_position.first; + enterEvent->y = native->last_mouse_position.second; + native->event_queue.push_back(enterEvent); + native->mouse_in_window = true; + } + native->event_queue.push_back(mouseMoveEvent); + } + break; + + case WM_MOUSEWHEEL: + { + auto scrollEvent = std::make_shared(); + + // NOTE: lp is coordinates in screen space, not client space. + POINT p; + p.x = (short)LOWORD(lp); + p.y = (short)HIWORD(lp); + ScreenToClient(hwnd, &p); + + scrollEvent->x = p.x; + scrollEvent->y = p.y; + scrollEvent->delta = -1 * (short)HIWORD(wp) / 60.0f; + native->event_queue.push_back(scrollEvent); + } + break; + + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_RBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_MBUTTONDOWN: + { + auto buttonEvent = std::make_shared(); + + buttonEvent->x = (short)LOWORD(lp); + buttonEvent->y = (short)HIWORD(lp); + + if(msg == WM_LBUTTONUP || + msg == WM_LBUTTONDBLCLK || + msg == WM_LBUTTONDOWN) + { + buttonEvent->button = MouseButton::left; + } + else if(msg == WM_MBUTTONUP || + msg == WM_MBUTTONDBLCLK || + msg == WM_MBUTTONDOWN) + { + buttonEvent->button = MouseButton::middle; + } + else if(msg == WM_RBUTTONUP || + msg == WM_RBUTTONDBLCLK || + msg == WM_RBUTTONDOWN) + { + buttonEvent->button = MouseButton::right; + } + else + { + break; // unknown button + } + + // Double-clicking the a mouse button actually generates a sequence + // of four messages: WM_xBUTTONDOWN, WM_xBUTTONUP, WM_xBUTTONDBLCLK, and + // WM_xBUTTONUP. In other words the second WM_xBUTTONDOWN is replaced by a + // WM_xBUTTONDBLCLK. We simply 'return it' as a WM_xBUTTONDOWN but set the + // doubleClick boolean hint accordingly. + if(msg == WM_LBUTTONUP || + msg == WM_RBUTTONUP || + msg == WM_MBUTTONUP) + { + buttonEvent->direction = Direction::up; + } + else if(msg == WM_LBUTTONDOWN || + msg == WM_RBUTTONDOWN || + msg == WM_MBUTTONDOWN || + msg == WM_LBUTTONDBLCLK || + msg == WM_RBUTTONDBLCLK || + msg == WM_MBUTTONDBLCLK) + { + buttonEvent->direction = Direction::down; + } + + buttonEvent->doubleClick = (msg == WM_LBUTTONDBLCLK || + msg == WM_RBUTTONDBLCLK || + msg == WM_MBUTTONDBLCLK); + + native->event_queue.push_back(buttonEvent); + } + break; + + case WM_KEYDOWN: + case WM_KEYUP: + { + auto keyEvent = std::make_shared(); + + switch(wp) { + case VK_LEFT: keyEvent->keycode = Key::left; break; + case VK_RIGHT: keyEvent->keycode = Key::right; break; + case VK_UP: keyEvent->keycode = Key::up; break; + case VK_DOWN: keyEvent->keycode = Key::down; break; + case VK_BACK: keyEvent->keycode = Key::backspace; break; + case VK_DELETE: keyEvent->keycode = Key::deleteKey; break; + case VK_HOME: keyEvent->keycode = Key::home; break; + case VK_END: keyEvent->keycode = Key::end; break; + case VK_PRIOR: keyEvent->keycode = Key::pageUp; break; + case VK_NEXT: keyEvent->keycode = Key::pageDown; break; + case VK_RETURN: keyEvent->keycode = Key::enter; break; + default: keyEvent->keycode = Key::unknown; break; + } + + keyEvent->text = ""; + keyEvent->direction = + (msg == WM_KEYDOWN) ? Direction::down : Direction::up; + + native->event_queue.push_back(keyEvent); + } + break; + + case WM_CHAR: + { + if(wp >= ' ') // Filter control chars. + { + auto keyEvent = std::make_shared(); + keyEvent->keycode = Key::character; + keyEvent->text += (char)wp; + keyEvent->direction = Direction::up; + native->event_queue.push_back(keyEvent); + } + } + break; + + case WM_PAINT: + { + RECT rect; + GetUpdateRect(hwnd, &rect, FALSE); + + // Bypass partial update, which is apparrently broken. + rect.left = 0; + rect.top = 0; + rect.right = window.wpixbuf.width; + rect.bottom = window.wpixbuf.height; + + auto repaintEvent = std::make_shared(); + repaintEvent->x = rect.left; + repaintEvent->y = rect.top; + repaintEvent->width = rect.right - rect.left; + repaintEvent->height = rect.bottom - rect.top; + native->event_queue.push_back(repaintEvent); + + // Move to window.h (in class) + HDC pDC; + HBITMAP old; + HBITMAP ourbitmap; + int* framebuf; + PixelBuffer& px = window.wpixbuf; + + { // Create bitmap + HDC hDC; + BITMAPINFO bitmapinfo; + hDC = CreateCompatibleDC(nullptr); + bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapinfo.bmiHeader.biWidth = px.width; + bitmapinfo.bmiHeader.biHeight = -px.height; // top-down + bitmapinfo.bmiHeader.biPlanes = 1; + bitmapinfo.bmiHeader.biBitCount = 32; + bitmapinfo.bmiHeader.biCompression = BI_RGB; + bitmapinfo.bmiHeader.biSizeImage = 0; + bitmapinfo.bmiHeader.biClrUsed = 256; + bitmapinfo.bmiHeader.biClrImportant = 256; + ourbitmap = CreateDIBSection(hDC, &bitmapinfo, + DIB_RGB_COLORS, (void**)&framebuf, 0, 0); + pDC=CreateCompatibleDC(nullptr); + old = (HBITMAP__*)SelectObject(pDC, ourbitmap); + DeleteDC(hDC); + } + + int from_x = rect.left; + int to_x = std::min(rect.right, (long)px.width); + int from_y = rect.top; + int to_y = std::min(rect.bottom, (long)px.height); + { // Copy PixelBuffer to framebuffer + int idx = 0; + for(int y = from_y; y < to_y; ++y) + { + for(int x = from_x; x < to_x; ++x) + { + *(framebuf + idx) = RGB(px.buf[(x + y * px.width) * 3 + 2], + px.buf[(x + y * px.width) * 3 + 1], + px.buf[(x + y * px.width) * 3 + 0]); + ++idx; + } + } + } + + PAINTSTRUCT ps; + HDC hdc = BeginPaint(native->m_hwnd, &ps); + BitBlt(hdc, from_x, from_y, to_x, to_y, pDC, from_x, from_y, SRCCOPY); + EndPaint(native->m_hwnd, &ps); + + { // Destroy bitmap (move to window.cc) + SelectObject(pDC,old); + DeleteDC(pDC); + DeleteObject(ourbitmap); + } + } + break; + + case WM_MOUSELEAVE: + { + auto leaveEvent = std::make_shared(); + leaveEvent->x = native->last_mouse_position.first; + leaveEvent->y = native->last_mouse_position.second; + native->event_queue.push_back(leaveEvent); + native->mouse_in_window = false; + } + break; + } + + return DefWindowProc(hwnd, msg, wp, lp); +} + +LRESULT CALLBACK NativeWindowWin32::subClassProc(HWND hwnd, UINT msg, + WPARAM wp, LPARAM lp, + UINT_PTR id, DWORD_PTR data) +{ + NativeWindowWin32* native = (NativeWindowWin32*)data; + + // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled. + if(!native) + { + return DefWindowProc(hwnd, msg, wp, lp); + } + + switch(msg) + { + case WM_SIZE: + if(wp > 4) + { + // Bogus value - ignore + break; + } + { + // Parent window size changed, replicate this size in inner window. + int width = LOWORD(lp); + int height = HIWORD(lp); + SetWindowPos(native->m_hwnd, nullptr, -1, -1, width, height, SWP_NOMOVE); + } + break; + } + + return DefSubclassProc(hwnd, msg, wp, lp); +} + +NativeWindowWin32::NativeWindowWin32(void* native_window, Window& window) + : window(window) +{ + WNDCLASSEX wcex{}; + + //Time to register a window class. + //Generic flags and everything. cbWndExtra is the size of a pointer to an + // object - we need this in the wndproc handler. + + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_DBLCLKS;//class_style; + wcex.lpfnWndProc = (WNDPROC)dialogProc; + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + // Set data: + wcex.cbWndExtra = sizeof(NativeWindowWin32*); // Size of data. + wcex.hInstance = GetModuleHandle(nullptr); + + // if(ex_style && WS_EX_TRANSPARENT == WS_EX_TRANSPARENT) { + // wcex.hbrBackground = nullptr; + // } else { + wcex.hbrBackground = nullptr;//(HBRUSH) COLOR_BACKGROUND + 1; + // } + + const char* name = "DrumGizmoClass"; + char* c_name = (char*)malloc(strlen(name) + 1); + strcpy(c_name, name); + wcex.lpszClassName = m_className = c_name; + + RegisterClassEx(&wcex); + + parent_window = (HWND)native_window; + + int width = 1, height = 1; + if(parent_window) + { + // Listen in on parent size changes. + SetWindowSubclass(parent_window, subClassProc, 42, (LONG_PTR)this); + + // Resize newly created window to fit into parent. + RECT rect; + GetClientRect(parent_window, &rect); + + auto resizeEvent = std::make_shared(); + width = resizeEvent->width = rect.right - rect.left; + height = resizeEvent->height = rect.bottom - rect.top; + event_queue.push_back(resizeEvent); + } + + m_hwnd = CreateWindowEx(0/*ex_style*/, m_className, + "DGBasisWidget", + (native_window?WS_CHILD:WS_OVERLAPPEDWINDOW) | + (native_window?WS_VISIBLE:0), + 0, 0, + width, height, + parent_window, nullptr, + GetModuleHandle(nullptr), nullptr); + + SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); + + // Set up initial tracking of the mouse leave events + trackMouse(m_hwnd); +} + +NativeWindowWin32::~NativeWindowWin32() +{ + if(parent_window) + { + RemoveWindowSubclass(parent_window, subClassProc, 42); + } + DestroyWindow(m_hwnd); + UnregisterClass(m_className, GetModuleHandle(nullptr)); + free(m_className); +} + +void NativeWindowWin32::setFixedSize(std::size_t width, std::size_t height) +{ + resize(width, height); + LONG style = GetWindowLong(m_hwnd, GWL_STYLE); + style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); + SetWindowLong(m_hwnd, GWL_STYLE, style); +} + +void NativeWindowWin32::setAlwaysOnTop(bool always_on_top) +{ + this->always_on_top = always_on_top; + SetWindowPos(m_hwnd, always_on_top ? HWND_TOPMOST : nullptr, + 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); +} + +void NativeWindowWin32::resize(std::size_t width, std::size_t height) +{ + auto hwnd = m_hwnd; + //if(parent_window) + //{ + // hwnd = parent_window; + //} + + // Set requested size on the window (or parent) + SetWindowPos(hwnd, always_on_top ? HWND_TOPMOST : nullptr, + -1, -1, (int)width, (int)height, SWP_NOMOVE); + + // Ask the client window what size it actually got + RECT rect; + GetClientRect(m_hwnd, &rect); + int w = width - rect.right; + int h = height - rect.bottom; + + // Set the compensated size on the window (or parent) + SetWindowPos(hwnd, always_on_top ? HWND_TOPMOST : nullptr, + -1, -1, width + w, height + h, SWP_NOMOVE); +} + +std::pair NativeWindowWin32::getSize() const +{ + RECT rect; + GetClientRect(m_hwnd, &rect); + return std::make_pair(rect.right - rect.left, rect.bottom - rect.top); +} + +void NativeWindowWin32::move(int x, int y) +{ + SetWindowPos(m_hwnd, always_on_top ? HWND_TOPMOST : nullptr, + (int)x, (int)y, -1, -1, SWP_NOSIZE); +} + +std::pair NativeWindowWin32::getPosition() const +{ + RECT rect; + GetClientRect(m_hwnd, &rect); + return std::make_pair(rect.left, rect.top); +} + +void NativeWindowWin32::show() +{ + ShowWindow(m_hwnd, SW_SHOW); +} + +void NativeWindowWin32::hide() +{ + ShowWindow(m_hwnd, SW_HIDE); +} + +bool NativeWindowWin32::visible() const +{ + return IsWindowVisible(m_hwnd); +} + +void NativeWindowWin32::redraw(const Rect& dirty_rect) +{ + // Send WM_PAINT message. Buffer transfering is handled in MessageHandler. + if(parent_window == nullptr) + { + RECT rect = + { + (long)dirty_rect.x1, + (long)dirty_rect.y1, + (long)dirty_rect.x2, + (long)dirty_rect.y2 + }; + RedrawWindow(m_hwnd, &rect, nullptr, RDW_INVALIDATE); + UpdateWindow(m_hwnd); + } + else + { + InvalidateRect(m_hwnd, 0, TRUE); + } +} + +void NativeWindowWin32::setCaption(const std::string &caption) +{ + SetWindowText(m_hwnd, caption.c_str()); +} + +void NativeWindowWin32::grabMouse(bool grab) +{ + if(grab) + { + SetCapture(m_hwnd); + } + else + { + ReleaseCapture(); + } +} + +EventQueue NativeWindowWin32::getEvents() +{ + MSG msg; + while(PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE) != 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + EventQueue events; + std::swap(events, event_queue); + return events; +} + +void* NativeWindowWin32::getNativeWindowHandle() const +{ + return (void*)m_hwnd; +} + +Point NativeWindowWin32::translateToScreen(const Point& point) +{ + POINT p{ point.x, point.y }; + ClientToScreen(m_hwnd, &p); + return { p.x, p.y }; +} + +} // GUI:: diff --git a/dggui/nativewindow_win32.h b/dggui/nativewindow_win32.h new file mode 100644 index 0000000..046b38a --- /dev/null +++ b/dggui/nativewindow_win32.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_win32.h + * + * Fri Dec 28 18:45:51 CET 2012 + * Copyright 2012 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "nativewindow.h" + +#define WIN32_LEAN_AND_MEAN +#include +typedef HWND WNDID; + +namespace GUI { + +class Window; +class Event; + +class NativeWindowWin32 : public NativeWindow { +public: + NativeWindowWin32(void* native_window, Window& window); + ~NativeWindowWin32(); + + void setFixedSize(std::size_t width, std::size_t height) override; + void setAlwaysOnTop(bool always_on_top) override; + void resize(std::size_t width, std::size_t height) override; + std::pair getSize() const override; + void move(int x, int y) override; + std::pair getPosition() const override; + void show() override; + bool visible() const override; + void hide() override; + void redraw(const Rect& dirty_rect) override; + void setCaption(const std::string &caption) override; + void grabMouse(bool grab) override; + EventQueue getEvents() override; + void* getNativeWindowHandle() const override; + Point translateToScreen(const Point& point) override; + +private: + static LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); + static LRESULT CALLBACK subClassProc(HWND hwnd, UINT msg, WPARAM wp, + LPARAM lp, UINT_PTR id, DWORD_PTR data); + + HWND parent_window; + Window& window; + WNDID m_hwnd = 0; + bool mouse_in_window{false}; + std::pair last_mouse_position{0, 0}; + char* m_className = nullptr; + EventQueue event_queue; + bool always_on_top{false}; +}; + +} // GUI:: diff --git a/dggui/nativewindow_x11.cc b/dggui/nativewindow_x11.cc new file mode 100644 index 0000000..33dde7b --- /dev/null +++ b/dggui/nativewindow_x11.cc @@ -0,0 +1,715 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_x11.cc + * + * Fri Dec 28 18:45:57 CET 2012 + * Copyright 2012 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "nativewindow_x11.h" + +//http://www.mesa3d.org/brianp/xshm.c + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "window.h" + +namespace GUI +{ + +#define _NET_WM_STATE_REMOVE 0 // remove/unset property +#define _NET_WM_STATE_ADD 1 // add/set property + +void setWindowFront(Display *disp, ::Window wind, bool enable) +{ + Atom wm_state, wm_state_above; + XEvent event; + + if((wm_state = XInternAtom(disp, "_NET_WM_STATE", False)) == None) + { + return; + } + + if((wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False)) == None) + { + return; + } + // + //window = the respective client window + //message_type = _NET_WM_STATE + //format = 32 + //data.l[0] = the action, as listed below + //data.l[1] = first property to alter + //data.l[2] = second property to alter + //data.l[3] = source indication (0-unk,1-normal app,2-pager) + //other data.l[] elements = 0 + // + + // sending a ClientMessage + event.xclient.type = ClientMessage; + + // value unimportant in this case + event.xclient.serial = 0; + + // coming from a SendEvent request, so True + event.xclient.send_event = True; + + // the event originates from disp + event.xclient.display = disp; + + // the window whose state will be modified + event.xclient.window = wind; + + // the component Atom being modified in the window + event.xclient.message_type = wm_state; + + // specifies that data.l will be used + event.xclient.format = 32; + + // 0 is _NET_WM_STATE_REMOVE, 1 is _NET_WM_STATE_ADD + event.xclient.data.l[0] = + enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + + // the atom being added + event.xclient.data.l[1] = wm_state_above; + + // unused + event.xclient.data.l[2] = 0; + event.xclient.data.l[3] = 0; + event.xclient.data.l[4] = 0; + + // actually send the event + XSendEvent(disp, DefaultRootWindow(disp), False, + SubstructureRedirectMask | SubstructureNotifyMask, &event); +} + +NativeWindowX11::NativeWindowX11(void* native_window, Window& window) + : window(window) +{ + display = XOpenDisplay(nullptr); + if(display == nullptr) + { + ERR(X11, "XOpenDisplay failed"); + return; + } + + screen = DefaultScreen(display); + visual = DefaultVisual(display, screen); + depth = DefaultDepth(display, screen); + + if(native_window) + { + parent_window = (::Window)native_window; + + // Track size changes on the parent window + XSelectInput(display, parent_window, StructureNotifyMask); + } + else + { + parent_window = DefaultRootWindow(display); + } + + // Create the window + XSetWindowAttributes swa; + swa.backing_store = Always; + xwindow = XCreateWindow(display, + parent_window, + 0, 0, //window.x(), window.y(), + 1, 1, //window.width(), window.height(), + 0, // border + CopyFromParent, // depth + CopyFromParent, // class + CopyFromParent, // visual + 0,//CWBackingStore, + &swa); + + long mask = (StructureNotifyMask | + PointerMotionMask | + ButtonPressMask | + ButtonReleaseMask | + KeyPressMask | + KeyReleaseMask| + ExposureMask | + StructureNotifyMask | + SubstructureNotifyMask | + EnterWindowMask | + LeaveWindowMask); + XSelectInput(display, xwindow, mask); + + // Register the delete window message: + wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false); + + Atom protocols[] = { wmDeleteMessage }; + XSetWMProtocols(display, xwindow, protocols, + sizeof(protocols) / sizeof(*protocols)); + + // Create a "Graphics Context" + gc = XCreateGC(display, xwindow, 0, nullptr); +} + +NativeWindowX11::~NativeWindowX11() +{ + if(display == nullptr) + { + return; + } + + deallocateShmImage(); + + XFreeGC(display, gc); + + XDestroyWindow(display, xwindow); + XCloseDisplay(display); +} + +void NativeWindowX11::setFixedSize(std::size_t width, std::size_t height) +{ + if(display == nullptr) + { + return; + } + + resize(width, height); + + XSizeHints size_hints; + memset(&size_hints, 0, sizeof(size_hints)); + + size_hints.flags = PMinSize|PMaxSize; + size_hints.min_width = size_hints.max_width = (int)width; + size_hints.min_height = size_hints.max_height = (int)height; + + XSetNormalHints(display, xwindow, &size_hints); +} + +void NativeWindowX11::setAlwaysOnTop(bool always_on_top) +{ + setWindowFront(display, xwindow, always_on_top); +} + +void NativeWindowX11::resize(std::size_t width, std::size_t height) +{ + if(display == nullptr) + { + return; + } + + XResizeWindow(display, xwindow, width, height); +} + +std::pair NativeWindowX11::getSize() const +{ +// XWindowAttributes attributes; +// XGetWindowAttributes(display, xwindow, &attributes); +// return std::make_pair(attributes.width, attributes.height); + + ::Window root_window; + int x, y; + unsigned int width, height, border, depth; + + XGetGeometry(display, xwindow, &root_window, + &x, &y, + &width, &height, &border, &depth); + + return {width, height}; +} + +void NativeWindowX11::move(int x, int y) +{ + if(display == nullptr) + { + return; + } + + XMoveWindow(display, xwindow, x, y); +} + +std::pair NativeWindowX11::getPosition() const +{ + ::Window root_window; + ::Window child_window; + int x, y; + unsigned int width, height, border, depth; + + XGetGeometry(display, xwindow, &root_window, + &x, &y, + &width, &height, &border, &depth); + + XTranslateCoordinates(display, xwindow, root_window, + 0, 0, &x, &y, &child_window); + + return std::make_pair(x, y); +} + +void NativeWindowX11::show() +{ + if(display == nullptr) + { + return; + } + + XMapWindow(display, xwindow); +} + +void NativeWindowX11::hide() +{ + if(display == nullptr) + { + return; + } + + XUnmapWindow(display, xwindow); +} + +bool NativeWindowX11::visible() const +{ + if(display == nullptr) + { + return false; + } + + XWindowAttributes xwa; + XGetWindowAttributes(display, xwindow, &xwa); + return (xwa.map_state == IsViewable); +} + +void NativeWindowX11::redraw(const Rect& dirty_rect) +{ + if(display == nullptr) + { + return; + } + + auto x1 = dirty_rect.x1; + auto y1 = dirty_rect.y1; + auto x2 = dirty_rect.x2; + auto y2 = dirty_rect.y2; + + // Assert that we don't try to paint a backwards rect. + assert(x1 <= x2); + assert(y1 <= y2); + + updateImageFromBuffer(x1, y1, x2, y2); + + XShmPutImage(display, xwindow, gc, image, x1, y1, x1, y1, + std::min((std::size_t)image->width, (x2 - x1)), + std::min((std::size_t)image->height, (y2 - y1)), false); + XFlush(display); +} + +void NativeWindowX11::setCaption(const std::string &caption) +{ + if(display == nullptr) + { + return; + } + + XStoreName(display, xwindow, caption.c_str()); +} + +void NativeWindowX11::grabMouse(bool grab) +{ + (void)grab; + // Don't need to do anything on this platform... +} + +EventQueue NativeWindowX11::getEvents() +{ + while(XPending(display)) + { + XEvent xEvent; + XNextEvent(display, &xEvent); + translateXMessage(xEvent); + } + + EventQueue events; + std::swap(events, event_queue); + return events; +} + +void* NativeWindowX11::getNativeWindowHandle() const +{ + return (void*)xwindow; +} + +Point NativeWindowX11::translateToScreen(const Point& point) +{ + ::Window child_window; + Point p; + XTranslateCoordinates(display, xwindow, DefaultRootWindow(display), + point.x, point.y, &p.x, &p.y, &child_window); + return p; +} + +void NativeWindowX11::translateXMessage(XEvent& xevent) +{ + switch(xevent.type) + { + case MotionNotify: + //DEBUG(x11, "MotionNotify"); + { + auto mouseMoveEvent = std::make_shared(); + mouseMoveEvent->x = xevent.xmotion.x; + mouseMoveEvent->y = xevent.xmotion.y; + event_queue.push_back(mouseMoveEvent); + } + break; + + case Expose: + //DEBUG(x11, "Expose"); + if(xevent.xexpose.count == 0) + { + auto repaintEvent = std::make_shared(); + repaintEvent->x = xevent.xexpose.x; + repaintEvent->y = xevent.xexpose.y; + repaintEvent->width = xevent.xexpose.width; + repaintEvent->height = xevent.xexpose.height; + event_queue.push_back(repaintEvent); + + if(image) + { + // Redraw the entire window. + Rect rect{0, 0, window.wpixbuf.width, window.wpixbuf.height}; + redraw(rect); + } + } + break; + + case ConfigureNotify: + //DEBUG(x11, "ConfigureNotify"); + + // The parent window size changed, reflect the new size in our own window. + if(xevent.xconfigure.window == parent_window) + { + resize(xevent.xconfigure.width, xevent.xconfigure.height); + return; + } + + { + if((window.width() != (std::size_t)xevent.xconfigure.width) || + (window.height() != (std::size_t)xevent.xconfigure.height)) + { + auto resizeEvent = std::make_shared(); + resizeEvent->width = xevent.xconfigure.width; + resizeEvent->height = xevent.xconfigure.height; + event_queue.push_back(resizeEvent); + } + + if((window.x() != xevent.xconfigure.x) || + (window.y() != xevent.xconfigure.y)) + { + auto moveEvent = std::make_shared(); + moveEvent->x = xevent.xconfigure.x; + moveEvent->y = xevent.xconfigure.y; + event_queue.push_back(moveEvent); + } + } + break; + + case ButtonPress: + case ButtonRelease: + //DEBUG(x11, "ButtonPress"); + { + if((xevent.xbutton.button == 4) || (xevent.xbutton.button == 5)) + { + if(xevent.type == ButtonPress) + { + int scroll = 1; + auto scrollEvent = std::make_shared(); + scrollEvent->x = xevent.xbutton.x; + scrollEvent->y = xevent.xbutton.y; + scrollEvent->delta = scroll * ((xevent.xbutton.button == 4) ? -1 : 1); + event_queue.push_back(scrollEvent); + } + } + else if ((xevent.xbutton.button == 6) || (xevent.xbutton.button == 7)) + { + // Horizontal scrolling case + // FIXME Introduce horizontal scrolling event to handle this. + } + else + { + auto buttonEvent = std::make_shared(); + buttonEvent->x = xevent.xbutton.x; + buttonEvent->y = xevent.xbutton.y; + switch(xevent.xbutton.button) { + case 1: + buttonEvent->button = MouseButton::left; + break; + case 2: + buttonEvent->button = MouseButton::middle; + break; + case 3: + buttonEvent->button = MouseButton::right; + break; + default: + WARN(X11, "Unknown button %d, setting to MouseButton::left\n", + xevent.xbutton.button); + buttonEvent->button = MouseButton::left; + break; + } + + buttonEvent->direction = + (xevent.type == ButtonPress) ? + Direction::down : Direction::up; + + // This is a fix for hosts (e.g. those using JUCE) that set the + // event time to '0'. + if(xevent.xbutton.time == 0) + { + auto now = std::chrono::system_clock::now().time_since_epoch(); + xevent.xbutton.time = + std::chrono::duration_cast(now).count(); + } + + buttonEvent->doubleClick = + (xevent.type == ButtonPress) && + ((xevent.xbutton.time - last_click) < 200); + + if(xevent.type == ButtonPress) + { + last_click = xevent.xbutton.time; + } + event_queue.push_back(buttonEvent); + } + } + break; + + case KeyPress: + case KeyRelease: + //DEBUG(x11, "KeyPress"); + { + auto keyEvent = std::make_shared(); + + switch(xevent.xkey.keycode) { + case 113: keyEvent->keycode = Key::left; break; + case 114: keyEvent->keycode = Key::right; break; + case 111: keyEvent->keycode = Key::up; break; + case 116: keyEvent->keycode = Key::down; break; + case 119: keyEvent->keycode = Key::deleteKey; break; + case 22: keyEvent->keycode = Key::backspace; break; + case 110: keyEvent->keycode = Key::home; break; + case 115: keyEvent->keycode = Key::end; break; + case 117: keyEvent->keycode = Key::pageDown; break; + case 112: keyEvent->keycode = Key::pageUp; break; + case 36: keyEvent->keycode = Key::enter; break; + default: keyEvent->keycode = Key::unknown; break; + } + + char stringBuffer[1024]; + int size = XLookupString(&xevent.xkey, stringBuffer, + sizeof(stringBuffer), nullptr, nullptr); + if(size && keyEvent->keycode == Key::unknown) + { + keyEvent->keycode = Key::character; + } + + keyEvent->text.append(stringBuffer, size); + + keyEvent->direction = + (xevent.type == KeyPress) ? Direction::down : Direction::up; + + event_queue.push_back(keyEvent); + } + break; + + case ClientMessage: + //DEBUG(x11, "ClientMessage"); + if(((unsigned int)xevent.xclient.data.l[0] == wmDeleteMessage)) + { + auto closeEvent = std::make_shared(); + event_queue.push_back(closeEvent); + } + break; + + case EnterNotify: + //DEBUG(x11, "EnterNotify"); + { + auto enterEvent = std::make_shared(); + enterEvent->x = xevent.xcrossing.x; + enterEvent->y = xevent.xcrossing.y; + event_queue.push_back(enterEvent); + } + break; + + case LeaveNotify: + //DEBUG(x11, "LeaveNotify"); + { + auto leaveEvent = std::make_shared(); + leaveEvent->x = xevent.xcrossing.x; + leaveEvent->y = xevent.xcrossing.y; + event_queue.push_back(leaveEvent); + } + break; + + case MapNotify: + case MappingNotify: + //DEBUG(x11, "EnterNotify"); + // There's nothing to do here atm. + break; + + default: + WARN(X11, "Unhandled xevent.type: %d\n", xevent.type); + break; + } +} + +void NativeWindowX11::allocateShmImage(std::size_t width, std::size_t height) +{ + DEBUG(x11, "(Re)alloc XShmImage (%d, %d)", (int)width, (int)height); + + if(image) + { + deallocateShmImage(); + } + + if(!XShmQueryExtension(display)) + { + ERR(x11, "XShmExtension not available"); + return; + } + + image = XShmCreateImage(display, visual, depth, + ZPixmap, nullptr, &shm_info, + width, height); + if(image == nullptr) + { + ERR(x11, "XShmCreateImage failed!\n"); + return; + } + + std::size_t byte_size = image->bytes_per_line * image->height; + + // Allocate shm buffer + int shm_id = shmget(IPC_PRIVATE, byte_size, IPC_CREAT|0777); + if(shm_id == -1) + { + ERR(x11, "shmget failed: %s", strerror(errno)); + return; + } + + shm_info.shmid = shm_id; + + // Attach share memory bufer + void* shm_addr = shmat(shm_id, nullptr, 0); + if(reinterpret_cast(shm_addr) == -1) + { + ERR(x11, "shmat failed: %s", strerror(errno)); + return; + } + + shm_info.shmaddr = reinterpret_cast(shm_addr); + image->data = shm_info.shmaddr; + shm_info.readOnly = false; + + // This may trigger the X protocol error we're ready to catch: + XShmAttach(display, &shm_info); + XSync(display, false); + + // Make the shm id unavailable to others + shmctl(shm_id, IPC_RMID, 0); +} + +void NativeWindowX11::deallocateShmImage() +{ + if(image == nullptr) + { + return; + } + + XFlush(display); + XShmDetach(display, &shm_info); + XDestroyImage(image); + image = nullptr; + shmdt(shm_info.shmaddr); +} + +void NativeWindowX11::updateImageFromBuffer(std::size_t x1, std::size_t y1, + std::size_t x2, std::size_t y2) +{ + //DEBUG(x11, "depth: %d", depth); + + auto width = window.wpixbuf.width; + auto height = window.wpixbuf.height; + + // If image hasn't been allocated yet or if the image backbuffer is + // too small, (re)allocate with a suitable size. + if((image == nullptr) || + ((int)width > image->width) || + ((int)height > image->height)) + { + constexpr std::size_t step_size = 128; // size increments + std::size_t new_width = ((width / step_size) + 1) * step_size; + std::size_t new_height = ((height / step_size) + 1) * step_size; + allocateShmImage(new_width, new_height); + x1 = 0; + y1 = 0; + x2 = width; + y2 = height; + } + + auto stride = image->width; + + std::uint8_t* pixel_buffer = (std::uint8_t*)window.wpixbuf.buf; + if(depth >= 24) // RGB 888 format + { + std::uint32_t* shm_addr = (std::uint32_t*)shm_info.shmaddr; + for(std::size_t y = y1; y < y2; ++y) + { + for(std::size_t x = x1; x < x2; ++x) + { + const std::size_t pin = y * width + x; + const std::size_t pout = y * stride + x; + const std::uint8_t red = pixel_buffer[pin * 3]; + const std::uint8_t green = pixel_buffer[pin * 3 + 1]; + const std::uint8_t blue = pixel_buffer[pin * 3 + 2]; + shm_addr[pout] = (red << 16) | (green << 8) | blue; + } + } + } + else if(depth >= 15) // RGB 565 format + { + std::uint16_t* shm_addr = (std::uint16_t*)shm_info.shmaddr; + + for(std::size_t y = y1; y < y2; ++y) + { + for(std::size_t x = x1; x < x2; ++x) + { + const std::size_t pin = y * width + x; + const std::size_t pout = y * stride + x; + const std::uint8_t red = pixel_buffer[pin * 3]; + const std::uint8_t green = pixel_buffer[pin * 3 + 1]; + const std::uint8_t blue = pixel_buffer[pin * 3 + 2]; + shm_addr[pout] = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); + } + } + } +} + +} // GUI:: diff --git a/dggui/nativewindow_x11.h b/dggui/nativewindow_x11.h new file mode 100644 index 0000000..cb56fbc --- /dev/null +++ b/dggui/nativewindow_x11.h @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * nativewindow_x11.h + * + * Fri Dec 28 18:45:56 CET 2012 + * Copyright 2012 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include +#include + +#include "nativewindow.h" + +namespace GUI +{ + +class Window; + +class NativeWindowX11 + : public NativeWindow +{ +public: + NativeWindowX11(void* native_window, Window& window); + ~NativeWindowX11(); + + // From NativeWindow: + void setFixedSize(std::size_t width, std::size_t height) override; + void setAlwaysOnTop(bool always_on_top) override; + void resize(std::size_t width, std::size_t height) override; + std::pair getSize() const override; + void move(int x, int y) override; + std::pair getPosition() const override; + void show() override; + void hide() override; + bool visible() const override; + void setCaption(const std::string &caption) override; + void redraw(const Rect& dirty_rect) override; + void grabMouse(bool grab) override; + EventQueue getEvents() override; + void* getNativeWindowHandle() const override; + Point translateToScreen(const Point& point) override; + +private: + void translateXMessage(XEvent& xevent); + + //! Allocate new shared memory buffer for the pixel buffer. + //! Frees the existing buffer if there is one. + void allocateShmImage(std::size_t width, std::size_t height); + + //! Deallocate image and shm resources. + void deallocateShmImage(); + + //! Copy data from the pixel buffer into the shared memory + void updateImageFromBuffer(std::size_t x1, std::size_t y1, + std::size_t x2, std::size_t y2); + + XShmSegmentInfo shm_info; + XImage* image{nullptr}; + + ::Window xwindow{0}; + GC gc{0}; + + Window& window; + + Time last_click{0}; + + Display* display{nullptr}; + int screen{0}; + int depth{0}; + Visual* visual{nullptr}; + Atom wmDeleteMessage{0}; + ::Window parent_window; + + EventQueue event_queue; +}; + +} // GUI:: diff --git a/dggui/painter.cc b/dggui/painter.cc new file mode 100644 index 0000000..f746f83 --- /dev/null +++ b/dggui/painter.cc @@ -0,0 +1,644 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * painter.cc + * + * Wed Oct 12 19:48:45 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "painter.h" + +#include +#include + +#include "pixelbuffer.h" +#include "font.h" +#include "drawable.h" +#include "image.h" +#include "canvas.h" + +namespace GUI +{ + +Painter::Painter(Canvas& canvas) + : pixbuf(canvas.getPixelBuffer()) +{ + colour = Colour(0.0f, 0.0f, 0.0f, 0.5f); +} + +Painter::~Painter() +{ +} + +void Painter::setColour(const Colour& colour) +{ + this->colour = colour; +} + +static void plot(PixelBufferAlpha& pixbuf, const Colour& colour, + int x, int y, double c) +{ + if((x >= (int)pixbuf.width) || + (y >= (int)pixbuf.height) || + (x < 0) || + (y < 0)) + { + return; + } + + // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1) + Colour col(colour); + if(c != 1) + { + col.data()[3] *= c; + } + pixbuf.addPixel(x, y, col); +} + +static inline double fpart(double x) +{ + return x - std::floor(x);// fractional part of x +} + +static inline double rfpart(double x) +{ + return 1 - fpart(x); // reverse fractional part of x +} + +void Painter::drawLine(int x0, int y0, int x1, int y1) +{ + bool steep = abs(y1 - y0) > abs(x1 - x0); + + if(steep) + { + std::swap(x0, y0); + std::swap(x1, y1); + } + if(x0 > x1) + { + std::swap(x0, x1); + std::swap(y0, y1); + } + + double dx = x1 - x0; + double dy = y1 - y0; + double gradient = dy / dx; + + // Handle first endpoint: + double xend = std::round(x0); + double yend = y0 + gradient * (xend - x0); + + double xpxl1 = xend; // this will be used in the main loop + double ypxl1 = std::floor(yend); + + if(steep) + { + pixbuf.addPixel(ypxl1, xpxl1, colour); + } + else + { + pixbuf.addPixel(xpxl1, ypxl1, colour); + } + + double intery = yend + gradient; // first y-intersection for the main loop + + // Handle second endpoint: + xend = std::round(x1); + yend = y1 + gradient * (xend - x1); + + double xpxl2 = xend; // this will be used in the main loop + double ypxl2 = std::floor(yend); + + if(steep) + { + pixbuf.addPixel(ypxl2, xpxl2, colour); + } + else + { + pixbuf.addPixel(xpxl2, ypxl2, colour); + } + + // main loop + for(int x = xpxl1 + 1; x <= xpxl2 - 1; ++x) + { + if(steep) + { + plot(pixbuf, colour, std::floor(intery) , x, rfpart(intery)); + plot(pixbuf, colour, std::floor(intery)+1, x, fpart(intery)); + } + else + { + plot(pixbuf, colour, x, std::floor(intery), rfpart(intery)); + plot(pixbuf, colour, x, std::floor(intery)+1, fpart(intery)); + } + intery += gradient; + } +} + +void Painter::drawRectangle(int x1, int y1, int x2, int y2) +{ + drawLine(x1, y1, x2 - 1, y1); + drawLine(x2, y1, x2, y2 - 1); + drawLine(x1 + 1, y2, x2, y2); + drawLine(x1, y1 + 1, x1, y2); +} + +void Painter::drawFilledRectangle(int x1, int y1, int x2, int y2) +{ + for(int y = y1; y <= y2; ++y) + { + drawLine(x1, y, x2, y); + } +} + +void Painter::clear() +{ + pixbuf.clear(); +} + +void Painter::drawText(int x0, int y0, const Font& font, + const std::string& text, bool nocolour, bool rotate) +{ + PixelBufferAlpha* textbuf = font.render(text); + + if(!rotate) + { + y0 -= textbuf->height; // The y0 offset (baseline) is the bottom of the text. + } + + // If the text offset is outside the buffer; skip it. + if((x0 > (int)pixbuf.width) || (y0 > (int)pixbuf.height)) + { + delete textbuf; + return; + } + + // Make sure we don't try to draw outside the pixbuf. + int renderWidth = textbuf->width; + if(renderWidth > (int)(pixbuf.width - x0)) + { + renderWidth = pixbuf.width - x0; + } + + int renderHeight = textbuf->height; + if(renderHeight > ((int)pixbuf.height - y0)) + { + renderHeight = ((int)pixbuf.height - y0); + } + + if(nocolour) + { + for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) + { + int x = -1 * std::min(0, x0); + + assert(x >= 0); + assert(y >= 0); + assert(x < (int)textbuf->width); + assert(y < (int)textbuf->height); + + auto c = textbuf->getLine(x, y); + + assert(x + x0 >= 0); + assert(y + y0 >= 0); + assert(x + x0 < (int)pixbuf.width); + assert(y + y0 < (int)pixbuf.height); + + pixbuf.blendLine(x + x0, y + y0, c, renderWidth - x); + } + } + else if(rotate) + { + int renderWidth = textbuf->height; + if(renderWidth > (int)(pixbuf.width - x0)) + { + renderWidth = pixbuf.width - x0; + } + + int renderHeight = textbuf->width; + if(renderHeight > ((int)pixbuf.height - y0)) + { + renderHeight = ((int)pixbuf.height - y0); + } + + for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) + { + for(int x = -1 * std::min(0, x0); x < renderWidth; ++x) + { + assert(x >= 0); + assert(y >= 0); + assert(x < (int)textbuf->height); + assert(y < (int)textbuf->width); + + auto c = textbuf->pixel(textbuf->width - y - 1, x); + + assert(x + x0 >= 0); + assert(y + y0 >= 0); + assert(x + x0 < (int)pixbuf.width); + assert(y + y0 < (int)pixbuf.height); + + Colour col(colour.red(), colour.green(), + colour.blue(), (int)(colour.alpha() * c.alpha()) / 255); + pixbuf.addPixel(x + x0, y + y0, col); + } + } + } + else + { + for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) + { + for(int x = -1 * std::min(0, x0); x < renderWidth; ++x) + { + assert(x >= 0); + assert(y >= 0); + assert(x < (int)textbuf->width); + assert(y < (int)textbuf->height); + + auto c = textbuf->pixel(x, y); + + assert(x + x0 >= 0); + assert(y + y0 >= 0); + assert(x + x0 < (int)pixbuf.width); + assert(y + y0 < (int)pixbuf.height); + + Colour col(colour.red(), colour.green(), + colour.blue(), (int)(colour.alpha() * c.alpha()) / 255); + pixbuf.addPixel(x + x0, y + y0, col); + } + } + } + + delete textbuf; +} + +void Painter::drawPoint(int x, int y) +{ + if(x >= 0 && y >= 0 && (std::size_t)x < pixbuf.width && (std::size_t)y < pixbuf.height) + { + pixbuf.setPixel(x, y, colour); + } +} + +static void plot4points(Painter *p, int cx, int cy, int x, int y) +{ + p->drawPoint(cx + x, cy + y); + if(x != 0) + { + p->drawPoint(cx - x, cy + y); + } + + if(y != 0) + { + p->drawPoint(cx + x, cy - y); + } + + if(x != 0 && y != 0) + { + p->drawPoint(cx - x, cy - y); + } +} + +void Painter::drawCircle(int cx, int cy, double radius) +{ + int error = -radius; + int x = radius; + int y = 0; + + while(x >= y) + { + plot4points(this, cx, cy, x, y); + + if(x != y) + { + plot4points(this, cx, cy, y, x); + } + + error += y; + ++y; + error += y; + + if(error >= 0) + { + --x; + error -= x; + error -= x; + } + } +} + +static void plot4lines(Painter *p, int cx, int cy, int x, int y) +{ + p->drawLine(cx + x, cy + y, cx - x, cy + y); + if(x != 0) + { + p->drawLine(cx - x, cy + y, cx + x, cy + y); + } + + if(y != 0) + { + p->drawLine(cx + x, cy - y, cx - x, cy - y); + } + + if(x != 0 && y != 0) + { + p->drawLine(cx - x, cy - y, cx + x, cy - y); + } +} + +void Painter::drawFilledCircle(int cx, int cy, int radius) +{ + int error = -radius; + int x = radius; + int y = 0; + + while(x >= y) + { + plot4lines(this, cx, cy, x, y); + + if(x != y) + { + plot4lines(this, cx, cy, y, x); + } + + error += y; + ++y; + error += y; + + if(error >= 0) + { + --x; + error -= x; + error -= x; + } + } +} + +void Painter::drawImage(int x0, int y0, const Drawable& image) +{ + int fw = image.width(); + int fh = image.height(); + + // Make sure we don't try to draw outside the pixbuf. + if(fw > (int)(pixbuf.width - x0)) + { + fw = (int)(pixbuf.width - x0); + } + + if(fh > (int)(pixbuf.height - y0)) + { + fh = (int)(pixbuf.height - y0); + } + + if((fw < 1) || (fh < 1)) + { + return; + } + + if(image.hasAlpha()) + { + if(!image.line(0)) + { + for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) + { + for(std::size_t x = -1 * std::min(0, x0); x < (std::size_t)fw; ++x) + { + assert(x >= 0); + assert(y >= 0); + assert(x < image.width()); + assert(y < image.height()); + auto& c = image.getPixel(x, y); + + assert(x0 + x >= 0); + assert(y0 + y >= 0); + assert(x0 + x < pixbuf.width); + assert(y0 + y < pixbuf.height); + + pixbuf.addPixel(x0 + x, y0 + y, c); + } + } + } + else + { + std::size_t x_offset = -1 * std::min(0, x0); + for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) + { + pixbuf.blendLine(x_offset + x0, y + y0, image.line(y, x_offset), + std::min((int)image.width(), fw - (int)x_offset)); + } + } + } + else + { + std::size_t x_offset = -1 * std::min(0, x0); + for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) + { + pixbuf.writeLine(x_offset + x0, y + y0, image.line(y, x_offset), + std::min((int)image.width(), fw - (int)x_offset)); + } + } +} + +void Painter::drawRestrictedImage(int x0, int y0, + const Colour& restriction_colour, + const Drawable& image) +{ + int fw = image.width(); + int fh = image.height(); + + // Make sure we don't try to draw outside the pixbuf. + if(fw > (int)(pixbuf.width - x0)) + { + fw = (int)(pixbuf.width - x0); + } + + if(fh > (int)(pixbuf.height - y0)) + { + fh = (int)(pixbuf.height - y0); + } + + if((fw < 1) || (fh < 1)) + { + return; + } + + for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) + { + for(std::size_t x = -1 * std::min(0, x0); x < (std::size_t)fw; ++x) + { + assert(x >= 0); + assert(y >= 0); + assert(x < image.width()); + assert(y < image.height()); + auto& c = image.getPixel(x, y); + + assert(x0 + x >= 0); + assert(y0 + y >= 0); + assert(x0 + x < pixbuf.width); + assert(y0 + y < pixbuf.height); + + if(c == restriction_colour) + { + pixbuf.setPixel(x0 + x, y0 + y, c); + } + } + } +} + +void Painter::drawImageStretched(int x0, int y0, const Drawable& image, + int width, int height) +{ + float fw = image.width(); + float fh = image.height(); + + // Make sure we don't try to draw outside the pixbuf. + if(width > (int)(pixbuf.width - x0)) + { + width = pixbuf.width - x0; + } + + if(height > (int)(pixbuf.height - y0)) + { + height = pixbuf.height - y0; + } + + if((width < 1) || (height < 1)) + { + return; + } + + for(int y = -1 * std::min(0, y0); y < height; ++y) + { + for(int x = -1 * std::min(0, x0); x < width; ++x) + { + int lx = ((float)x / (float)width) * fw; + int ly = ((float)y / (float)height) * fh; + auto& c = image.getPixel(lx, ly); + pixbuf.addPixel(x0 + x, y0 + y, c); + } + } +} + +void Painter::drawBox(int x, int y, const Box& box, int width, int height) +{ + int dx = x; + int dy = y; + + // Top: + drawImage(dx, dy, *box.topLeft); + + dx += box.topLeft->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.top, + width - box.topRight->width() - box.topLeft->width(), + box.top->height()); + + dx = x + width - box.topRight->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImage(dx, dy, *box.topRight); + + // Center: + dy = y + box.topLeft->height(); + dx = x + box.left->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.center, + width - box.left->width() - box.right->width(), + height - box.topLeft->height() - box.bottomLeft->height()); + + // Mid: + dx = x; + dy = y + box.topLeft->height(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.left, box.left->width(), + height - box.topLeft->height() - box.bottomLeft->height()); + + dx = x + width - box.right->width(); + dy = y + box.topRight->height(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.right, + box.right->width(), + height - box.topRight->height() - box.bottomRight->height()); + + // Bottom: + dx = x; + dy = y + height - box.bottomLeft->height(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImage(dx, dy, *box.bottomLeft); + + dx += box.bottomLeft->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.bottom, + width - box.bottomRight->width() - box.bottomLeft->width(), + box.bottom->height()); + + dx = x + width - box.bottomRight->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImage(dx, dy, *box.bottomRight); +} + +void Painter::drawBar(int x, int y, const Bar& bar, int width, int height) +{ + if(width < ((int)bar.left->width() + (int)bar.right->width() + 1)) + { + width = bar.left->width() + bar.right->width() + 1; + } + + drawImageStretched(x, y, *bar.left, bar.left->width(), height); + + drawImageStretched(x + bar.left->width(), y, *bar.center, + width - bar.left->width() - bar.right->width(), height); + + drawImageStretched(x + width - bar.left->width(), y, *bar.right, + bar.right->width(), height); +} + +} // GUI:: diff --git a/dggui/painter.h b/dggui/painter.h new file mode 100644 index 0000000..9bf7fbf --- /dev/null +++ b/dggui/painter.h @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * painter.h + * + * Wed Oct 12 19:48:45 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "colour.h" +#include "pixelbuffer.h" + +namespace GUI +{ + +class Font; +class Drawable; +class Image; +class Canvas; + +class Painter +{ +public: + Painter(Canvas& canvas); + ~Painter(); + + void setColour(const Colour& colour); + + void drawLine(int x1, int y1, int x2, int y2); + void drawText(int x, int y, const Font& font, const std::string& text, + bool nocolour = false, bool rotate = false); + void drawRectangle(int x1, int y1, int x2, int y2); + void drawFilledRectangle(int x1, int y1, int x2, int y2); + void drawPoint(int x, int y); + void drawCircle(int x, int y, double r); + void drawFilledCircle(int x, int y, int r); + void drawImage(int x, int y, const Drawable& image); + void drawRestrictedImage(int x0, int y0, const Colour& restriction_colour, + const Drawable& image); + void drawImageStretched(int x, int y, const Drawable& image, + int width, int height); + + template + void draw(Iterator begin, Iterator end, int x_offset, int y_offset, Colour const& colour); + + typedef struct { + Image* topLeft; + Image* top; + Image* topRight; + Image* left; + Image* right; + Image* bottomLeft; + Image* bottom; + Image* bottomRight; + Image* center; + } Box; + void drawBox(int x, int y, const Box& box, int width, int height); + + typedef struct { + Image* left; + Image* right; + Image* center; + } Bar; + void drawBar(int x, int y, const Bar& bar, int width, int height); + + void clear(); + +private: + PixelBufferAlpha& pixbuf; + Colour colour; +}; + +template +void Painter::draw(Iterator begin, Iterator end, int x_offset, int y_offset, Colour const& colour) +{ + for (auto it = begin; it != end; ++it) + { + pixbuf.addPixel(x_offset + it->x, y_offset + it->y, colour); + } +} + +} // GUI:: diff --git a/dggui/pixelbuffer.cc b/dggui/pixelbuffer.cc new file mode 100644 index 0000000..3c666cd --- /dev/null +++ b/dggui/pixelbuffer.cc @@ -0,0 +1,369 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * pixelbuffer.cc + * + * Thu Nov 10 09:00:38 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "pixelbuffer.h" + +#include + +#include +#include +#include + +namespace GUI +{ + +PixelBuffer::PixelBuffer(std::size_t width, std::size_t height) +{ + realloc(width, height); +} + +PixelBuffer::~PixelBuffer() +{ +} + +void PixelBuffer::realloc(std::size_t width, std::size_t height) +{ + buf_data.resize(width * height * 3); + buf = buf_data.data(); + this->width = width; + this->height = height; +} + +void PixelBuffer::blendLine(std::size_t x, std::size_t y, + const std::uint8_t* line, std::size_t len) +{ + std::uint8_t* target = buf + (x + y * width) * 3; + while(len) + { + if(line[3] == 0xff) + { + std::memcpy(target, line, 3); + } + else + { + unsigned int a = line[3]; + unsigned int b = 255 - a; + + target[0] = (std::uint8_t)((line[0] * a + target[0] * b) / 255); + target[1] = (std::uint8_t)((line[1] * a + target[1] * b) / 255); + target[2] = (std::uint8_t)((line[2] * a + target[2] * b) / 255); + } + target += 3; + line += 4; + --len; + } +} + +Rect PixelBuffer::updateBuffer(std::vector& pixel_buffers) +{ + bool has_dirty_rect{false}; + Rect dirty_rect; + + for(const auto& pixel_buffer : pixel_buffers) + { + if(pixel_buffer->dirty) + { + auto x1 = (std::size_t)std::max(pixel_buffer->x, 0); + auto x2 = (std::size_t)std::max((pixel_buffer->x + (int)pixel_buffer->width), 0); + auto y1 = (std::size_t)std::max(pixel_buffer->y, 0); + auto y2 = (std::size_t)std::max((pixel_buffer->y + (int)pixel_buffer->height), 0); + + pixel_buffer->dirty = false; + if(!has_dirty_rect) + { + // Insert this area: + dirty_rect = {x1, y1, x2, y2}; + has_dirty_rect = true; + } + else + { + // Expand existing area: + auto x1_0 = dirty_rect.x1; + auto y1_0 = dirty_rect.y1; + auto x2_0 = dirty_rect.x2; + auto y2_0 = dirty_rect.y2; + dirty_rect = { + (x1_0 < x1) ? x1_0 : x1, + (y1_0 < y1) ? y1_0 : y1, + (x2_0 > x2) ? x2_0 : x2, + (y2_0 > y2) ? y2_0 : y2 + }; + } + } + + if(pixel_buffer->has_last) + { + auto x1 = (std::size_t)pixel_buffer->last_x; + auto x2 = (std::size_t)(pixel_buffer->last_x + pixel_buffer->last_width); + auto y1 = (std::size_t)pixel_buffer->last_y; + auto y2 = (std::size_t)(pixel_buffer->last_y + pixel_buffer->last_height); + + pixel_buffer->has_last = false; + if(!has_dirty_rect) + { + // Insert this area: + dirty_rect = {x1, y1, x2, y2}; + has_dirty_rect = true; + } + else + { + // Expand existing area: + auto x1_0 = dirty_rect.x1; + auto y1_0 = dirty_rect.y1; + auto x2_0 = dirty_rect.x2; + auto y2_0 = dirty_rect.y2; + dirty_rect = { + (x1_0 < x1) ? x1_0 : x1, + (y1_0 < y1) ? y1_0 : y1, + (x2_0 > x2) ? x2_0 : x2, + (y2_0 > y2) ? y2_0 : y2 + }; + } + } + } + + if(!has_dirty_rect) + { + return {}; + } + + for(const auto& pixel_buffer : pixel_buffers) + { + if(!pixel_buffer->visible) + { + continue; + } + + int update_width = pixel_buffer->width; + int update_height = pixel_buffer->height; + + // Skip buffer if not inside window. + if(((int)width < pixel_buffer->x) || + ((int)height < pixel_buffer->y)) + { + continue; + } + + if(update_width > ((int)width - pixel_buffer->x)) + { + update_width = ((int)width - pixel_buffer->x); + } + + if(update_height > ((int)height - pixel_buffer->y)) + { + update_height = ((int)height - pixel_buffer->y); + } + + auto from_x = (int)dirty_rect.x1 - pixel_buffer->x; + from_x = std::max(0, from_x); + auto from_y = (int)dirty_rect.y1 - pixel_buffer->y; + from_y = std::max(0, from_y); + + auto to_x = (int)dirty_rect.x2 - pixel_buffer->x; + to_x = std::min(to_x, (int)update_width); + auto to_y = (int)dirty_rect.y2 - pixel_buffer->y; + to_y = std::min(to_y, (int)update_height); + + if(to_x < from_x) + { + continue; + } + + for(int y = from_y; y < to_y; y++) + { + blendLine(pixel_buffer->x + from_x, + pixel_buffer->y + y, + pixel_buffer->getLine(from_x, y), + to_x - from_x); + } + } + + dirty_rect.x2 = std::min(width, dirty_rect.x2); + dirty_rect.y2 = std::min(height, dirty_rect.y2); + + // Make sure we don't try to paint a rect backwards. + if(dirty_rect.x1 > dirty_rect.x2) + { + std::swap(dirty_rect.x1, dirty_rect.x2); + } + + if(dirty_rect.y1 > dirty_rect.y2) + { + std::swap(dirty_rect.y1, dirty_rect.y2); + } + + return dirty_rect; +} + +PixelBufferAlpha::PixelBufferAlpha(std::size_t width, std::size_t height) +{ + realloc(width, height); +} + +PixelBufferAlpha::~PixelBufferAlpha() +{ +} + +void PixelBufferAlpha::realloc(std::size_t width, std::size_t height) +{ + buf_data.resize(width * height * 4); + buf = buf_data.data(); + this->width = width; + this->height = height; + clear(); +} + +void PixelBufferAlpha::clear() +{ + std::memset(buf, 0, width * height * 4); +} + +void PixelBufferAlpha::setPixel(std::size_t x, std::size_t y, const Colour& c) +{ + std::uint8_t* pixel = buf + (x + y * width) * 4; + std::memcpy(pixel, c.data(), 4); +} + +void PixelBufferAlpha::writeLine(std::size_t x, std::size_t y, + const std::uint8_t* line, std::size_t len) +{ + if(x >= width || y >= height) + { + return; + } + + if(x + len > width) + { + len = width - x; + } + + auto offset = buf + (x + y * width) * 4; + + std::memcpy(offset, line, len * 4); +} + + +// SIMD: https://github.com/WojciechMula/toys/blob/master/blend_32bpp/blend_32bpp.c +// Alpha blending: http://en.wikipedia.org/wiki/Alpha_compositing + +void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, + const std::uint8_t* line, std::size_t len) +{ + if(x >= width || y >= height) + { + return; + } + + if(x + len > width) + { + len = width - x; + } + + int a, b; + std::uint8_t* target = buf + (x + y * width) * 4; + while(len) + { + if(line[3] == 0xff) + { + const std::uint8_t* end = line; + while(end[3] == 0xff && end < line + len * 4) + { + end += 4; + } + auto chunk_len = end - line; + std::memcpy(target, line, chunk_len); + line += chunk_len; + target += chunk_len; + len -= chunk_len / 4; + continue; + } + else if(line[3] == 0) + { + // Do nothing + } + else + { + a = line[3]; + b = target[3] * (255 - a) / 255; + + target[0] = (line[0] * a + target[0] * b) / (a + b); + target[1] = (line[1] * a + target[1] * b) / (a + b); + target[2] = (line[2] * a + target[2] * b) / (a + b); + target[3] = (int)target[3] + line[3] * (255 - target[3]) / 255; + } + + line += 4; + target += 4; + --len; + } +} + +void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) +{ + if(x >= width || y >= height) + { + return; // out of bounds + } + + const std::uint8_t* colour = c.data(); + + if(colour[3] == 0) + { + return; + } + + int a, b; + std::uint8_t* target = buf + (x + y * width) * 4; + + if(colour[3] == 0xff) + { + std::memcpy(target, colour, 4); + } + else + { + a = colour[3]; + b = target[3] * (255 - a) / 255; + + target[0] = (colour[0] * a + target[0] * b) / (a + b); + target[1] = (colour[1] * a + target[1] * b) / (a + b); + target[2] = (colour[2] * a + target[2] * b) / (a + b); + target[3] = (int)target[3] + colour[3] * (255 - target[3]) / 255; + } +} + +const Colour& PixelBufferAlpha::pixel(std::size_t x, std::size_t y) const +{ + static Colour c; + std::memcpy(c.data(), buf + (x + y * width) * 4, 4); + return c; +} + +const std::uint8_t* PixelBufferAlpha::getLine(std::size_t x, std::size_t y) const +{ + return buf + (x + y * width) * 4; +} + +} // GUI:: diff --git a/dggui/pixelbuffer.h b/dggui/pixelbuffer.h new file mode 100644 index 0000000..5c11d14 --- /dev/null +++ b/dggui/pixelbuffer.h @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * pixelbuffer.h + * + * Thu Nov 10 09:00:37 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "colour.h" + +#include +#include +#include + +#include "guievent.h" + +namespace GUI +{ + +class PixelBuffer +{ +public: + PixelBuffer(std::size_t width, std::size_t height); + ~PixelBuffer(); + + void realloc(std::size_t width, std::size_t height); + + void blendLine(std::size_t x, std::size_t y, + const std::uint8_t* line, std::size_t len); + + Rect updateBuffer(std::vector& pixel_buffers); + + std::vector buf_data; + std::uint8_t* buf{nullptr}; + std::size_t width{0}; + std::size_t height{0}; +}; + +class PixelBufferAlpha +{ +public: + PixelBufferAlpha() = default; + PixelBufferAlpha(std::size_t width, std::size_t height); + ~PixelBufferAlpha(); + + void realloc(std::size_t width, std::size_t height); + + void clear(); + + void setPixel(std::size_t x, std::size_t y, const Colour& c); + + void writeLine(std::size_t x, std::size_t y, + const std::uint8_t* line, std::size_t len); + void blendLine(std::size_t x, std::size_t y, + const std::uint8_t* line, std::size_t len); + + void addPixel(std::size_t x, std::size_t y, const Colour& c); + + const Colour& pixel(std::size_t x, std::size_t y) const; + + const std::uint8_t* getLine(std::size_t x, std::size_t y) const; + + std::vector buf_data; + std::uint8_t* buf{nullptr}; + std::size_t width{0}; + std::size_t height{0}; + int x{0}; + int y{0}; + bool dirty{true}; + bool visible{true}; + + // Add optional dirty rect that this pixelbuffer took up since it was last + // rendered. Make sure to update this list on resize and/or move. + std::size_t last_width{0}; + std::size_t last_height{0}; + int last_x{0}; + int last_y{0}; + bool has_last{false}; +}; + +} // GUI:: diff --git a/dggui/powerbutton.cc b/dggui/powerbutton.cc new file mode 100644 index 0000000..5bf2a2c --- /dev/null +++ b/dggui/powerbutton.cc @@ -0,0 +1,88 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * powerbutton.cc + * + * Thu Mar 23 12:30:50 CET 2017 + * Copyright 2017 AndrĂ© Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "powerbutton.h" + +#include "painter.h" + +namespace GUI +{ + +PowerButton::PowerButton(Widget* parent) : Toggle(parent) +{ +} + +void PowerButton::setEnabled(bool enabled) +{ + this->enabled = enabled; + + redraw(); +} + +void PowerButton::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + // disabled + if(!enabled) + { + if(clicked) + { + p.drawImage(0, 0, disabled_clicked); + } + else + { + p.drawImage(0, 0, disabled); + } + return; + } + + // enabled and on + if(state) + { + if(clicked) + { + p.drawImage(0, 0, on_clicked); + } + else + { + p.drawImage(0, 0, on); + } + return; + } + + // enabled and off + if(clicked) + { + p.drawImage(0, 0, off_clicked); + } + else + { + p.drawImage(0, 0, off); + } +} + +} // GUI:: diff --git a/dggui/powerbutton.h b/dggui/powerbutton.h new file mode 100644 index 0000000..14dbeca --- /dev/null +++ b/dggui/powerbutton.h @@ -0,0 +1,58 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * powerbutton.h + * + * Thu Mar 23 12:30:50 CET 2017 + * Copyright 2017 AndrĂ© Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "texture.h" +#include "toggle.h" + +namespace GUI +{ + +class PowerButton : public Toggle +{ +public: + PowerButton(Widget* parent); + virtual ~PowerButton() = default; + + void setEnabled(bool enabled); + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + + bool enabled = true; + +private: + Texture on{getImageCache(), ":resources/bypass_button.png", 32, 0, 16, 16}; + Texture on_clicked{getImageCache(), ":resources/bypass_button.png", 48, 0, 16, 16}; + Texture off{getImageCache(), ":resources/bypass_button.png", 0, 0, 16, 16}; + Texture off_clicked{getImageCache(), ":resources/bypass_button.png", 16, 0, 16, 16}; + Texture disabled{getImageCache(), ":resources/bypass_button.png", 64, 0, 16, 16}; + Texture disabled_clicked{getImageCache(), ":resources/bypass_button.png", 80, 0, 16, 16}; +}; + +} // GUI:: diff --git a/dggui/progressbar.cc b/dggui/progressbar.cc new file mode 100644 index 0000000..dd3e130 --- /dev/null +++ b/dggui/progressbar.cc @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * progressbar.cc + * + * Fri Mar 22 22:07:57 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "progressbar.h" + +namespace GUI +{ + +ProgressBar::ProgressBar(Widget *parent) + : Widget(parent) +{ +} + +ProgressBar::~ProgressBar() +{ +} + +void ProgressBar::setState(ProgressBarState state) +{ + if(this->state != state) + { + this->state = state; + redraw(); + } +} + +void ProgressBar::setTotal(std::size_t total) +{ + if(this->total != total) + { + this->total = total; + redraw(); + } +} + +void ProgressBar::setValue(std::size_t value) +{ + if(this->value != value) + { + this->value = value; + redraw(); + } +} + +void ProgressBar::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + float progress = 0.0f; + if(total != 0) + { + progress = (float)value / (float)total; + } + + int brd = 4; + int val = (width() - (2 * brd)) * progress; + + bar_bg.setSize(width(), height()); + p.drawImage(0, 0, bar_bg); + + switch(state) + { + case ProgressBarState::Red: + bar_red.setSize(val, height()); + p.drawImage(brd, 0, bar_red); + break; + case ProgressBarState::Green: + bar_green.setSize(val, height()); + p.drawImage(brd, 0, bar_green); + break; + case ProgressBarState::Blue: + bar_blue.setSize(val, height()); + p.drawImage(brd, 0, bar_blue); + break; + case ProgressBarState::Off: + return; + } + +} + +} // GUI:: diff --git a/dggui/progressbar.h b/dggui/progressbar.h new file mode 100644 index 0000000..76cc6fd --- /dev/null +++ b/dggui/progressbar.h @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * progressbar.h + * + * Fri Mar 22 22:07:57 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "widget.h" + +#include "guievent.h" +#include "painter.h" +#include "texturedbox.h" + +namespace GUI +{ + +enum class ProgressBarState +{ + Red, + Green, + Blue, + Off +}; + +class ProgressBar + : public Widget +{ +public: + ProgressBar(Widget* parent); + virtual ~ProgressBar(); + + void setTotal(std::size_t total); + void setValue(std::size_t value); + + void setState(ProgressBarState state); + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + ProgressBarState state{ProgressBarState::Blue}; + + TexturedBox bar_bg{getImageCache(), ":resources/progress.png", + 0, 0, // atlas offset (x, y) + 6, 1, 6, // dx1, dx2, dx3 + 11, 0, 0}; // dy1, dy2, dy3 + + TexturedBox bar_red{getImageCache(), ":resources/progress.png", + 13, 0, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 11, 0, 0}; // dy1, dy2, dy3 + + TexturedBox bar_green{getImageCache(), ":resources/progress.png", + 18, 0, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 11, 0, 0}; // dy1, dy2, dy3 + + TexturedBox bar_blue{getImageCache(), ":resources/progress.png", + 23, 0, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 11, 0, 0}; // dy1, dy2, dy3 + + std::size_t total{0}; + std::size_t value{0}; +}; + +} // GUI:: diff --git a/dggui/rc_data.cc b/dggui/rc_data.cc new file mode 100644 index 0000000..18e3cd5 --- /dev/null +++ b/dggui/rc_data.cc @@ -0,0 +1,29 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * rc_data.cc + * + * Wed Dec 23 09:51:20 CET 2020 + * Copyright 2020 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "resource_data.h" + +const rc_data_t* rc_data __attribute__((__weak__)) = nullptr; diff --git a/dggui/rcgentool.cc b/dggui/rcgentool.cc new file mode 100644 index 0000000..c0ba0db --- /dev/null +++ b/dggui/rcgentool.cc @@ -0,0 +1,192 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * rcgen.cc + * + * Sun Mar 17 20:27:17 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include +#include +#include +#include + +#include + +std::string usage(const std::string& name, bool brief = false) +{ + std::ostringstream output; + output << + "Usage: " << name << " [options]\n"; + if(!brief) + { + output << + "\n" + "Create resource file from list of input files.\n" + "\n"; + } + return output.str(); +} + +int main(int argc, char *argv[]) +{ + bool verbose{false}; + std::vector stripPrefixes; + std::string dirRoot; + std::string outfile; + + dg::Options opt; + + opt.add("strip-path", required_argument, 's', + "Strip supplied path prefix from resource names.", + [&]() + { + stripPrefixes.push_back(optarg); + return 0; + }); + + opt.add("dir-root", required_argument, 'd', + "Change to supplied root dir before reading files.", + [&]() + { + dirRoot = optarg; + return 0; + }); + + opt.add("output", required_argument, 'o', + "Write output to specificed file, defaults to stdout.", + [&]() + { + outfile = optarg; + return 0; + }); + + opt.add("verbose", no_argument, 'v', + "Print verbose output during processing.", + [&]() + { + verbose = true; + return 0; + }); + + opt.add("help", no_argument, 'h', + "Print this message and exit.", + [&]() + { + std::cout << usage(argv[0]); + std::cout << "Options:\n"; + opt.help(); + exit(0); + return 0; + }); + + if(opt.process(argc, argv) != 0) + { + return 1; + } + + FILE* out = stdout; + if(!outfile.empty()) + { + out = fopen(outfile.data(), "wb"); + if(!out) + { + fprintf(stderr, "Could not write to file '%s' - quitting\n", + outfile.data()); + return 1; + + } + } + + fprintf(out, "/* This file is autogenerated by rcgen. Do not modify! */\n"); + fprintf(out, "#include \n"); + fprintf(out, "\n"); + fprintf(out, "const rc_data_t rc_dataX[] =\n"); + fprintf(out, "{\n"); + + if(!dirRoot.empty()) + { + if(verbose) + { + fprintf(stderr, "Change to dir: %s\n", dirRoot.data()); + } + + if(chdir(dirRoot.data())) + { + return 1; + } + } + + for(const auto& arg : opt.arguments()) + { + std::string resourceName = arg; + for(const auto& stripPrefix : stripPrefixes) + { + if(stripPrefix == resourceName.substr(0, stripPrefix.length())) + { + resourceName = resourceName.substr(stripPrefix.length()); + break; + } + } + + fprintf(out, " {\n \":%s\", ", resourceName.data()); + + if(verbose) + { + fprintf(stderr, "Process: %s\n", arg.data()); + } + + std::string data; + FILE *fp = fopen(arg.data(), "rb"); + if(!fp) + { + fprintf(stderr, "Could not read file '%s' - quitting\n", arg.data()); + return 1; + } + + char buf[32]; + while(!feof(fp)) + { + std::size_t sz = fread(buf, 1, sizeof(buf), fp); + data.append(buf, sz); + } + fclose(fp); + + fprintf(out, "%d,\n \"", (int)data.length()); + for(std::size_t j = 0; j < data.length(); ++j) + { + if((j != 0) && (j % 16) == 0) + { + fprintf(out, "\"\n \""); + } + fprintf(out, "\\%o", (unsigned char)data[j]); + } + + fprintf(out, "\"\n },\n"); + } + + fprintf(out, " { \"\", 0, 0 }\n"); + fprintf(out, "};\n"); + + fprintf(out, "\nconst rc_data_t* rc_data = rc_dataX;\n"); + + return 0; +} diff --git a/dggui/resource.cc b/dggui/resource.cc new file mode 100644 index 0000000..52aca0a --- /dev/null +++ b/dggui/resource.cc @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * resource.cc + * + * Sun Mar 17 19:38:04 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "resource.h" + +#include +#include +#include + +#include + +#if DG_PLATFORM != DG_PLATFORM_WINDOWS +#include +#include +#include +#endif + +// rcgen generated file containing rc_data declaration. +#include "resource_data.h" + +extern const rc_data_t* rc_data; + +namespace GUI +{ + +// TODO: Replace with std::filesystem::is_regular_file once we update the +// compiler to require C++17 +static bool pathIsFile(const std::string& path) +{ +#if DG_PLATFORM == DG_PLATFORM_WINDOWS + return (GetFileAttributesA(path.data()) & FILE_ATTRIBUTE_DIRECTORY) == 0; +#else + struct stat s; + if(stat(path.data(), &s) != 0) + { + return false; // error + } + + return (s.st_mode & S_IFREG) != 0; // s.st_mode & S_IFDIR => dir +#endif +} + +// Internal resources start with a colon. +static bool nameIsInternal(const std::string& name) +{ + return name.size() && (name[0] == ':'); +} + +Resource::Resource(const std::string& name) +{ + isValid = false; + + if(nameIsInternal(name)) + { + // Use internal resource: + + // Find internal resource in rc_data. + const rc_data_t* p = rc_data; + while(p && *p->name) // last entry in rc_data has the name := "" + { + if(name == p->name) + { + internalData = p->data; + internalSize = p->size; + break; + } + ++p; + } + + // We did not find the named resource. + if(internalData == nullptr) + { + ERR(rc, "Could not find '%s'\n", name.c_str()); + return; + } + + isInternal = true; + } + else + { + if(!pathIsFile(name)) + { + return; + } + + // Read from file: + std::FILE *fp = std::fopen(name.data(), "rb"); + if(!fp) + { + return; + } + + // Get the file size + if(std::fseek(fp, 0, SEEK_END) == -1) + { + std::fclose(fp); + return; + } + + long filesize = std::ftell(fp); + + // Apparently fseek doesn't fail if fp points to a directory that has been + // opened (which doesn't fail either!!) and ftell will then fail by either + // returning -1 or LONG_MAX + if(filesize == -1L || filesize == LONG_MAX) + { + std::fclose(fp); + return; + } + + // Reserve space in the string for the data. + externalData.reserve(filesize); + + // Rewind and read... + std::rewind(fp); + + char buffer[32]; + while(!std::feof(fp)) + { + size_t size = std::fread(buffer, 1, sizeof(buffer), fp); + externalData.append(buffer, size); + } + + std::fclose(fp); + + isInternal = false; + } + + isValid = true; +} + +const char *Resource::data() +{ + if(isValid == false) + { + return nullptr; + } + + if(isInternal) + { + return internalData; + } + else + { + return externalData.data(); + } +} + +size_t Resource::size() +{ + if(isValid == false) + { + return 0; + } + + if(isInternal) + { + return internalSize; + } + else + { + return externalData.length(); + } +} + +bool Resource::valid() +{ + return isValid; +} + +} // GUI:: diff --git a/dggui/resource.h b/dggui/resource.h new file mode 100644 index 0000000..5f7b3b4 --- /dev/null +++ b/dggui/resource.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * resource.h + * + * Sun Mar 17 19:38:03 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +namespace GUI { + +class Resource { +public: + Resource(const std::string& name); + + const char* data(); + size_t size(); + + bool valid(); + +protected: + std::string externalData; + bool isValid{false}; + bool isInternal{false}; + const char *internalData{nullptr}; + size_t internalSize{0}; +}; + +} // GUI:: diff --git a/dggui/resource_data.h b/dggui/resource_data.h new file mode 100644 index 0000000..d685e13 --- /dev/null +++ b/dggui/resource_data.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * resource_data.h + * + * Sun Mar 17 20:25:24 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +typedef struct { + const char *name; + unsigned int size; + const char *data; +} rc_data_t; diff --git a/dggui/scrollbar.cc b/dggui/scrollbar.cc new file mode 100644 index 0000000..9a17d1d --- /dev/null +++ b/dggui/scrollbar.cc @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * scrollbar.cc + * + * Sun Apr 14 12:54:58 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "scrollbar.h" + +#include + +#include "painter.h" + +namespace GUI { + +ScrollBar::ScrollBar(Widget *parent) + : Widget(parent) +{ +} + +void ScrollBar::setRange(int r) +{ + rangeValue = r; + setValue(value()); + redraw(); +} + +int ScrollBar::range() +{ + return rangeValue; +} + +void ScrollBar::setMaximum(int m) +{ + maxValue = m; + if(maxValue < rangeValue) + { + rangeValue = maxValue; + } + setValue(value()); + redraw(); +} + +int ScrollBar::maximum() +{ + return maxValue; +} + +void ScrollBar::addValue(int delta) +{ + setValue(value() + delta); +} + +void ScrollBar::setValue(int value) +{ + if(value > (maxValue - rangeValue)) + { + value = maxValue - rangeValue; + } + + if(value < 0) + { + value = 0; + } + + if(currentValue == value) + { + return; + } + + currentValue = value; + + valueChangeNotifier(value); + + redraw(); +} + +int ScrollBar::value() +{ + return currentValue; +} + +//! Draw an up/down arrow at (x,y) with the bounding box size (w,h) +//! If h is negative the arrow will point down, if positive it will point up. +static void drawArrow(Painter &p, int x, int y, int w, int h) +{ + if(h < 0) + { + y -= h; + } + + p.drawLine(x, y, x + (w / 2), y + h); + p.drawLine(x + (w / 2), y + h, x + w, y); + + ++y; + p.drawLine(x, y, x + (w / 2), y + h); + p.drawLine(x + (w / 2), y + h, x + w, y); +} + +void ScrollBar::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + p.clear(); + + p.drawImageStretched(0, 0, bg_img, width(), height()); + + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); + if(!maxValue) + { + return; + } + + { + int h = height() - 2 * width() - 3; + int offset = width() + 2; + + int y_val1 = (currentValue * h) / maxValue; + int y_val2 = ((currentValue + rangeValue) * h) / maxValue - 1; + + p.drawFilledRectangle(2, y_val1 + offset, width() - 1, y_val2 + offset); + } + + p.drawLine(0, 0, 0, height()); + + drawArrow(p, width()/4, width()/4, width()/2, -1 * (width()/3)); + p.drawLine(0, width(), width(), width()); + + drawArrow(p, width()/4, height() - width() + width()/4, width()/2, width()/3); + p.drawLine(0, height() - width(), width(), height() - width()); +} + +void ScrollBar::scrollEvent(ScrollEvent* scrollEvent) +{ + setValue(value() + scrollEvent->delta); +} + +void ScrollBar::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) +{ + if(!dragging) + { + return; + } + + float delta = yOffset - mouseMoveEvent->y; + + int h = height() - 2 * width() - 3; + delta /= (float)h / (float)maxValue; + + int newval = valueOffset - delta; + if(newval != value()) + { + setValue(newval); + } +} + +void ScrollBar::buttonEvent(ButtonEvent* buttonEvent) +{ + // Ignore everything except left clicks. + if(buttonEvent->button != MouseButton::left) + { + return; + } + + if((buttonEvent->y < (int)width()) && buttonEvent->y > 0) + { + if(buttonEvent->direction == Direction::down) + { + addValue(-1); + } + + return; + } + + if((buttonEvent->y > ((int)height() - (int)width())) && + (buttonEvent->y < (int)height())) + { + if(buttonEvent->direction == Direction::down) + { + addValue(1); + } + + return; + } + + if(buttonEvent->direction == Direction::down) + { + yOffset = buttonEvent->y; + valueOffset = value(); + } + + dragging = (buttonEvent->direction == Direction::down); +} + +} // GUI:: diff --git a/dggui/scrollbar.h b/dggui/scrollbar.h new file mode 100644 index 0000000..5e60673 --- /dev/null +++ b/dggui/scrollbar.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * scrollbar.h + * + * Sun Apr 14 12:54:58 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "widget.h" +#include "texture.h" +#include "notifier.h" + +namespace GUI { + +class ScrollBar : public Widget { + friend class ListBoxBasic; +public: + ScrollBar(Widget *parent); + + void setRange(int range); + int range(); + + void setMaximum(int max); + int maximum(); + + void addValue(int delta); + void setValue(int value); + int value(); + + Notifier valueChangeNotifier; // (int value) + +protected: + // From Widget: + bool catchMouse() override { return true; } + void scrollEvent(ScrollEvent* scrollEvent) override; + void repaintEvent(RepaintEvent* repaintEvent) override; + void buttonEvent(ButtonEvent* buttonEvent) override; + void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; + +private: + int maxValue{100}; + int currentValue{0}; + int rangeValue{10}; + + int yOffset{0}; + int valueOffset{0}; + bool dragging{false}; + + Texture bg_img{getImageCache(), ":resources/widget.png", 7, 7, 1, 63}; +}; + +} // GUI:: diff --git a/dggui/slider.cc b/dggui/slider.cc new file mode 100644 index 0000000..15a82b3 --- /dev/null +++ b/dggui/slider.cc @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * slider.cc + * + * Sat Nov 26 18:10:22 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "slider.h" + +#include "painter.h" + +#include +#include + +namespace GUI +{ + +Slider::Slider(Widget* parent) : Widget(parent) +{ + state = State::up; + + current_value = 0.0; + maximum = 1.0; + minimum = 0.0; +} + +void Slider::setValue(float new_value) +{ + current_value = new_value; + if (current_value < 0.) + { + current_value = 0.; + } + else if (current_value > 1.0) { + current_value = 1.0; + } + + redraw(); + clickNotifier(); + valueChangedNotifier(current_value); +} + +float Slider::value() const +{ + return current_value; +} + +void Slider::setColour(Colour colour) +{ + switch (colour) { + case Colour::Green: + active_inner_bar = &inner_bar_green; + break; + case Colour::Red: + active_inner_bar = &inner_bar_red; + break; + case Colour::Blue: + active_inner_bar = &inner_bar_blue; + break; + case Colour::Yellow: + active_inner_bar = &inner_bar_yellow; + break; + case Colour::Purple: + active_inner_bar = &inner_bar_purple; + break; + case Colour::Grey: + active_inner_bar = &inner_bar_grey; + break; + } + + if (enabled) { inner_bar = active_inner_bar; } +} + +void Slider::setEnabled(bool enabled) +{ + this->enabled = enabled; + + if (enabled) { + inner_bar = active_inner_bar; + } + else { + active_inner_bar = inner_bar; + inner_bar = &inner_bar_light_grey; + } + + redraw(); +} + +void Slider::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + auto inner_offset = (current_value / maximum) * getControlWidth(); + auto button_x = button_offset + inner_offset - (button.width() / 2); + auto button_y = (height() - button.height()) / 2; + + // draw bar + bar.setSize(width(), height()); + p.drawImage(0, 0, bar); + + // draw inner bar + inner_bar->setSize(button_x - bar_boundary, height() - 2 * bar_boundary); + p.drawImage(bar_boundary, bar_boundary, *inner_bar); + + // draw button + p.drawImage(button_x, button_y, button); +} + +void Slider::buttonEvent(ButtonEvent* buttonEvent) +{ + // Ignore everything except left clicks. + if(!enabled || buttonEvent->button != MouseButton::left) + { + return; + } + + if(buttonEvent->direction == Direction::down) + { + state = State::down; + recomputeCurrentValue(buttonEvent->x); + + redraw(); + clickNotifier(); + valueChangedNotifier(current_value); + } + + if(buttonEvent->direction == Direction::up) + { + state = State::up; + recomputeCurrentValue(buttonEvent->x); + + redraw(); + clickNotifier(); + valueChangedNotifier(current_value); + } +} + +void Slider::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) +{ + if(state == State::down) + { + recomputeCurrentValue(mouseMoveEvent->x); + + redraw(); + clickNotifier(); + valueChangedNotifier(current_value); + } +} + +void Slider::scrollEvent(ScrollEvent* scrollEvent) +{ + if (!enabled) { return; } + + current_value -= scrollEvent->delta/(float)getControlWidth(); + if (current_value < 0.) + { + current_value = 0.; + } + else if (current_value > 1.0) { + current_value = 1.0; + } + + redraw(); + clickNotifier(); + valueChangedNotifier(current_value); +} + +std::size_t Slider::getControlWidth() const +{ + if(width() < 2 * button_offset) + { + return 0; + } + + return width() - 2 * button_offset; +} + +void Slider::recomputeCurrentValue(float x) +{ + if(x < button_offset) + { + current_value = 0; + } + else + { + current_value = (x - button_offset) / getControlWidth(); + } + + if (current_value < 0.) + { + current_value = 0.; + } + else if (current_value > 1.0) { + current_value = 1.0; + } +} + +} // GUI:: diff --git a/dggui/slider.h b/dggui/slider.h new file mode 100644 index 0000000..90905fd --- /dev/null +++ b/dggui/slider.h @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * slider.h + * + * Sat Nov 26 18:10:22 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "texture.h" +#include "texturedbox.h" +#include "widget.h" + +namespace GUI +{ + +class Slider + : public Widget +{ +public: + Slider(Widget* parent); + virtual ~Slider() = default; + + // From Widget: + bool catchMouse() override + { + return true; + } + bool isFocusable() override + { + return true; + } + + void setValue(float new_value); + float value() const; + + enum class Colour { Green, Red, Blue, Yellow, Purple, Grey }; + // Changes the colour of the inner bar + void setColour(Colour colour); + void setEnabled(bool enabled); + + Notifier<> clickNotifier; + Notifier valueChangedNotifier; // (float value) + +protected: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; + virtual void scrollEvent(ScrollEvent* scrollEvent) override; + + bool enabled = true;; + +private: + enum class State + { + up, + down + }; + + float current_value; + float maximum; + float minimum; + + State state; + + TexturedBox bar{getImageCache(), ":resources/slider.png", + 0, 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 7, 1, 7 // dy1, dy2, dy3 + }; + Texture button{ + getImageCache(), ":resources/slider.png", 15, 0, // atlas offset (x, y) + 15, 15 // width, height + }; + + TexturedBox inner_bar_green{getImageCache(), ":resources/slider.png", + 30, 0, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_red{getImageCache(), ":resources/slider.png", + 30, 5, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_blue{getImageCache(), ":resources/slider.png", + 30, 10, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_yellow{getImageCache(), ":resources/slider.png", + 35, 0, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_purple{getImageCache(), ":resources/slider.png", + 35, 5, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_grey{getImageCache(), ":resources/slider.png", + 35, 10, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_turquoise{getImageCache(), ":resources/slider.png", + 40, 0, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_orange{getImageCache(), ":resources/slider.png", + 40, 5, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + TexturedBox inner_bar_light_grey{getImageCache(), ":resources/slider.png", + 40, 10, // atlas offset (x, y) + 2, 1, 2, // dx1, dx2, dx3 + 2, 1, 2 // dy1, dy2, dy3 + }; + + // This points to the inner_bar_* of the current color. + // It should never be a nullptr! + TexturedBox* inner_bar{&inner_bar_blue}; + TexturedBox* active_inner_bar = inner_bar; + + std::size_t bar_boundary{5}; + std::size_t button_offset{7}; + + std::size_t getControlWidth() const; + void recomputeCurrentValue(float x); +}; + +} // GUI:: diff --git a/dggui/stackedwidget.cc b/dggui/stackedwidget.cc new file mode 100644 index 0000000..05f8f3c --- /dev/null +++ b/dggui/stackedwidget.cc @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * stackedwidget.cc + * + * Mon Nov 21 19:36:49 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "stackedwidget.h" + +namespace GUI +{ + +StackedWidget::StackedWidget(Widget *parent) + : Widget(parent) +{ + CONNECT(this, sizeChangeNotifier, this, &StackedWidget::sizeChanged); +} + +StackedWidget::~StackedWidget() +{ +} + +void StackedWidget::addWidget(Widget *widget) +{ + widgets.push_back(widget); + widget->reparent(this); + + if(currentWidget == nullptr) + { + setCurrentWidget(widget); + } + else + { + widget->setVisible(false); + } +} + +void StackedWidget::removeWidget(Widget *widget) +{ + if(widget == currentWidget) + { + setCurrentWidget(nullptr); + } + + widgets.remove(widget); +} + +Widget *StackedWidget::getCurrentWidget() const +{ + return currentWidget; +} + +void StackedWidget::setCurrentWidget(Widget *widget) +{ + if(widget == currentWidget) + { + return; + } + + if(currentWidget) + { + currentWidget->setVisible(false); + } + + currentWidget = widget; + + if(currentWidget) + { + currentWidget->move(0, 0); + currentWidget->resize(width(), height()); + currentWidget->setVisible(true); + } + + currentChanged(currentWidget); +} + +Widget* StackedWidget::getWidgetAfter(Widget* widget) +{ + bool found_it{false}; + + for(auto w : widgets) + { + if(found_it) + { + return w; + } + + if(w == widget) + { + found_it = true; + } + } + + if(found_it) + { + // widget was the last in the list. + return nullptr; + } + + // The Widget pointed to by 'widget' was not in the list... + return nullptr; +} + +Widget* StackedWidget::getWidgetBefore(Widget* widget) +{ + Widget* last{nullptr}; + + for(auto w : widgets) + { + if(w == widget) + { + return last; + } + + last = w; + } + + // The Widget pointed to by 'widget' was not in the list... + return nullptr; +} + +void StackedWidget::sizeChanged(int width, int height) +{ + // Propagate size change to child: + if(currentWidget) + { + currentWidget->move(0, 0); + currentWidget->resize(width, height); + } +} + +} // GUI:: diff --git a/dggui/stackedwidget.h b/dggui/stackedwidget.h new file mode 100644 index 0000000..24213f7 --- /dev/null +++ b/dggui/stackedwidget.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * stackedwidget.h + * + * Mon Nov 21 19:36:49 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "widget.h" +#include "notifier.h" + +namespace GUI +{ + +//! A StackedWidget is a widget containing a list of widgets but only showing +//! one of them at a time. +//! It is be used to implement a TabWidget but can also be used for other +//! purposes. +class StackedWidget + : public Widget +{ +public: + StackedWidget(Widget* parent); + ~StackedWidget(); + + //! Add a widget to the stack. + void addWidget(Widget* widget); + + //! Remove a widget from the stack. + void removeWidget(Widget* widget); + + //! Get currently visible widget. + Widget* getCurrentWidget() const; + + //! Show widget. Hide all the others. + //! If widget is not in the stack nothing happens. + void setCurrentWidget(Widget* widget); + + //! Returns a pointer to the Widget after the one referenced by 'widget' or + //! nullptr if 'widget' is the last in the list. + Widget* getWidgetAfter(Widget* widget); + + //! Returns a pointer to the Widget beforer the one referenced by 'widget' or + //! nullptr if 'widget' is the first in the list. + Widget* getWidgetBefore(Widget* widget); + + //! Reports whn a new widget is shown. + Notifier currentChanged; + +private: + //! Callback for Widget::sizeChangeNotifier + void sizeChanged(int width, int height); + +private: + Widget* currentWidget{nullptr}; + std::list widgets; +}; + +} // GUI:: diff --git a/dggui/tabbutton.cc b/dggui/tabbutton.cc new file mode 100644 index 0000000..6a27f61 --- /dev/null +++ b/dggui/tabbutton.cc @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tabbutton.cc + * + * Thu Nov 24 18:52:26 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "tabbutton.h" + +#include "painter.h" + +namespace GUI +{ + +static TabID getNextTabID() +{ + static TabID next{0}; + next++; + return next; +} + +TabButton::TabButton(Widget* parent, Widget* tab_widget) + : ButtonBase(parent) + , tab_widget(tab_widget) +{ + tab_id = getNextTabID(); + CONNECT(this, clickNotifier, this, &TabButton::clickHandler); +} + +TabButton::~TabButton() +{ +} + +Widget* TabButton::getTabWidget() +{ + return tab_widget; +} + +std::size_t TabButton::getMinimalWidth() const +{ + std::size_t padding = 15; + auto font_width = font.textWidth(text); + + return font_width + padding; +} + +std::size_t TabButton::getMinimalHeight() const +{ + std::size_t padding = 10; + auto font_height= font.textHeight(text); + + return font_height + padding; +} + +void TabButton::setActive(bool active) +{ + this->active = active; + + if (active) { + draw_state = State::Down; + } + else { + draw_state = State::Up; + } + + redraw(); +} + +TabID TabButton::getID() const +{ + return tab_id; +} + +void TabButton::repaintEvent(RepaintEvent* e) +{ + Painter p(*this); + + int padTop = 3; + int padLeft = 0; + int padTextTop = 3; + + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } + + if (draw_state == State::Up && !active) { + tab_passive.setSize(w - padLeft, h - padTop); + p.drawImage(padLeft, padTop, tab_passive); + } + else { + tab_active.setSize(w - padLeft, h - padTop); + p.drawImage(padLeft, padTop, tab_active); + } + + auto x = padLeft + (width() - font.textWidth(text)) / 2; + auto y = padTop + padTextTop + font.textHeight(text); + p.drawText(x, y, font, text, true); +} + +void TabButton::scrollEvent(ScrollEvent* scroll_event) +{ + scrollNotifier(scroll_event->delta); +} + +void TabButton::clickHandler() +{ + switchTabNotifier(tab_widget); +} + +} // GUI:: diff --git a/dggui/tabbutton.h b/dggui/tabbutton.h new file mode 100644 index 0000000..1e9371a --- /dev/null +++ b/dggui/tabbutton.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tabbutton.h + * + * Thu Nov 24 18:52:26 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include "button_base.h" +#include "font.h" +#include "texturedbox.h" + +namespace GUI +{ + +class ScrollEvent; + +using TabID = int; + +class TabButton + : public ButtonBase +{ +public: + TabButton(Widget* parent, Widget* tab_widget); + virtual ~TabButton(); + + Widget* getTabWidget(); + std::size_t getMinimalWidth() const; + std::size_t getMinimalHeight() const; + void setActive(bool active); + + TabID getID() const; + + Notifier switchTabNotifier; + Notifier scrollNotifier; // float delta + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* e) override; + virtual void scrollEvent(ScrollEvent* scroll_event) override; + +private: + TabID tab_id; + + void clickHandler(); + + Widget* tab_widget; + bool active{false}; + + TexturedBox tab_active{getImageCache(), ":resources/tab.png", + 0, 0, // atlas offset (x, y) + 5, 1, 5, // dx1, dx2, dx3 + 5, 13, 1}; // dy1, dy2, dy3 + + TexturedBox tab_passive{getImageCache(), ":resources/tab.png", + 11, 0, // atlas offset (x, y) + 5, 1, 5, // dx1, dx2, dx3 + 5, 13, 1}; // dy1, dy2, dy3 + + Font font{":resources/fontemboss.png"}; +}; + +} // GUI:: diff --git a/dggui/tabwidget.cc b/dggui/tabwidget.cc new file mode 100644 index 0000000..635f1bd --- /dev/null +++ b/dggui/tabwidget.cc @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tabwidget.cc + * + * Thu Nov 24 17:46:22 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "tabwidget.h" + +#include "painter.h" + +namespace GUI +{ + +TabWidget::TabWidget(Widget *parent) + : Widget(parent) + , stack(this) +{ + CONNECT(this, sizeChangeNotifier, this, &TabWidget::sizeChanged); + CONNECT(&stack, currentChanged, this, &TabWidget::setActiveButtons); +} + +TabID TabWidget::addTab(const std::string& title, Widget* widget) +{ + buttons.emplace_back(this, widget); + auto& button = buttons.back(); + button.setText(title); + stack.addWidget(widget); + CONNECT(&button, switchTabNotifier, this, &TabWidget::switchTab); + CONNECT(&button, scrollNotifier, this, &TabWidget::rotateTab); + sizeChanged(width(), height()); + return button.getID(); +} + +void TabWidget::setTabWidth(std::size_t width) +{ + tab_width = width; + relayout(); +} + +std::size_t TabWidget::getTabWidth() const +{ + return tab_width; +} + +void TabWidget::setVisible(TabID tab_id, bool visible) +{ + for (auto& button : buttons) + { + if(button.getID() == tab_id) + { + button.setVisible(visible); + relayout(); + return; + } + } +} + +std::size_t TabWidget::getBarHeight() const +{ + return topbar.height(); +} + +void TabWidget::rotateTab(float delta) +{ + Widget* widget{nullptr}; + Widget* current = stack.getCurrentWidget(); + if(delta > 0.0f) + { + while((widget = stack.getWidgetAfter(current)) != nullptr) + { + auto button = getButtonFromWidget(widget); + if(!button || !button->visible()) + { + current = widget; + continue; + } + break; + } + } + else + { + while((widget = stack.getWidgetBefore(current)) != nullptr) + { + auto button = getButtonFromWidget(widget); + if(!button || !button->visible()) + { + current = widget; + continue; + } + break; + } + } + + if(widget) + { + switchTab(widget); + } +} + +void TabWidget::switchTab(Widget* tab_widget) +{ + stack.setCurrentWidget(tab_widget); +} + +void TabWidget::setActiveButtons(Widget* current_widget) +{ + for (auto& button : buttons) { + if (button.getTabWidget() == current_widget) { + button.setActive(true); + } + else + { + button.setActive(false); + } + } +} + +void TabWidget::sizeChanged(int width, int height) +{ + std::size_t pos = 0; + + int button_width = tab_width; + int bar_height = 25; + int button_border_width = 10; + + int button_padding_left = 25; + int button_padding_inner = 3; + int logo_padding_right = button_padding_left / 2; + + Painter p(*this); + + if(buttons.size() > 0) + { + for(auto& button : buttons) + { + if(!button.visible()) + { + continue; + } + int min_width = button.getMinimalWidth(); + button_width = std::max(button_width, min_width + button_border_width); + } + + button_width = std::min(button_width, width / (int)buttons.size()); + } + + // draw the upper bar + topbar.setSize(width, bar_height); + p.drawImage(0, 0, topbar); + auto x_logo = width - toplogo.width() - logo_padding_right; + auto y_logo = (bar_height - toplogo.height()) / 2; + p.drawImage(x_logo, y_logo, toplogo); + + // place the buttons + pos = button_padding_left; + for(auto& button : buttons) + { + if(!button.visible()) + { + continue; + } + button.resize(button_width, bar_height); + button.move(pos, 0); + pos += button_width + button_padding_inner; + } + + stack.move(0, bar_height); + stack.resize(width, std::max((int)height - bar_height, 0)); +} + +void TabWidget::relayout() +{ + sizeChanged(TabWidget::width(), TabWidget::height()); // Force re-layout +} + +const TabButton* TabWidget::getButtonFromWidget(const Widget* tab_widget) +{ + if(tab_widget == nullptr) + { + return nullptr; + } + + for(auto& button : buttons) + { + if(button.getTabWidget() == tab_widget) + { + return &button; + } + } + + return nullptr; +} + +} // GUI:: diff --git a/dggui/tabwidget.h b/dggui/tabwidget.h new file mode 100644 index 0000000..129826a --- /dev/null +++ b/dggui/tabwidget.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tabwidget.h + * + * Thu Nov 24 17:46:22 CET 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "widget.h" +#include "tabbutton.h" +#include "stackedwidget.h" +#include "texture.h" + +namespace GUI +{ + +class TabWidget + : public Widget +{ +public: + TabWidget(Widget *parent); + + //! Add new tab to the tab widget. + //! \param title The title to display on the tab button. + //! \param widget The widget to show in the tab. + //! \returns The TabID of the newly added tab. + TabID addTab(const std::string& title, Widget* widget); + + std::size_t getBarHeight() const; + + void setTabWidth(std::size_t width); + std::size_t getTabWidth() const; + + void setVisible(TabID tab_id, bool visible); + +private: + //! Callback for Widget::sizeChangeNotifier + void sizeChanged(int width, int height); + +private: + void relayout(); + //! Switch to the next tab if delta is > 0 or previous tab if delta is <= 0. + void rotateTab(float delta); + void switchTab(Widget* tabWidget); + void setActiveButtons(Widget* current_widget); + + const TabButton* getButtonFromWidget(const Widget* tab_widget); + + std::list buttons; + StackedWidget stack; + + TexturedBox topbar{getImageCache(), ":resources/topbar.png", + 0, 0, // atlas offset (x, y) + 1, 1, 1, // dx1, dx2, dx3 + 17, 1, 1}; // dy1, dy2, dy3 + + Texture toplogo{getImageCache(), ":resources/toplogo.png", + 0, 0, // atlas offset (x, y) + 95, 17}; // width, height + + std::size_t tab_width{64}; +}; + +} // GUI:: diff --git a/dggui/textedit.cc b/dggui/textedit.cc new file mode 100644 index 0000000..9688b82 --- /dev/null +++ b/dggui/textedit.cc @@ -0,0 +1,201 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * lineedit.cc + * + * Tue Oct 21 11:25:26 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "textedit.h" + +#include "painter.h" + +namespace GUI +{ + +TextEdit::TextEdit(Widget* parent) : Widget(parent), scroll(this) +{ + setReadOnly(true); + + scroll.move(width() - 2*x_border - 3, y_border - 1); + scroll.resize(16, 100); + CONNECT(&scroll, valueChangeNotifier, this, &TextEdit::scrolled); +} + +TextEdit::~TextEdit() +{ +} + +void TextEdit::resize(std::size_t width, std::size_t height) +{ + Widget::resize(width, height); + + needs_preprocessing = true; + scroll.move(width - 2*x_border - 3, y_border - 1); + scroll.resize(scroll.width(), std::max((int)height - 2*(y_border - 1), 0)); +} + +void TextEdit::setReadOnly(bool readonly) +{ + this->readonly = readonly; +} + +bool TextEdit::readOnly() +{ + return readonly; +} + +void TextEdit::setText(const std::string& text) +{ + this->text = text; + + needs_preprocessing = true; + redraw(); + textChangedNotifier(); +} + +std::string TextEdit::getText() +{ + return text; +} + +void TextEdit::preprocessText() +{ + std::vector lines; + + preprocessed_text.clear(); + std::string text = this->text; + + // Handle tab characters + for(std::size_t i = 0; i < text.length(); ++i) + { + char ch = text.at(i); + if(ch == '\t') + { + text.erase(i, 1); + text.insert(i, 4, ' '); + } + } + + // Handle "\r" + for(std::size_t i = 0; i < text.length(); ++i) + { + char ch = text.at(i); + if(ch == '\r') + { + text.erase(i, 1); + } + } + + // Handle new line characters + std::size_t pos = 0; + do + { + pos = text.find("\n"); + lines.push_back(text.substr(0, pos)); + text = text.substr(pos + 1); + } while(pos != std::string::npos); + + // Wrap long lines + auto const max_width = width() - 2*x_border - 10 - scroll.width(); + for(auto const& line: lines) + { + std::string valid; + std::string current; + for(auto c: line) + { + current += c; + if(c == ' ') + { + valid.append(current.substr(valid.size())); + } + + if(font.textWidth(current) >= max_width) + { + if(valid.empty()) + { + current.pop_back(); + preprocessed_text.push_back(current); + current = c; + } + else + { + current = current.substr(valid.size()); + valid.pop_back(); + preprocessed_text.push_back(valid); + valid.clear(); + } + } + } + preprocessed_text.push_back(current); + } +} + +void TextEdit::repaintEvent(RepaintEvent* repaintEvent) +{ + if(needs_preprocessing) + { + preprocessText(); + } + + Painter p(*this); + + // update values of scroll bar + scroll.setRange(height() / font.textHeight()); + scroll.setMaximum(preprocessed_text.size()); + + if((width() == 0) || (height() == 0)) + { + return; + } + + box.setSize(width(), height()); + p.drawImage(0, 0, box); + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); + + int ypos = font.textHeight() + y_border; + + auto scroll_value = scroll.value(); + for(std::size_t i = 0; i < preprocessed_text.size() - scroll_value; ++i) + { + if(i * font.textHeight() >= (height() - y_border - font.textHeight())) + { + break; + } + + auto const& line = preprocessed_text[scroll_value + i]; + p.drawText(x_border, ypos, font, line); + ypos += font.textHeight(); + } +} + +void TextEdit::scrollEvent(ScrollEvent* scrollEvent) +{ + scroll.setValue(scroll.value() + scrollEvent->delta); +} + +void TextEdit::scrolled(int value) +{ + (void)value; + redraw(); +} + +} // GUI:: diff --git a/dggui/textedit.h b/dggui/textedit.h new file mode 100644 index 0000000..17a04ff --- /dev/null +++ b/dggui/textedit.h @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * textedit.h + * + * Tue Oct 21 11:23:58 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include "font.h" +#include "notifier.h" +#include "scrollbar.h" +#include "texturedbox.h" +#include "widget.h" + +namespace GUI +{ + +class TextEdit + : public Widget +{ +public: + TextEdit(Widget* parent); + virtual ~TextEdit(); + + // From Widget + bool isFocusable() override + { + return true; + } + void resize(std::size_t width, std::size_t height) override; + + std::string getText(); + void setText(const std::string& text); + + void setReadOnly(bool readonly); + bool readOnly(); + + void preprocessText(); + + Notifier<> textChangedNotifier; + +protected: + // From Widget + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + void scrollEvent(ScrollEvent* scrollEvent) override; + +private: + void scrolled(int value); + + TexturedBox box{getImageCache(), ":resources/widget.png", 0, + 0, // atlas offset (x, y) + 7, 1, 7, // dx1, dx2, dx3 + 7, 63, 7}; // dy1, dy2, dy3 + + static constexpr int x_border{10}; + static constexpr int y_border{8}; + + ScrollBar scroll; + Font font; + + std::string text; + + bool readonly{true}; + bool needs_preprocessing{false}; + + std::vector preprocessed_text; +}; + +} // GUI:: diff --git a/dggui/texture.cc b/dggui/texture.cc new file mode 100644 index 0000000..8cd7040 --- /dev/null +++ b/dggui/texture.cc @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * texture.cc + * + * Sat Jun 4 21:18:11 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "texture.h" + +namespace GUI +{ + +Texture::Texture(ImageCache& image_cache, const std::string& filename, + std::size_t x, std::size_t y, + std::size_t width, std::size_t height) + : ScopedImageBorrower(image_cache, filename) + , _x(x) + , _y(y) + , _width(width>image.width()?image.width():width) + , _height(height>image.height()?image.height():height) +{ +} + +size_t Texture::width() const +{ + return _width; +} + +size_t Texture::height() const +{ + return _height; +} + +const Colour& Texture::getPixel(size_t x, size_t y) const +{ + if(x > _width || y > _height) + { + return outOfRange; + } + return image.getPixel(x + _x, y + _y); +} + +const std::uint8_t* Texture::line(std::size_t y, std::size_t x_offset) const +{ + return image.line(y + _y) + _x * 4 + x_offset * 4; +} + +bool Texture::hasAlpha() const +{ + return true; +} + +} // GUI:: diff --git a/dggui/texture.h b/dggui/texture.h new file mode 100644 index 0000000..c751ed4 --- /dev/null +++ b/dggui/texture.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * texture.h + * + * Sat Jun 4 21:18:11 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include "imagecache.h" +#include "image.h" + +namespace GUI +{ + +class Texture + : public ScopedImageBorrower + , public Drawable +{ +public: + Texture(ImageCache& image_cache, const std::string& filename, + std::size_t x = 0, std::size_t y = 0, + std::size_t width = std::numeric_limits::max(), + std::size_t height = std::numeric_limits::max()); + + size_t width() const override; + size_t height() const override; + + const Colour& getPixel(size_t x, size_t y) const override; + const std::uint8_t* line(std::size_t y, + std::size_t x_offset = 0) const override; + bool hasAlpha() const override; + +private: + std::size_t _x; + std::size_t _y; + std::size_t _width; + std::size_t _height; + Colour outOfRange{0.0f, 0.0f, 0.0f, 0.0f}; +}; + +} // GUI:: diff --git a/dggui/texturedbox.cc b/dggui/texturedbox.cc new file mode 100644 index 0000000..e48353a --- /dev/null +++ b/dggui/texturedbox.cc @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * texturedbox.cc + * + * Sun Jun 5 12:22:15 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "texturedbox.h" + +#include + +namespace GUI +{ + +TexturedBox::TexturedBox(ImageCache& image_cache, const std::string& filename, + std::size_t x0, std::size_t y0, + std::size_t dx1, std::size_t dx2, std::size_t dx3, + std::size_t dy1, std::size_t dy2, std::size_t dy3) + : seg_a(image_cache, filename, x0 , y0 , dx1, dy1) + , seg_b(image_cache, filename, x0 + dx1 , y0 , dx2, dy1) + , seg_c(image_cache, filename, x0 + dx1 + dx2, y0 , dx3, dy1) + , seg_d(image_cache, filename, x0 , y0 + dy1 , dx1, dy2) + , seg_e(image_cache, filename, x0 + dx1 , y0 + dy1 , dx2, dy2) + , seg_f(image_cache, filename, x0 + dx1 + dx2, y0 + dy1 , dx3, dy2) + , seg_g(image_cache, filename, x0 , y0 + dy1 + dy2, dx1, dy3) + , seg_h(image_cache, filename, x0 + dx1 , y0 + dy1 + dy2, dx2, dy3) + , seg_i(image_cache, filename, x0 + dx1 + dx2, y0 + dy1 + dy2, dx3, dy3) + , dx1(dx1) + , dx2(dx2) + , dx3(dx3) + , dy1(dy1) + , dy2(dy2) + , dy3(dy3) + , _width(dx1 + dx2 + dx3) + , _height(dy1 + dy2 + dy3) +{ +} + +std::size_t TexturedBox::width() const +{ + return _width; +} + +std::size_t TexturedBox::height() const +{ + return _height; +} + +void TexturedBox::setSize(std::size_t width, std::size_t height) +{ + _width = width; + _height = height; +} + +const Colour& TexturedBox::getPixel(std::size_t x, std::size_t y) const +{ + assert(x < _width); + assert(y < _height); + + if(y < dy1) // row 1 + { + if(x < dx1) // col 1 + { + return seg_a.getPixel(x, y); + } + else if(x < (_width - dx3)) // col 2 + { + float scale = (float)(x - dx1) / (float)(_width - dx1 - dx3); + assert(seg_b.width() == dx2); + return seg_b.getPixel(scale * dx2, y); + } + else // col 3 + { + return seg_c.getPixel(x - (_width - dx3), y); + } + } + else if(y < (_height - dy3)) // row 2 + { + if(x < dx1) // col 1 + { + // TODO: Apply vertical scale + float scale = (float)(y - dy1) / (float)(_height - dy1 - dy3); + return seg_d.getPixel(x, scale * dy2); + } + else if(x < (_width - dx3)) // col 2 + { + float scale_x = (float)(x - dx1) / (float)(_width - dx1 - dx3); + float scale_y = (float)(y - dy1) / (float)(_height - dy1 - dy3); + return seg_e.getPixel(scale_x * dx2, scale_y * dy2); + } + else // col 3 + { + float scale = (float)(y - dy1) / (float)(_height - dy1 - dy3); + return seg_f.getPixel(x - (_width - dx3), scale * dy2); + } + } + else // row 3 + { + if(x < dx1) // col 1 + { + return seg_g.getPixel(x, y - (_height - dy3)); + } + else if(x < (_width - dx3)) // col 2 + { + float scale = (float)(x - dx1) / (float)(_width - dx1 - dx3); + return seg_h.getPixel(scale * dx2, y - (_height - dy3)); + } + else // col 3 + { + return seg_i.getPixel(x - (_width - dx3), y - (_height - dy3)); + } + } + + return outOfRange; +} + +const std::uint8_t* TexturedBox::line(std::size_t y, std::size_t x_offset) const +{ + // TODO: Gather line into temporary buffer? + return nullptr; +} + +bool TexturedBox::hasAlpha() const +{ + return true; +} + +} // GUI:: diff --git a/dggui/texturedbox.h b/dggui/texturedbox.h new file mode 100644 index 0000000..7aa3967 --- /dev/null +++ b/dggui/texturedbox.h @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * texturedbox.h + * + * Sun Jun 5 12:22:14 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "drawable.h" +#include "imagecache.h" +#include "texture.h" + +namespace GUI +{ + +class TexturedBox + : public Drawable +{ +public: + //! Draw a box from 9 image segments nested inside the same image. + //! An image says more than a thousand words: + //! .----------------------------------------. + //! | (x0, y0) | + //! | \ dx1 dx2 dx3 | + //! | .-----+-----------+-----. \ | + //! | dy1 | A | <--B--> | C | | | + //! | +-----+-----------+-----+ | | + //! | | /|\ | /|\ | /|\ | | h | + //! | | | | | | | | | e | + //! | dy2 | D | <--E--> | F | > i | + //! | | | | | | | | | g | + //! | | \|/ | \|/ | \|/ | | h | + //! | +-----+-----------+-----+ | t | + //! | dy3 | G | <--H--> | I | | | + //! | `-----+-----------+-----` / | + //! | | + //! | \___________ ___________/ | + //! | V | + //! | width | + //! `----------------------------------------` + //! + //! \param image_cache A reference to the image cache object. + //! \param filename The filename of the texture image to use. + //! \param (x0, y0) is coordinate of the upper left corner of the A segment. + //! \param (width, height) is the total rendered size of the Box. + //! \param dx1 is the width of the A, C and F segments. + //! \param dx2 is the width of the B, E and H segments. + //! \param dx3 is the width of the C, F and I segments. + //! \param dy1 is the height of the A, B and C segments. + //! \param dy2 is the height of the D, E and F segments. + //! \param dy3 is the height of the G, G and I segments. + //! + //! Segments A, C, G and I are drawn with no stretch. + //! Segments B and H are stretched horizontally to fill the + //! gaps between A, C and G, I so that resulting width is 'width' + //! Segments D and F are stretched vertically to fill the + //! gaps between A, G and C, I so that resulting height is 'height' + //! Segment E will be stretched both horizontally and vertically + //! to fill the inner space between B, H and D, F. + TexturedBox(ImageCache& image_cache, const std::string& filename, + std::size_t x0, std::size_t y0, + std::size_t dx1, std::size_t dx2, std::size_t dx3, + std::size_t dy1, std::size_t dy2, std::size_t dy3); + + // From Drawable: + std::size_t width() const override; + std::size_t height() const override; + + void setSize(std::size_t width, std::size_t height); + + const Colour& getPixel(std::size_t x, std::size_t y) const override; + const std::uint8_t* line(std::size_t y, + std::size_t x_offset = 0) const override; + bool hasAlpha() const override; + +private: + Texture seg_a; + Texture seg_b; + Texture seg_c; + Texture seg_d; + Texture seg_e; + Texture seg_f; + Texture seg_g; + Texture seg_h; + Texture seg_i; + + std::size_t dx1; + std::size_t dx2; + std::size_t dx3; + std::size_t dy1; + std::size_t dy2; + std::size_t dy3; + std::size_t _width{100}; + std::size_t _height{100}; + + Colour outOfRange{0.0f, 0.0f, 0.0f, 0.0f}; +}; + +} // GUI:: diff --git a/dggui/toggle.cc b/dggui/toggle.cc new file mode 100644 index 0000000..39587de --- /dev/null +++ b/dggui/toggle.cc @@ -0,0 +1,110 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * toggle.cc + * + * Wed Mar 22 22:58:57 CET 2017 + * Copyright 2017 AndrĂ© Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "toggle.h" + +namespace GUI +{ + +Toggle::Toggle(Widget* parent) : Widget(parent) +{ +} + +void Toggle::buttonEvent(ButtonEvent* buttonEvent) +{ + // Ignore everything except left clicks. + if(buttonEvent->button != MouseButton::left) + { + return; + } + + if((buttonEvent->direction == Direction::up) || buttonEvent->doubleClick) + { + buttonDown = false; + clicked = false; + if(inCheckbox) + { + internalSetChecked(!state); + } + } + else + { + buttonDown = true; + clicked = true; + } + + redraw(); +} + +void Toggle::setText(std::string text) +{ + _text = text; + redraw(); +} + +bool Toggle::checked() +{ + return state; +} + +void Toggle::setChecked(bool c) +{ + internalSetChecked(c); +} + +void Toggle::mouseLeaveEvent() +{ + inCheckbox = false; + if(buttonDown) + { + clicked = false; + redraw(); + } +} + +void Toggle::mouseEnterEvent() +{ + inCheckbox = true; + if(buttonDown) + { + clicked = true; + redraw(); + } +} + +void Toggle::internalSetChecked(bool checked) +{ + if(state == checked) + { + return; + } + + state = checked; + stateChangedNotifier(state); + redraw(); +} + +} // GUI:: diff --git a/dggui/toggle.h b/dggui/toggle.h new file mode 100644 index 0000000..3466459 --- /dev/null +++ b/dggui/toggle.h @@ -0,0 +1,70 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * toggle.h + * + * Wed Mar 22 22:58:57 CET 2017 + * Copyright 2017 AndrĂ© Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "widget.h" + +#include + +namespace GUI +{ + +class Toggle : public Widget +{ +public: + Toggle(Widget* parent); + virtual ~Toggle() = default; + + void setText(std::string text); + + // From Widget: + bool isFocusable() override { return true; } + bool catchMouse() override { return true; } + + bool checked(); + void setChecked(bool checked); + + Notifier stateChangedNotifier; + +protected: + // From Widget: + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void mouseLeaveEvent() override; + virtual void mouseEnterEvent() override; + + bool state{false}; + bool clicked{false}; + bool buttonDown{false}; + bool inCheckbox{false}; + + std::string _text; + +private: + void internalSetChecked(bool checked); +}; + +} // GUI:: diff --git a/dggui/tooltip.cc b/dggui/tooltip.cc new file mode 100644 index 0000000..e251ed5 --- /dev/null +++ b/dggui/tooltip.cc @@ -0,0 +1,200 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * tooltip.cc + * + * Wed May 8 17:31:42 CEST 2019 + * Copyright 2019 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "tooltip.h" + +#include "painter.h" +#include "font.h" +#include "window.h" +#include + +namespace GUI +{ + +Tooltip::Tooltip(Widget *parent) + : Widget(parent->window()) + , activating_widget(parent) +{ + resize(32, 32); +} + +Tooltip::~Tooltip() +{ +} + +void Tooltip::setText(const std::string& text) +{ + this->text = text; + needs_preprocessing = true; + redraw(); +} + +void Tooltip::resize(std::size_t width, std::size_t height) +{ + Widget::resize(width, height); +} + +void Tooltip::repaintEvent(RepaintEvent* repaintEvent) +{ + if(needs_preprocessing) + { + preprocessText(); + } + + Painter p(*this); + + if((width() == 0) || (height() == 0)) + { + return; + } + + box.setSize(width(), height()); + p.drawImage(0, 0, box); + p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); + + int ypos = font.textHeight() + y_border; + + for(std::size_t i = 0; i < preprocessed_text.size(); ++i) + { + if(i * font.textHeight() >= (height() - y_border - font.textHeight())) + { + break; + } + + auto const& line = preprocessed_text[i]; + p.drawText(x_border, ypos, font, line); + ypos += font.textHeight(); + } +} + +void Tooltip::preprocessText() +{ + std::vector lines; + + preprocessed_text.clear(); + std::string text = this->text; + + // Handle tab characters + for(std::size_t i = 0; i < text.length(); ++i) + { + char ch = text.at(i); + if(ch == '\t') + { + text.erase(i, 1); + text.insert(i, 4, ' '); + } + } + + // Handle "\r" + for(std::size_t i = 0; i < text.length(); ++i) + { + char ch = text.at(i); + if(ch == '\r') + { + text.erase(i, 1); + } + } + + // Handle new line characters + std::size_t pos = 0; + do + { + pos = text.find("\n"); + lines.push_back(text.substr(0, pos)); + text = text.substr(pos + 1); + } while(pos != std::string::npos); + + max_text_width = 0; + total_text_height = 0; + for(auto const& line: lines) + { + std::string valid; + std::string current; + for(auto c: line) + { + current += c; + if(c == ' ') + { + valid.append(current.substr(valid.size())); + } + } + preprocessed_text.push_back(current); + + max_text_width = std::max(max_text_width, font.textWidth(line)); + total_text_height += font.textHeight(line); + } +} + +void Tooltip::mouseLeaveEvent() +{ + hide(); +} + +void Tooltip::show() +{ + if(needs_preprocessing) + { + preprocessText(); + } + + resize(max_text_width + 2*x_border, total_text_height + 2*y_border); + + int x = activating_widget->translateToWindowX(); + int y = activating_widget->translateToWindowY(); + + if(x + width() > window()->width()) + { + x -= width(); + x += activating_widget->width(); + } + + if(y + height() > window()->height()) + { + y -= height(); + y += activating_widget->height(); + } + + // Make sure the tip is displayed inside the window + x = std::max(x, 0); + y = std::max(y, 0); + + move(x, y); + Widget::show(); + + // TODO: This should be handled differently + // Hack to notify the window that the mouse is now inside the tooltip. + window()->setMouseFocus(this); +} + +void Tooltip::buttonEvent(ButtonEvent* buttonEvent) +{ + if(buttonEvent->direction == Direction::down) + { + hide(); + } +} + +} // GUI:: diff --git a/dggui/tooltip.h b/dggui/tooltip.h new file mode 100644 index 0000000..9d1619d --- /dev/null +++ b/dggui/tooltip.h @@ -0,0 +1,78 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * tooltip.h + * + * Wed May 8 17:31:42 CEST 2019 + * Copyright 2019 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +#include + +#include "widget.h" +#include "painter.h" +#include "texturedbox.h" +#include "font.h" + +namespace GUI +{ + +class Tooltip + : public Widget +{ +public: + Tooltip(Widget *parent); + virtual ~Tooltip(); + + void setText(const std::string& text); + + // From Widget: + virtual void repaintEvent(RepaintEvent* repaint_event) override; + virtual void resize(std::size_t height, std::size_t width) override; + virtual void mouseLeaveEvent() override; + virtual void show() override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + +private: + void preprocessText(); + + TexturedBox box{getImageCache(), ":resources/thinlistbox.png", + 0, 0, // atlas offset (x, y) + 1, 1, 1, // dx1, dx2, dx3 + 1, 1, 1}; // dy1, dy2, dy3 + Font font; + + static constexpr int x_border{10}; + static constexpr int y_border{8}; + + bool needs_preprocessing{false}; + std::string text; + std::vector preprocessed_text; + std::size_t max_text_width{0}; + std::size_t total_text_height{0}; + Widget* activating_widget; +}; + +} // GUI:: diff --git a/dggui/uitranslation.cc b/dggui/uitranslation.cc new file mode 100644 index 0000000..0546be8 --- /dev/null +++ b/dggui/uitranslation.cc @@ -0,0 +1,51 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * uitranslation.cc + * + * Thu May 7 18:04:40 CEST 2020 + * Copyright 2020 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "uitranslation.h" + +#ifdef WITH_NLS + +#include "resource.h" + +UITranslation::UITranslation() +{ + auto lang = Translation::getISO639LanguageName(); + printf("LANG: %s\n", lang.data()); + std::string res = ":locale/"; + res += lang + ".mo"; + + GUI::Resource mo(res); + if(!mo.valid()) + { + printf("Locale not in resources - use default\n"); + // Locale not in resources - use default + return; + } + printf("Using mo: %s\n", res.data()); + load(mo.data(), mo.size()); +} + +#endif // WITH_NLS diff --git a/dggui/uitranslation.h b/dggui/uitranslation.h new file mode 100644 index 0000000..5341255 --- /dev/null +++ b/dggui/uitranslation.h @@ -0,0 +1,41 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * uitranslation.h + * + * Thu May 7 18:04:40 CEST 2020 + * Copyright 2020 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include + +#include + +#ifdef WITH_NLS +class UITranslation + : public Translation +{ +public: + UITranslation(); + ~UITranslation() = default; +}; +#endif diff --git a/dggui/utf8.cc b/dggui/utf8.cc new file mode 100644 index 0000000..747e726 --- /dev/null +++ b/dggui/utf8.cc @@ -0,0 +1,361 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * utf8.cc + * + * Tue Feb 27 19:18:23 CET 2007 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "utf8.h" + +UTF8::UTF8() +{ + // Encode Map + map_encode["\x80"] = "\xc2\x80"; + map_encode["\x81"] = "\xc2\x81"; + map_encode["\x82"] = "\xc2\x82"; + map_encode["\x83"] = "\xc2\x83"; + map_encode["\x84"] = "\xc2\x84"; + map_encode["\x85"] = "\xc2\x85"; + map_encode["\x86"] = "\xc2\x86"; + map_encode["\x87"] = "\xc2\x87"; + map_encode["\x88"] = "\xc2\x88"; + map_encode["\x89"] = "\xc2\x89"; + map_encode["\x8a"] = "\xc2\x8a"; + map_encode["\x8b"] = "\xc2\x8b"; + map_encode["\x8c"] = "\xc2\x8c"; + map_encode["\x8d"] = "\xc2\x8d"; + map_encode["\x8e"] = "\xc2\x8e"; + map_encode["\x8f"] = "\xc2\x8f"; + map_encode["\x90"] = "\xc2\x90"; + map_encode["\x91"] = "\xc2\x91"; + map_encode["\x92"] = "\xc2\x92"; + map_encode["\x93"] = "\xc2\x93"; + map_encode["\x94"] = "\xc2\x94"; + map_encode["\x95"] = "\xc2\x95"; + map_encode["\x96"] = "\xc2\x96"; + map_encode["\x97"] = "\xc2\x97"; + map_encode["\x98"] = "\xc2\x98"; + map_encode["\x99"] = "\xc2\x99"; + map_encode["\x9a"] = "\xc2\x9a"; + map_encode["\x9b"] = "\xc2\x9b"; + map_encode["\x9c"] = "\xc2\x9c"; + map_encode["\x9d"] = "\xc2\x9d"; + map_encode["\x9e"] = "\xc2\x9e"; + map_encode["\x9f"] = "\xc2\x9f"; + map_encode["\xa0"] = "\xc2\xa0"; + map_encode["\xa1"] = "\xc2\xa1"; + map_encode["\xa2"] = "\xc2\xa2"; + map_encode["\xa3"] = "\xc2\xa3"; + map_encode["\xa4"] = "\xc2\xa4"; + map_encode["\xa5"] = "\xc2\xa5"; + map_encode["\xa6"] = "\xc2\xa6"; + map_encode["\xa7"] = "\xc2\xa7"; + map_encode["\xa8"] = "\xc2\xa8"; + map_encode["\xa9"] = "\xc2\xa9"; + map_encode["\xaa"] = "\xc2\xaa"; + map_encode["\xab"] = "\xc2\xab"; + map_encode["\xac"] = "\xc2\xac"; + map_encode["\xad"] = "\xc2\xad"; + map_encode["\xae"] = "\xc2\xae"; + map_encode["\xaf"] = "\xc2\xaf"; + map_encode["\xb0"] = "\xc2\xb0"; + map_encode["\xb1"] = "\xc2\xb1"; + map_encode["\xb2"] = "\xc2\xb2"; + map_encode["\xb3"] = "\xc2\xb3"; + map_encode["\xb4"] = "\xc2\xb4"; + map_encode["\xb5"] = "\xc2\xb5"; + map_encode["\xb6"] = "\xc2\xb6"; + map_encode["\xb7"] = "\xc2\xb7"; + map_encode["\xb8"] = "\xc2\xb8"; + map_encode["\xb9"] = "\xc2\xb9"; + map_encode["\xba"] = "\xc2\xba"; + map_encode["\xbb"] = "\xc2\xbb"; + map_encode["\xbc"] = "\xc2\xbc"; + map_encode["\xbd"] = "\xc2\xbd"; + map_encode["\xbe"] = "\xc2\xbe"; + map_encode["\xbf"] = "\xc2\xbf"; + map_encode["\xc0"] = "\xc3\x80"; + map_encode["\xc1"] = "\xc3\x81"; + map_encode["\xc2"] = "\xc3\x82"; + map_encode["\xc3"] = "\xc3\x83"; + map_encode["\xc4"] = "\xc3\x84"; + map_encode["\xc5"] = "\xc3\x85"; + map_encode["\xc6"] = "\xc3\x86"; + map_encode["\xc7"] = "\xc3\x87"; + map_encode["\xc8"] = "\xc3\x88"; + map_encode["\xc9"] = "\xc3\x89"; + map_encode["\xca"] = "\xc3\x8a"; + map_encode["\xcb"] = "\xc3\x8b"; + map_encode["\xcc"] = "\xc3\x8c"; + map_encode["\xcd"] = "\xc3\x8d"; + map_encode["\xce"] = "\xc3\x8e"; + map_encode["\xcf"] = "\xc3\x8f"; + map_encode["\xd0"] = "\xc3\x90"; + map_encode["\xd1"] = "\xc3\x91"; + map_encode["\xd2"] = "\xc3\x92"; + map_encode["\xd3"] = "\xc3\x93"; + map_encode["\xd4"] = "\xc3\x94"; + map_encode["\xd5"] = "\xc3\x95"; + map_encode["\xd6"] = "\xc3\x96"; + map_encode["\xd7"] = "\xc3\x97"; + map_encode["\xd8"] = "\xc3\x98"; + map_encode["\xd9"] = "\xc3\x99"; + map_encode["\xda"] = "\xc3\x9a"; + map_encode["\xdb"] = "\xc3\x9b"; + map_encode["\xdc"] = "\xc3\x9c"; + map_encode["\xdd"] = "\xc3\x9d"; + map_encode["\xde"] = "\xc3\x9e"; + map_encode["\xdf"] = "\xc3\x9f"; + map_encode["\xe0"] = "\xc3\xa0"; + map_encode["\xe1"] = "\xc3\xa1"; + map_encode["\xe2"] = "\xc3\xa2"; + map_encode["\xe3"] = "\xc3\xa3"; + map_encode["\xe4"] = "\xc3\xa4"; + map_encode["\xe5"] = "\xc3\xa5"; + map_encode["\xe6"] = "\xc3\xa6"; + map_encode["\xe7"] = "\xc3\xa7"; + map_encode["\xe8"] = "\xc3\xa8"; + map_encode["\xe9"] = "\xc3\xa9"; + map_encode["\xea"] = "\xc3\xaa"; + map_encode["\xeb"] = "\xc3\xab"; + map_encode["\xec"] = "\xc3\xac"; + map_encode["\xed"] = "\xc3\xad"; + map_encode["\xee"] = "\xc3\xae"; + map_encode["\xef"] = "\xc3\xaf"; + map_encode["\xf0"] = "\xc3\xb0"; + map_encode["\xf1"] = "\xc3\xb1"; + map_encode["\xf2"] = "\xc3\xb2"; + map_encode["\xf3"] = "\xc3\xb3"; + map_encode["\xf4"] = "\xc3\xb4"; + map_encode["\xf5"] = "\xc3\xb5"; + map_encode["\xf6"] = "\xc3\xb6"; + map_encode["\xf7"] = "\xc3\xb7"; + map_encode["\xf8"] = "\xc3\xb8"; + map_encode["\xf9"] = "\xc3\xb9"; + map_encode["\xfa"] = "\xc3\xba"; + map_encode["\xfb"] = "\xc3\xbb"; + map_encode["\xfc"] = "\xc3\xbc"; + map_encode["\xfd"] = "\xc3\xbd"; + map_encode["\xfe"] = "\xc3\xbe"; + map_encode["\xff"] = "\xc3\xbf"; + + // Decode Map + map_decode["\xc2\x80"] = "\x80"; + map_decode["\xc2\x81"] = "\x81"; + map_decode["\xc2\x82"] = "\x82"; + map_decode["\xc2\x83"] = "\x83"; + map_decode["\xc2\x84"] = "\x84"; + map_decode["\xc2\x85"] = "\x85"; + map_decode["\xc2\x86"] = "\x86"; + map_decode["\xc2\x87"] = "\x87"; + map_decode["\xc2\x88"] = "\x88"; + map_decode["\xc2\x89"] = "\x89"; + map_decode["\xc2\x8a"] = "\x8a"; + map_decode["\xc2\x8b"] = "\x8b"; + map_decode["\xc2\x8c"] = "\x8c"; + map_decode["\xc2\x8d"] = "\x8d"; + map_decode["\xc2\x8e"] = "\x8e"; + map_decode["\xc2\x8f"] = "\x8f"; + map_decode["\xc2\x90"] = "\x90"; + map_decode["\xc2\x91"] = "\x91"; + map_decode["\xc2\x92"] = "\x92"; + map_decode["\xc2\x93"] = "\x93"; + map_decode["\xc2\x94"] = "\x94"; + map_decode["\xc2\x95"] = "\x95"; + map_decode["\xc2\x96"] = "\x96"; + map_decode["\xc2\x97"] = "\x97"; + map_decode["\xc2\x98"] = "\x98"; + map_decode["\xc2\x99"] = "\x99"; + map_decode["\xc2\x9a"] = "\x9a"; + map_decode["\xc2\x9b"] = "\x9b"; + map_decode["\xc2\x9c"] = "\x9c"; + map_decode["\xc2\x9d"] = "\x9d"; + map_decode["\xc2\x9e"] = "\x9e"; + map_decode["\xc2\x9f"] = "\x9f"; + map_decode["\xc2\xa0"] = "\xa0"; + map_decode["\xc2\xa1"] = "\xa1"; + map_decode["\xc2\xa2"] = "\xa2"; + map_decode["\xc2\xa3"] = "\xa3"; + map_decode["\xc2\xa4"] = "\xa4"; + map_decode["\xc2\xa5"] = "\xa5"; + map_decode["\xc2\xa6"] = "\xa6"; + map_decode["\xc2\xa7"] = "\xa7"; + map_decode["\xc2\xa8"] = "\xa8"; + map_decode["\xc2\xa9"] = "\xa9"; + map_decode["\xc2\xaa"] = "\xaa"; + map_decode["\xc2\xab"] = "\xab"; + map_decode["\xc2\xac"] = "\xac"; + map_decode["\xc2\xad"] = "\xad"; + map_decode["\xc2\xae"] = "\xae"; + map_decode["\xc2\xaf"] = "\xaf"; + map_decode["\xc2\xb0"] = "\xb0"; + map_decode["\xc2\xb1"] = "\xb1"; + map_decode["\xc2\xb2"] = "\xb2"; + map_decode["\xc2\xb3"] = "\xb3"; + map_decode["\xc2\xb4"] = "\xb4"; + map_decode["\xc2\xb5"] = "\xb5"; + map_decode["\xc2\xb6"] = "\xb6"; + map_decode["\xc2\xb7"] = "\xb7"; + map_decode["\xc2\xb8"] = "\xb8"; + map_decode["\xc2\xb9"] = "\xb9"; + map_decode["\xc2\xba"] = "\xba"; + map_decode["\xc2\xbb"] = "\xbb"; + map_decode["\xc2\xbc"] = "\xbc"; + map_decode["\xc2\xbd"] = "\xbd"; + map_decode["\xc2\xbe"] = "\xbe"; + map_decode["\xc2\xbf"] = "\xbf"; + map_decode["\xc3\x80"] = "\xc0"; + map_decode["\xc3\x81"] = "\xc1"; + map_decode["\xc3\x82"] = "\xc2"; + map_decode["\xc3\x83"] = "\xc3"; + map_decode["\xc3\x84"] = "\xc4"; + map_decode["\xc3\x85"] = "\xc5"; + map_decode["\xc3\x86"] = "\xc6"; + map_decode["\xc3\x87"] = "\xc7"; + map_decode["\xc3\x88"] = "\xc8"; + map_decode["\xc3\x89"] = "\xc9"; + map_decode["\xc3\x8a"] = "\xca"; + map_decode["\xc3\x8b"] = "\xcb"; + map_decode["\xc3\x8c"] = "\xcc"; + map_decode["\xc3\x8d"] = "\xcd"; + map_decode["\xc3\x8e"] = "\xce"; + map_decode["\xc3\x8f"] = "\xcf"; + map_decode["\xc3\x90"] = "\xd0"; + map_decode["\xc3\x91"] = "\xd1"; + map_decode["\xc3\x92"] = "\xd2"; + map_decode["\xc3\x93"] = "\xd3"; + map_decode["\xc3\x94"] = "\xd4"; + map_decode["\xc3\x95"] = "\xd5"; + map_decode["\xc3\x96"] = "\xd6"; + map_decode["\xc3\x97"] = "\xd7"; + map_decode["\xc3\x98"] = "\xd8"; + map_decode["\xc3\x99"] = "\xd9"; + map_decode["\xc3\x9a"] = "\xda"; + map_decode["\xc3\x9b"] = "\xdb"; + map_decode["\xc3\x9c"] = "\xdc"; + map_decode["\xc3\x9d"] = "\xdd"; + map_decode["\xc3\x9e"] = "\xde"; + map_decode["\xc3\x9f"] = "\xdf"; + map_decode["\xc3\xa0"] = "\xe0"; + map_decode["\xc3\xa1"] = "\xe1"; + map_decode["\xc3\xa2"] = "\xe2"; + map_decode["\xc3\xa3"] = "\xe3"; + map_decode["\xc3\xa4"] = "\xe4"; + map_decode["\xc3\xa5"] = "\xe5"; + map_decode["\xc3\xa6"] = "\xe6"; + map_decode["\xc3\xa7"] = "\xe7"; + map_decode["\xc3\xa8"] = "\xe8"; + map_decode["\xc3\xa9"] = "\xe9"; + map_decode["\xc3\xaa"] = "\xea"; + map_decode["\xc3\xab"] = "\xeb"; + map_decode["\xc3\xac"] = "\xec"; + map_decode["\xc3\xad"] = "\xed"; + map_decode["\xc3\xae"] = "\xee"; + map_decode["\xc3\xaf"] = "\xef"; + map_decode["\xc3\xb0"] = "\xf0"; + map_decode["\xc3\xb1"] = "\xf1"; + map_decode["\xc3\xb2"] = "\xf2"; + map_decode["\xc3\xb3"] = "\xf3"; + map_decode["\xc3\xb4"] = "\xf4"; + map_decode["\xc3\xb5"] = "\xf5"; + map_decode["\xc3\xb6"] = "\xf6"; + map_decode["\xc3\xb7"] = "\xf7"; + map_decode["\xc3\xb8"] = "\xf8"; + map_decode["\xc3\xb9"] = "\xf9"; + map_decode["\xc3\xba"] = "\xfa"; + map_decode["\xc3\xbb"] = "\xfb"; + map_decode["\xc3\xbc"] = "\xfc"; + map_decode["\xc3\xbd"] = "\xfd"; + map_decode["\xc3\xbe"] = "\xfe"; + map_decode["\xc3\xbf"] = "\xff"; + // FIXME: This is just a hack to make Goran Mekic's name work. + map_decode["\xc4\x87"] = "c"; +} + +std::string UTF8::fromLatin1(std::string const& s) +{ + std::string ret; + + for(int i = 0; i < (int)s.length(); i++) + { + std::string c; + + if((unsigned char)s[i] <= 0x7F) + { + c = s.substr(i, 1); + } + else + { + c = map_encode[s.substr(i, 1)]; + } + + // If c == "", the character wasn't found in the map. + // Ignore this case for now and just push an empty string in this case. + + ret.append(c); + } + + return ret; +} + +std::string UTF8::toLatin1(std::string const& s) +{ + std::string ret; + + int width = 1; + for(int i = 0; i < (int)s.length(); i += width) + { + if(/*(unsigned char)s[i]>=0x00&&*/ (unsigned char)s[i] <= 0x7F) + { + width = 1; // 00-7F -> 1 byte + } + if((unsigned char)s[i] >= 0xC2 && (unsigned char)s[i] <= 0xDF) + { + width = 2; // C2-DF -> 2 bytes + } + if((unsigned char)s[i] >= 0xE0 && (unsigned char)s[i] <= 0xEF) + { + width = 3; // E0-EF -> 3 bytes + } + if((unsigned char)s[i] >= 0xF0 && (unsigned char)s[i] <= 0xF4) + { + width = 4; // F0-F4 -> 4 bytes + } + + std::string c; + if(width == 1) + { + c = s.substr(i, 1); + } + else + { + c = map_decode[s.substr(i, width)]; + } + + // If c == "", the character wasn't found in the map. + // Ignore this case for now and just push an empty string in this case. + + ret.append(c); + } + + return ret; +} diff --git a/dggui/utf8.h b/dggui/utf8.h new file mode 100644 index 0000000..04c26b1 --- /dev/null +++ b/dggui/utf8.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * utf8.h + * + * Tue Feb 27 19:18:23 CET 2007 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include + +// Class to convert utf8 to latin1 and the other way around. +class UTF8 +{ +public: + UTF8(); + + // Encode a string from latin1 to UTF-8. + std::string fromLatin1(std::string const& s); + + // Decode a string from UTF-8 to latin1. + std::string toLatin1(std::string const& s); + +private: + std::unordered_map map_encode; + std::unordered_map map_decode; +}; diff --git a/dggui/verticalline.cc b/dggui/verticalline.cc new file mode 100644 index 0000000..6a3a98a --- /dev/null +++ b/dggui/verticalline.cc @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * verticalline.cc + * + * Sat Apr 6 12:59:44 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "verticalline.h" + +#include "painter.h" + +namespace GUI { + +VerticalLine::VerticalLine(Widget *parent) + : Widget(parent) + , vline(":resources/vertline.png") +{ +} + +void VerticalLine::repaintEvent(RepaintEvent* repaintEvent) +{ + if(height() < 2) + { + return; + } + + Painter p(*this); + p.drawImageStretched(0, (height() - vline.height()) / 2, + vline, width(), vline.height()); +} + +} // GUI:: diff --git a/dggui/verticalline.h b/dggui/verticalline.h new file mode 100644 index 0000000..3403244 --- /dev/null +++ b/dggui/verticalline.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * verticalline.h + * + * Sat Apr 6 12:59:43 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "widget.h" +#include "image.h" + +namespace GUI { + +class VerticalLine : public Widget { +public: + VerticalLine(Widget* parent); + virtual ~VerticalLine() = default; + +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + Image vline; +}; + +} // GUI:: diff --git a/dggui/widget.cc b/dggui/widget.cc new file mode 100644 index 0000000..da6b1e2 --- /dev/null +++ b/dggui/widget.cc @@ -0,0 +1,297 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * widget.cc + * + * Sun Oct 9 13:01:44 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "widget.h" + +#include + +#include "painter.h" +#include "window.h" + +namespace GUI +{ + +Widget::Widget(Widget* parent) + : parent(parent) +{ + if(parent) + { + parent->addChild(this); + _window = parent->window(); + } + + pixbuf.x = translateToWindowX(); + pixbuf.y = translateToWindowY(); +} + +Widget::~Widget() +{ + if(parent) + { + parent->removeChild(this); + } +} + +void Widget::show() +{ + setVisible(true); +} + +void Widget::hide() +{ + setVisible(false); +} + +void Widget::setVisible(bool visible) +{ + _visible = visible; + pixbuf.visible = visible; + redraw(); +} + +bool Widget::visible() const +{ + return _visible; +} + +void Widget::redraw() +{ + dirty = true; + window()->needsRedraw(); +} + +void Widget::addChild(Widget* widget) +{ + children.push_back(widget); +} + +void Widget::removeChild(Widget* widget) +{ + for(auto i = children.begin(); i != children.end(); ++i) + { + if(*i == widget) + { + children.erase(i); + return; + } + } +} + +void Widget::reparent(Widget* parent) +{ + if(parent == this->parent) + { + return; // Already at the right parent. + } + + if(this->parent) + { + this->parent->removeChild(this); + } + + if(parent) + { + parent->addChild(this); + } + + this->parent = parent; +} + +void Widget::resize(std::size_t width, std::size_t height) +{ + assert(width < 32000 && height < 32000); // Catch negative values as size_t + if((width < 1) || (height < 1) || + ((width == _width) && (height == _height))) + { + return; + } + + _width = width; + _height = height; + + // Store old size/position in pixelbuffer for rendering invalidation. + if(!pixbuf.has_last) + { + pixbuf.last_width = pixbuf.width; + pixbuf.last_height = pixbuf.height; + pixbuf.last_x = pixbuf.x; + pixbuf.last_y = pixbuf.y; + pixbuf.has_last = true; + } + + pixbuf.realloc(width, height); + pixbuf.x = translateToWindowX(); + pixbuf.y = translateToWindowY(); + redraw(); + sizeChangeNotifier(width, height); +} + +void Widget::move(int x, int y) +{ + if((_x == x) && + (_y == y)) + { + return; + } + + _x = x; + _y = y; + + // Store old size/position in pixelbuffer for rendering invalidation. + if(!pixbuf.has_last) + { + pixbuf.last_width = pixbuf.width; + pixbuf.last_height = pixbuf.height; + pixbuf.last_x = pixbuf.x; + pixbuf.last_y = pixbuf.y; + pixbuf.has_last = true; + } + + //pixbuf.x = translateToWindowX(); + //pixbuf.y = translateToWindowY(); + + positionChangeNotifier(x, y); +} + +int Widget::x() const +{ + return _x; +} + +int Widget::y() const +{ + return _y; +} + +std::size_t Widget::width() const +{ + return _width; +} + +std::size_t Widget::height() const +{ + return _height; +} + +Point Widget::position() const +{ + return { _x, _y }; +} + +PixelBufferAlpha& Widget::getPixelBuffer() +{ + return pixbuf; +} + +ImageCache& Widget::getImageCache() +{ + assert(parent); + return parent->getImageCache(); +} + +Widget* Widget::find(int x, int y) +{ + for(auto i = children.rbegin(); i != children.rend(); ++i) + { + Widget* widget = *i; + if(widget->visible()) + { + if((x >= widget->x()) && (x < (widget->x() + (int)widget->width())) && + (y >= widget->y()) && (y < (widget->y() + (int)widget->height()))) + { + return widget->find(x - widget->x(), y - widget->y()); + } + } + } + + return this; +} + +Window* Widget::window() +{ + return _window; +} + +std::vector Widget::getPixelBuffers() +{ + std::vector pixelBuffers; + + pixbuf.x = translateToWindowX(); + pixbuf.y = translateToWindowY(); + + if(dirty) + { + repaintEvent(nullptr); + pixbuf.dirty = true; + dirty = false; + } + + if(pixbuf.dirty || visible()) + { + pixelBuffers.push_back(&pixbuf); + } + + if(visible()) + { + for(auto child : children) + { + auto childPixelBuffers = child->getPixelBuffers(); + pixelBuffers.insert(pixelBuffers.end(), + childPixelBuffers.begin(), childPixelBuffers.end()); + } + } + + return pixelBuffers; +} + +bool Widget::hasKeyboardFocus() +{ + return window()->keyboardFocus() == this; +} + +std::size_t Widget::translateToWindowX() +{ + size_t window_x = x(); + if(parent) + { + window_x += parent->translateToWindowX(); + } + + return window_x; +} + +std::size_t Widget::translateToWindowY() +{ + size_t window_y = y(); + if(parent) + { + window_y += parent->translateToWindowY(); + } + + return window_y; +} + +} // GUI:: diff --git a/dggui/widget.h b/dggui/widget.h new file mode 100644 index 0000000..b9436b7 --- /dev/null +++ b/dggui/widget.h @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * widget.h + * + * Sun Oct 9 13:01:44 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "guievent.h" +#include "pixelbuffer.h" +#include "notifier.h" +#include "layout.h" +#include "canvas.h" + +#include + +namespace GUI +{ + +struct Point +{ + int x; + int y; +}; + +struct Size +{ + std::size_t width; + std::size_t height; +}; + +class ImageCache; +class Window; + +class Widget + : public Listener + , public LayoutItem + , public Canvas +{ + friend class Painter; +public: + Widget(Widget* parent); + virtual ~Widget(); + + virtual void show(); + virtual void hide(); + void setVisible(bool visible); + virtual bool visible() const; + + //! Mark widget dirty and shedule redraw on next window redraw. + void redraw(); + + // From LayoutItem + virtual void resize(std::size_t width, std::size_t height) override; + virtual void move(int x, int y) override; + virtual int x() const override; + virtual int y() const override; + virtual std::size_t width() const override; + virtual std::size_t height() const override; + + Point position() const; + + // From Canvas + PixelBufferAlpha& getPixelBuffer() override; + + virtual bool isFocusable() { return false; } + virtual bool catchMouse() { return false; } + + void addChild(Widget* widget); + void removeChild(Widget* widget); + void reparent(Widget* parent); + + virtual void repaintEvent(RepaintEvent* repaintEvent) {} + virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) {} + virtual void buttonEvent(ButtonEvent* buttonEvent) {} + virtual void scrollEvent(ScrollEvent* scrollEvent) {} + virtual void keyEvent(KeyEvent* keyEvent) {} + virtual void mouseLeaveEvent() {} + virtual void mouseEnterEvent() {} + + virtual ImageCache& getImageCache(); + + Widget* find(int x, int y); + + virtual Window* window(); + + std::vector getPixelBuffers(); + + bool hasKeyboardFocus(); + + Notifier sizeChangeNotifier; // (width, height) + Notifier positionChangeNotifier; // (x, y) + + //! Translate x-coordinate from parent-space to window-space. + virtual std::size_t translateToWindowX(); + + //! Translate y-coordinate from parent-space to window-space. + virtual std::size_t translateToWindowY(); + +protected: + friend class EventHandler; + PixelBufferAlpha pixbuf{0,0}; + + std::vector children; + + Widget* parent = nullptr; + Window* _window = nullptr; + + int _x{0}; + int _y{0}; + std::size_t _width{0}; + std::size_t _height{0}; + + bool _visible{true}; + + bool dirty{true}; +}; + +} // GUI:: diff --git a/dggui/window.cc b/dggui/window.cc new file mode 100644 index 0000000..5e0ad31 --- /dev/null +++ b/dggui/window.cc @@ -0,0 +1,266 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * window.cc + * + * Sun Oct 9 13:11:53 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "window.h" + +#include + +#include "painter.h" + +#ifndef UI_PUGL +#ifdef UI_X11 +#include "nativewindow_x11.h" +#endif // UI_X11 +#ifdef UI_WIN32 +#include "nativewindow_win32.h" +#endif // UI_WIN32 +#ifdef UI_COCOA +#include "nativewindow_cocoa.h" +#endif // UI_COCOA +#else +#include "nativewindow_pugl.h" +#endif // !UI_PUGL + +namespace GUI +{ + +Window::Window(void* native_window) + : Widget(nullptr) + , wpixbuf(1, 1) +{ + // Make sure we have a valid size when initialising the NativeWindow + _width = wpixbuf.width; + _height = wpixbuf.height; + +#ifndef UI_PUGL +#ifdef UI_X11 + native = new NativeWindowX11(native_window, *this); +#endif // UI_X11 +#ifdef UI_WIN32 + native = new NativeWindowWin32(native_window, *this); +#endif // UI_WIN32 +#ifdef UI_COCOA + native = new NativeWindowCocoa(native_window, *this); +#endif // UI_COCOA +#else + // Use pugl + native = new NativeWindowPugl(native_window, *this); +#endif // !UI_PUGL + + eventhandler = new EventHandler(*native, *this); + + setVisible(true); // The root widget is always visible. +} + +Window::~Window() +{ + delete native; + delete eventhandler; +} + +void Window::setFixedSize(int w, int h) +{ + native->setFixedSize(w, h); +} + +void Window::setAlwaysOnTop(bool always_on_top) +{ + native->setAlwaysOnTop(always_on_top); +} + +void Window::setCaption(const std::string& caption) +{ + native->setCaption(caption); +} + +//! This overload the resize method on Widget and simply requests a window resize +//! on the windowmanager/OS. The resized() method is called by the event handler +//! once the window has been resized. +void Window::resize(std::size_t width, std::size_t height) +{ + native->resize(width, height); +} + +//! This overload the move method on Widget and simply requests a window move +//! on the windowmanager/OS. The moved() method is called by the event handler +//! once the window has been moved. +void Window::move(int x, int y) +{ + native->move(x, y); +} + +void Window::show() +{ + Widget::show(); + redraw(); + native->show(); +} + +void Window::hide() +{ + native->hide(); + Widget::hide(); +} + +Window* Window::window() +{ + return this; +} + +Size Window::getNativeSize() +{ + auto sz = native->getSize(); + return {sz.first, sz.second}; +} + +ImageCache& Window::getImageCache() +{ + return image_cache; +} + +EventHandler* Window::eventHandler() +{ + return eventhandler; +} + +Widget* Window::keyboardFocus() +{ + return _keyboardFocus; +} + +void Window::setKeyboardFocus(Widget* widget) +{ + auto oldFocusWidget = _keyboardFocus; + _keyboardFocus = widget; + + if(oldFocusWidget) + { + oldFocusWidget->redraw(); + } + + if(_keyboardFocus) + { + _keyboardFocus->redraw(); + } +} + +Widget* Window::buttonDownFocus() +{ + return _buttonDownFocus; +} + +void Window::setButtonDownFocus(Widget* widget) +{ + _buttonDownFocus = widget; + native->grabMouse(widget != nullptr); +} + +Widget* Window::mouseFocus() +{ + return _mouseFocus; +} + +void Window::setMouseFocus(Widget* widget) +{ + _mouseFocus = widget; + +} + +void Window::needsRedraw() +{ + needs_redraw = true; +} + +void* Window::getNativeWindowHandle() const +{ + return native->getNativeWindowHandle(); +} + +Point Window::translateToScreen(const Point& point) +{ + return native->translateToScreen(point); +} + +std::size_t Window::translateToWindowX() +{ + return 0; +} + +std::size_t Window::translateToWindowY() +{ + return 0; +} + +//! Called by event handler when an windowmanager/OS window resize event has +//! been received. Do not call this directly. +void Window::resized(std::size_t width, std::size_t height) +{ + auto size = native->getSize(); + if((wpixbuf.width != size.first) || + (wpixbuf.height != size.second)) + { + wpixbuf.realloc(size.first, size.second); + Widget::resize(size.first, size.second); + } + + updateBuffer(); +} + +//! Called by event handler when an windowmanager/OS window move event has +//! been received. Do not call this directly. +void Window::moved(int x, int y) +{ + // Make sure widget coordinates are updated. + Widget::move(x, y); +} + +bool Window::updateBuffer() +{ + if(!native) + { + return false; + } + + if(!needs_redraw) + { + // Nothing changed, don't update anything. + return false; + } + + auto pixel_buffers = getPixelBuffers(); + + auto dirty_rect = wpixbuf.updateBuffer(pixel_buffers); + + if(!dirty_rect.empty()) + { + native->redraw(dirty_rect); + } + needs_redraw = false; + + return true; +} + +} // GUI:: diff --git a/dggui/window.h b/dggui/window.h new file mode 100644 index 0000000..6031500 --- /dev/null +++ b/dggui/window.h @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * window.h + * + * Sun Oct 9 13:11:52 CEST 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "widget.h" + +#include "pixelbuffer.h" +#include "nativewindow.h" +#include "image.h" +#include "eventhandler.h" +#include "imagecache.h" + +namespace GUI +{ + +class Window + : public Widget +{ +public: + Window(void* native_window = nullptr); + ~Window(); + + void setFixedSize(int width, int height); + void setAlwaysOnTop(bool always_on_top); + void setCaption(const std::string& caption); + + // From Widget: + void resize(std::size_t width, std::size_t height) override; + void move(int x, int y) override; + void show() override; + void hide() override; + Window* window() override; + Size getNativeSize(); + ImageCache& getImageCache() override; + + EventHandler* eventHandler(); + + Widget* keyboardFocus(); + void setKeyboardFocus(Widget* widget); + + Widget* buttonDownFocus(); + void setButtonDownFocus(Widget* widget); + + Widget* mouseFocus(); + void setMouseFocus(Widget* widget); + + //! Tag the window buffer dirty to be rendered. + void needsRedraw(); + + // \returns the native window handle, it HWND on Win32 or Window id on X11 + void* getNativeWindowHandle() const; + + //! Translate a local window coordinate to a global screen coordinate. + Point translateToScreen(const Point& point); + +protected: + // For the EventHandler + friend class EventHandler; + + // From Widget: + std::size_t translateToWindowX() override; + std::size_t translateToWindowY() override; + void resized(std::size_t width, std::size_t height); + void moved(int x, int y); + + //! Returns true if window pixel buffer changed and needs to be copied to + //! native window. + bool updateBuffer(); + + // For the Painter + friend class Widget; + + // For the NativeWindow implementations: + friend class NativeWindowX11; + friend class NativeWindowWin32; + friend class NativeWindowPugl; + friend class NativeWindowCocoa; + PixelBuffer wpixbuf; + + size_t refcount{0}; + + Widget* _keyboardFocus{nullptr}; + Widget* _buttonDownFocus{nullptr}; + Widget* _mouseFocus{nullptr}; + + NativeWindow* native{nullptr}; + EventHandler* eventhandler{nullptr}; + + size_t maxRefcount{0}; + + bool needs_redraw{false}; + ImageCache image_cache; +}; + +} // GUI:: diff --git a/drumgizmo/Makefile.am b/drumgizmo/Makefile.am index 2cb46bf..b3bca32 100644 --- a/drumgizmo/Makefile.am +++ b/drumgizmo/Makefile.am @@ -109,7 +109,7 @@ dgvalidator_CXXFLAGS = \ -I$(top_srcdir)/src -I$(top_srcdir)/getoptpp \ -I$(top_srcdir)/hugin -DWITH_HUG_MUTEX -DWITH_HUG_FILTER \ $(SSEFLAGS) \ - -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -DLODEPNG_NO_COMPILE_ENCODER \ -DLODEPNG_NO_COMPILE_DISK \ -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS \ @@ -122,9 +122,9 @@ dgvalidator_SOURCES = \ dgvalidator.cc \ $(top_srcdir)/hugin/hugin.c \ $(top_srcdir)/hugin/hugin_filter.c \ - $(top_srcdir)/plugingui/lodepng/lodepng.cpp \ - $(top_srcdir)/plugingui/image.cc \ - $(top_srcdir)/plugingui/resource.cc \ - $(top_srcdir)/plugingui/colour.cc + $(top_srcdir)/dggui/lodepng/lodepng.cpp \ + $(top_srcdir)/dggui/image.cc \ + $(top_srcdir)/dggui/resource.cc \ + $(top_srcdir)/dggui/colour.cc endif # ENABLE_CLI diff --git a/drumgizmo/dgvalidator.cc b/drumgizmo/dgvalidator.cc index 6a7c546..1b21c59 100644 --- a/drumgizmo/dgvalidator.cc +++ b/drumgizmo/dgvalidator.cc @@ -37,8 +37,6 @@ #include #include -#include - #include #include @@ -48,11 +46,13 @@ #include #endif -#include +#include // Needed for Resource class -#include -const rc_data_t rc_data[] = {}; +#include + +const rc_data_t rc_dataX[] = {}; +const rc_data_t* rc_data = rc_dataX; namespace { diff --git a/plugin/Makefile.am b/plugin/Makefile.am index f382acc..935b601 100644 --- a/plugin/Makefile.am +++ b/plugin/Makefile.am @@ -19,6 +19,7 @@ drumgizmo_la_CXXFLAGS = -DLV2 -DLV2_PLUGIN_URI=\"http://drumgizmo.org/lv2\" \ $(LV2_CFLAGS) \ $(SNDFILE_CFLAGS) \ -I$(top_srcdir)/plugin/plugingizmo \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/plugingui \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin @@ -35,7 +36,7 @@ drumgizmo_la_LDFLAGS = -shared -module -avoid-version \ -no-undefined -export-symbols $(top_srcdir)/plugin/drumgizmo_lv2.sym drumgizmo_la_LIBADD = $(LV2_LIBS) \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la @@ -93,6 +94,7 @@ drumgizmo_vst_la_CXXFLAGS = -DVST \ -I$(top_srcdir)/zita-resampler/libs \ $(SNDFILE_CFLAGS) \ -I$(top_srcdir)/plugin/plugingizmo \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/plugingui \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin \ @@ -111,7 +113,7 @@ drumgizmo_vst_la_LDFLAGS = -shared -module -avoid-version \ drumgizmo_vst_la_LIBADD = \ vst/libvstsdk.la \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in index 2c2055c..ad47bcc 100644 --- a/plugin/Makefile.mingw32.in +++ b/plugin/Makefile.mingw32.in @@ -59,66 +59,70 @@ DG_CFLAGS = -I@top_srcdir@ -I@top_srcdir@/src \ GUI_SRC = \ @top_srcdir@/plugingui/abouttab.cc \ @top_srcdir@/plugingui/bleedcontrolframecontent.cc \ - @top_srcdir@/plugingui/button.cc \ - @top_srcdir@/plugingui/button_base.cc \ - @top_srcdir@/plugingui/checkbox.cc \ - @top_srcdir@/plugingui/colour.cc \ - @top_srcdir@/plugingui/combobox.cc \ - @top_srcdir@/plugingui/dialog.cc \ @top_srcdir@/plugingui/diskstreamingframecontent.cc \ @top_srcdir@/plugingui/drumkitframecontent.cc \ @top_srcdir@/plugingui/drumkittab.cc \ - @top_srcdir@/plugingui/eventhandler.cc \ @top_srcdir@/plugingui/filebrowser.cc \ - @top_srcdir@/plugingui/font.cc \ - @top_srcdir@/plugingui/frame.cc \ - @top_srcdir@/plugingui/helpbutton.cc \ - @top_srcdir@/plugingui/humanizerframecontent.cc \ @top_srcdir@/plugingui/humaniservisualiser.cc \ - @top_srcdir@/plugingui/image.cc \ - @top_srcdir@/plugingui/imagecache.cc \ - @top_srcdir@/plugingui/knob.cc \ - @top_srcdir@/plugingui/label.cc \ - @top_srcdir@/plugingui/layout.cc \ - @top_srcdir@/plugingui/led.cc \ - @top_srcdir@/plugingui/lineedit.cc \ - @top_srcdir@/plugingui/listbox.cc \ - @top_srcdir@/plugingui/listboxbasic.cc \ - @top_srcdir@/plugingui/listboxthin.cc \ + @top_srcdir@/plugingui/humanizerframecontent.cc \ @top_srcdir@/plugingui/maintab.cc \ @top_srcdir@/plugingui/mainwindow.cc \ - @top_srcdir@/plugingui/nativewindow_win32.cc \ - @top_srcdir@/plugingui/painter.cc \ - @top_srcdir@/plugingui/pixelbuffer.cc \ @top_srcdir@/plugingui/pluginconfig.cc \ - @top_srcdir@/plugingui/powerbutton.cc \ @top_srcdir@/plugingui/powerwidget.cc \ - @top_srcdir@/plugingui/progressbar.cc \ @top_srcdir@/plugingui/resamplingframecontent.cc \ - @top_srcdir@/plugingui/resource.cc \ @top_srcdir@/plugingui/sampleselectionframecontent.cc \ - @top_srcdir@/plugingui/scrollbar.cc \ - @top_srcdir@/plugingui/slider.cc \ - @top_srcdir@/plugingui/stackedwidget.cc \ @top_srcdir@/plugingui/statusframecontent.cc \ - @top_srcdir@/plugingui/tabbutton.cc \ - @top_srcdir@/plugingui/tabwidget.cc \ - @top_srcdir@/plugingui/textedit.cc \ - @top_srcdir@/plugingui/texture.cc \ - @top_srcdir@/plugingui/texturedbox.cc \ @top_srcdir@/plugingui/timingframecontent.cc \ - @top_srcdir@/plugingui/toggle.cc \ - @top_srcdir@/plugingui/tooltip.cc \ - @top_srcdir@/plugingui/uitranslation.cc \ - @top_srcdir@/plugingui/utf8.cc \ - @top_srcdir@/plugingui/verticalline.cc \ @top_srcdir@/plugingui/visualizerframecontent.cc \ @top_srcdir@/plugingui/voicelimitframecontent.cc \ - @top_srcdir@/plugingui/widget.cc \ - @top_srcdir@/plugingui/window.cc \ - @top_srcdir@/plugingui/lodepng/lodepng.cpp +\ + @top_srcdir@/dggui/button.cc \ + @top_srcdir@/dggui/button_base.cc \ + @top_srcdir@/dggui/checkbox.cc \ + @top_srcdir@/dggui/colour.cc \ + @top_srcdir@/dggui/combobox.cc \ + @top_srcdir@/dggui/dialog.cc \ + @top_srcdir@/dggui/eventhandler.cc \ + @top_srcdir@/dggui/font.cc \ + @top_srcdir@/dggui/frame.cc \ + @top_srcdir@/dggui/helpbutton.cc \ + @top_srcdir@/dggui/image.cc \ + @top_srcdir@/dggui/imagecache.cc \ + @top_srcdir@/dggui/knob.cc \ + @top_srcdir@/dggui/label.cc \ + @top_srcdir@/dggui/layout.cc \ + @top_srcdir@/dggui/led.cc \ + @top_srcdir@/dggui/lineedit.cc \ + @top_srcdir@/dggui/listbox.cc \ + @top_srcdir@/dggui/listboxbasic.cc \ + @top_srcdir@/dggui/listboxthin.cc \ + @top_srcdir@/dggui/painter.cc \ + @top_srcdir@/dggui/pixelbuffer.cc \ + @top_srcdir@/dggui/powerbutton.cc \ + @top_srcdir@/dggui/progressbar.cc \ + @top_srcdir@/dggui/rc_data.cc \ + @top_srcdir@/dggui/resource.cc \ + @top_srcdir@/dggui/scrollbar.cc \ + @top_srcdir@/dggui/slider.cc \ + @top_srcdir@/dggui/stackedwidget.cc \ + @top_srcdir@/dggui/tabbutton.cc \ + @top_srcdir@/dggui/tabwidget.cc \ + @top_srcdir@/dggui/textedit.cc \ + @top_srcdir@/dggui/texture.cc \ + @top_srcdir@/dggui/texturedbox.cc \ + @top_srcdir@/dggui/toggle.cc \ + @top_srcdir@/dggui/tooltip.cc \ + @top_srcdir@/dggui/uitranslation.cc \ + @top_srcdir@/dggui/utf8.cc \ + @top_srcdir@/dggui/verticalline.cc \ + @top_srcdir@/dggui/widget.cc \ + @top_srcdir@/dggui/window.cc \ +\ + @top_srcdir@/dggui/lodepng/lodepng.cpp \ + @top_srcdir@/dggui/nativewindow_win32.cc + -GUI_CPPFLAGS=-I@top_srcdir@/plugingui/ -DUSE_THREAD @GUI_CPPFLAGS@ +GUI_CPPFLAGS=-I@top_srcdir@/plugingui/ -I@top_srcdir@/ -DUSE_THREAD @GUI_CPPFLAGS@ GUI_LIBS=@GUI_LIBS@ DBG_SRC = \ @@ -186,9 +190,9 @@ NLS_RES = \ all: (cd @top_srcdir@/plugingui/locale; msgfmt -c -v -o da.mo da.po) (cd @top_srcdir@/plugingui/locale; msgfmt -c -v -o fr.mo fr.po) - g++ -I@top_srcdir@/getoptpp @top_srcdir@/plugingui/rcgen.cc -o @top_srcdir@/plugingui/rcgen - @top_srcdir@/plugingui/rcgen -s @top_srcdir@/plugingui/ -s @top_builddir@/plugingui/ $(RES) $(NLS_RES) -o @top_srcdir@/plugingui/resource_data.cc - g++ $(CXXFLAGS) @top_srcdir@/plugingui/resource_data.cc -c + g++ -I@top_srcdir@/getoptpp @top_srcdir@/dggui/rcgentool.cc -o @top_srcdir@/dggui/rcgen + @top_srcdir@/dggui/rcgen -s @top_srcdir@/dggui/ -s @top_builddir@/plugingui/ $(RES) $(NLS_RES) -o @top_srcdir@/plugingui/resource_data.cc + g++ $(CXXFLAGS) -I@top_srcdir@ @top_srcdir@/plugingui/resource_data.cc -c gcc $(CFLAGS) $(DBG_CFLAGS) @top_srcdir@/hugin/hugin.c -c gcc $(CFLAGS) $(DBG_CFLAGS) @top_srcdir@/hugin/hugin_syslog.c -c g++ $(LDFLAGS) $(CXXFLAGS) -std=c++11 -static -static-libgcc -O2 -g -Wall $(DBG_CFLAGS) $(DG_CFLAGS) $(DG_LIBS) $(VST_CFLAGS) hugin.o hugin_syslog.o resource_data.o $(DG_SRC) $(VST_SRC) ${SRC} ${GUI_SRC} ${GUI_CPPFLAGS} $(GUI_LIBS) $(SNDFILE_CFLAGS) $(SNDFILE_LIBS) -latomic -shared -Wl,-retain-symbols-file -Wl,drumgizmo_vst.sym -o drumgizmo_vst.dll -Wl,--out-implib,libdrumgizmo_vst.a diff --git a/plugin/drumgizmo_plugin.h b/plugin/drumgizmo_plugin.h index 78a74dc..4ecf489 100644 --- a/plugin/drumgizmo_plugin.h +++ b/plugin/drumgizmo_plugin.h @@ -39,14 +39,14 @@ #endif #include -#include #include #include #include -#include -#include -#include +#include +#include +#include +#include class DrumGizmoPlugin #ifdef LV2 diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index ab2e076..706b3c9 100644 --- a/plugingui/Makefile.am +++ b/plugingui/Makefile.am @@ -1,8 +1,8 @@ SUBDIRS = locale DISTDIRS = locale -noinst_PROGRAMS = plugingui rcgen -noinst_LTLIBRARIES = libdggui.la +noinst_PROGRAMS = plugingui +noinst_LTLIBRARIES = libplugingui.la # If you add a file here, remember to add it to plugin/Makefile.mingw32.in RES = \ @@ -70,14 +70,14 @@ BUILT_SOURCES = \ resource_data.cc \ $(NLS_RES) -resource_data.cc: rcgen$(EXEEXT) $(RES) $(NLS_RES) - $(rcgen_verbose)./rcgen$(EXEEXT) -s $(top_srcdir)/plugingui/ -s $(top_builddir)/plugingui/ -o $@ $(RES) $(NLS_RES) +resource_data.cc: $(top_builddir)/dggui/rcgen$(EXEEXT) $(RES) $(NLS_RES) + $(rcgen_verbose)$(top_builddir)/dggui/rcgen$(EXEEXT) -s $(top_srcdir)/plugingui/ -s $(top_builddir)/plugingui/ -o $@ $(RES) $(NLS_RES) CLEANFILES = \ resource_data.cc \ $(NLS_RES) -libdggui_la_CPPFLAGS = \ +libplugingui_la_CPPFLAGS = \ $(DEBUG_FLAGS) \ -I$(top_srcdir) \ $(GUI_CPPFLAGS) \ @@ -90,205 +90,64 @@ libdggui_la_CPPFLAGS = \ -DLODEPNG_NO_COMPILE_ERROR_TEXT \ -DLODEPNG_NO_COMPILE_CPP -libdggui_la_CFLAGS = +libplugingui_la_CFLAGS = -libdggui_la_LIBTOOLFLAGS=--tag=CC +libplugingui_la_LIBTOOLFLAGS=--tag=CC -libdggui_la_LIBADD = \ +libplugingui_la_LIBADD = \ + $(top_builddir)/dggui/libdggui.la \ $(GUI_LIBS) $(PTHREAD_LIBS) # If you add a file here, remember to add it to plugin/Makefile.mingw32.in GUI_SRC = \ abouttab.cc \ bleedcontrolframecontent.cc \ - button.cc \ - button_base.cc \ - checkbox.cc \ - colour.cc \ - combobox.cc \ - dialog.cc \ diskstreamingframecontent.cc \ drumkitframecontent.cc \ drumkittab.cc \ - eventhandler.cc \ filebrowser.cc \ - font.cc \ - frame.cc \ - helpbutton.cc \ - humanizerframecontent.cc \ humaniservisualiser.cc \ - image.cc \ - imagecache.cc \ - knob.cc \ - label.cc \ - layout.cc \ - led.cc \ - lineedit.cc \ - listbox.cc \ - listboxbasic.cc \ - listboxthin.cc \ + humanizerframecontent.cc \ maintab.cc \ mainwindow.cc \ - painter.cc \ - pixelbuffer.cc \ pluginconfig.cc \ - powerbutton.cc \ powerwidget.cc \ - progressbar.cc \ resamplingframecontent.cc \ - resource.cc \ sampleselectionframecontent.cc \ - scrollbar.cc \ - slider.cc \ - stackedwidget.cc \ statusframecontent.cc \ - tabbutton.cc \ - tabwidget.cc \ - textedit.cc \ - texture.cc \ - texturedbox.cc \ timingframecontent.cc \ - toggle.cc \ - tooltip.cc \ - uitranslation.cc \ - utf8.cc \ - verticalline.cc \ visualizerframecontent.cc \ - voicelimitframecontent.cc \ - widget.cc \ - window.cc + voicelimitframecontent.cc GUI_HDR = \ abouttab.h \ bleedcontrolframecontent.h \ - button.h \ - button_base.h \ - canvas.h \ - checkbox.h \ - colour.h \ - combobox.h \ - dialog.h \ diskstreamingframecontent.h \ - drawable.h \ drumkitframecontent.h \ drumkittab.h \ - eventhandler.h \ filebrowser.h \ - font.h \ - frame.h \ - guievent.h \ - helpbutton.h \ humaniservisualiser.h \ humanizerframecontent.h \ - image.h \ - imagecache.h \ - knob.h \ - label.h \ labeledcontrol.h \ - layout.h \ - led.h \ - lineedit.h \ - listbox.h \ - listboxbasic.h \ - listboxthin.h \ maintab.h \ mainwindow.h \ - nativewindow.h \ - nativewindow_cocoa.h \ - nativewindow_cocoa.mm \ - nativewindow_pugl.h \ - nativewindow_pugl.cc \ - nativewindow_win32.h \ - nativewindow_win32.cc \ - nativewindow_x11.h \ - nativewindow_x11.cc \ - painter.h \ - pixelbuffer.h \ pluginconfig.h \ - powerbutton.h \ powerwidget.h \ - progressbar.h \ resamplingframecontent.h \ - resource.h \ - resource_data.h \ sampleselectionframecontent.h \ - scrollbar.h \ - slider.h \ - stackedwidget.h \ statusframecontent.h \ - tabbutton.h \ - tabwidget.h \ - textedit.h \ - texture.h \ - texturedbox.h \ timingframecontent.h \ - toggle.h \ - tooltip.h \ - uitranslation.h \ - utf8.h \ - verticalline.h \ visualizerframecontent.h \ - voicelimitframecontent.h \ - widget.h \ - window.h + voicelimitframecontent.h -libdggui_la_SOURCES = \ - $(GUI_SRC) \ - lodepng/lodepng.cpp +libplugingui_la_SOURCES = \ + $(GUI_SRC) -nodist_libdggui_la_SOURCES = \ +nodist_libplugingui_la_SOURCES = \ $(top_builddir)/plugingui/resource_data.cc -if ENABLE_X11 -nodist_libdggui_la_SOURCES += \ - nativewindow_x11.cc -endif - -if ENABLE_WIN32 -nodist_libdggui_la_SOURCES += \ - nativewindow_win32.cc -endif - -if ENABLE_COCOA -nodist_libdggui_la_SOURCES += \ - nativewindow_cocoa.mm - -libdggui_la_OBJCXXFLAGS = \ - -fblocks -endif - -if ENABLE_PUGL_X11 -nodist_libdggui_la_SOURCES += \ - nativewindow_pugl.cc \ - $(top_srcdir)/pugl/pugl/pugl_x11.c - -libdggui_la_CPPFLAGS += \ - -I$(top_srcdir)/pugl - -libdggui_la_CFLAGS += \ - -std=c99 -endif - -if ENABLE_PUGL_WIN32 -nodist_libdggui_la_SOURCES += \ - nativewindow_pugl.cc \ - $(top_srcdir)/pugl/pugl/pugl_win.cpp - -libdggui_la_CPPFLAGS += \ - -I$(top_srcdir)/pugl -endif - -if ENABLE_PUGL_COCOA -nodist_libdggui_la_SOURCES += \ - nativewindow_pugl.cc \ - $(top_srcdir)/pugl/pugl/pugl_osx.m - -libdggui_la_CPPFLAGS += \ - -I$(top_srcdir)/pugl -endif - plugingui_LDADD = \ - libdggui.la \ + libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la @@ -297,6 +156,7 @@ plugingui_CXXFLAGS = \ $(GUI_CPPFLAGS) \ $(SNDFILE_CXXFLAGS) \ $(PTHREAD_CFLAGS) \ + -I$(top_srcdir) \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin @@ -306,11 +166,6 @@ plugingui_SOURCES = \ testmain.cc \ $(top_srcdir)/hugin/hugin.c -rcgen_LDFLAGS = -static -rcgen_CXXFLAGS = -I$(top_srcdir)/getoptpp -rcgen_SOURCES = \ - rcgen.cc - EXTRA_DIST = \ $(RES) \ $(GUI_HDR) diff --git a/plugingui/abouttab.cc b/plugingui/abouttab.cc index 384c815..094ed5d 100644 --- a/plugingui/abouttab.cc +++ b/plugingui/abouttab.cc @@ -29,7 +29,7 @@ #include #include -#include "utf8.h" +#include namespace { diff --git a/plugingui/abouttab.h b/plugingui/abouttab.h index ed06b1d..99653d1 100644 --- a/plugingui/abouttab.h +++ b/plugingui/abouttab.h @@ -26,9 +26,9 @@ */ #pragma once -#include "widget.h" -#include "resource.h" -#include "textedit.h" +#include +#include +#include #include diff --git a/plugingui/bleedcontrolframecontent.h b/plugingui/bleedcontrolframecontent.h index 78733c0..d4f6c2e 100644 --- a/plugingui/bleedcontrolframecontent.h +++ b/plugingui/bleedcontrolframecontent.h @@ -25,9 +25,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "label.h" -#include "slider.h" -#include "widget.h" +#include +#include +#include struct Settings; class SettingsNotifier; diff --git a/plugingui/button.cc b/plugingui/button.cc deleted file mode 100644 index 30bda82..0000000 --- a/plugingui/button.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * button.cc - * - * Sun Oct 9 13:01:56 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "button.h" - -#include "painter.h" - -#include -#include - -namespace GUI -{ - -Button::Button(Widget* parent) - : ButtonBase(parent) -{ -} - -Button::~Button() -{ -} - -void Button::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - p.clear(); - - int padTop = 3; - int padLeft = 0; - int padTextTop = 3; - - int w = width(); - int h = height(); - if(w == 0 || h == 0) - { - return; - } - - if (enabled) { - switch(draw_state) - { - case State::Up: - box_up.setSize(w - padLeft, h - padTop); - p.drawImage(padLeft, padTop, box_up); - break; - - case State::Down: - box_down.setSize(w - padLeft, h - padTop); - p.drawImage(padLeft, padTop, box_down); - break; - } - } - else { - box_grey.setSize(w - padLeft, h - padTop); - p.drawImage(padLeft, padTop, box_grey); - - p.setColour(Colour(0.55)); - } - - auto x = padLeft + (width() - font.textWidth(text)) / 2; - auto y = padTop + padTextTop + font.textHeight(text); - p.drawText(x, y, font, text, enabled); -} - -} // GUI:: diff --git a/plugingui/button.h b/plugingui/button.h deleted file mode 100644 index 52f22e2..0000000 --- a/plugingui/button.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * button.h - * - * Sun Oct 9 13:01:56 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "button_base.h" -#include "font.h" -#include "texturedbox.h" - -namespace GUI { - -class Button - : public ButtonBase { -public: - Button(Widget* parent); - virtual ~Button(); - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* e) override; - -private: - TexturedBox box_up{getImageCache(), ":resources/pushbutton.png", - 0, 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 6, 12, 9}; // dy1, dy2, dy3 - - TexturedBox box_down{getImageCache(), ":resources/pushbutton.png", - 15, 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 6, 12, 9}; // dy1, dy2, dy3 - - TexturedBox box_grey{getImageCache(), ":resources/pushbutton.png", - 30, 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 6, 12, 9}; // dy1, dy2, dy3 - - Font font{":resources/fontemboss.png"}; -}; - -} // GUI:: diff --git a/plugingui/button_base.cc b/plugingui/button_base.cc deleted file mode 100644 index bf441f5..0000000 --- a/plugingui/button_base.cc +++ /dev/null @@ -1,116 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * button_base.cc - * - * Sat Apr 15 21:45:30 CEST 2017 - * Copyright 2017 AndrĂ© Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "button_base.h" - -namespace GUI { - -ButtonBase::ButtonBase(Widget *parent) - : Widget(parent) - , draw_state(State::Up) - , button_state(State::Up) -{ -} - -ButtonBase::~ButtonBase() -{ -} - -void ButtonBase::buttonEvent(ButtonEvent* buttonEvent) -{ - // Ignore everything except left clicks. - if(!enabled || buttonEvent->button != MouseButton::left) - { - return; - } - - if(buttonEvent->direction == Direction::down) - { - draw_state = State::Down; - button_state = State::Down; - in_button = true; - redraw(); - } - - if(buttonEvent->direction == Direction::up) - { - draw_state = State::Up; - button_state = State::Up; - redraw(); - if(in_button) - { - clicked(); - clickNotifier(); - } - } -} - -void ButtonBase::setText(const std::string& text) -{ - this->text = text; - redraw(); -} - -void ButtonBase::setEnabled(bool enabled) -{ - this->enabled = enabled; - redraw(); -} - -bool ButtonBase::isEnabled() const -{ - return enabled; -} - -void ButtonBase::mouseLeaveEvent() -{ - if (!enabled) { - return; - } - - in_button = false; - if(button_state == State::Down) - { - draw_state = State::Up; - redraw(); - } -} - -void ButtonBase::mouseEnterEvent() -{ - if (!enabled) { - return; - } - - in_button = true; - if(button_state == State::Down) - { - draw_state = State::Down; - redraw(); - } -} - -} // GUI:: diff --git a/plugingui/button_base.h b/plugingui/button_base.h deleted file mode 100644 index c872d9b..0000000 --- a/plugingui/button_base.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * button_base.h - * - * Sat Apr 15 21:45:30 CEST 2017 - * Copyright 2017 AndrĂ© Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include - -#include "widget.h" - -namespace GUI { - -class ButtonBase - : public Widget -{ -public: - ButtonBase(Widget* parent); - virtual ~ButtonBase(); - - // From Widget: - bool isFocusable() override { return true; } - bool catchMouse() override { return true; } - - void setText(const std::string& text); - - void setEnabled(bool enabled); - bool isEnabled() const; - - Notifier<> clickNotifier; - -protected: - virtual void clicked() {} - - // From Widget: - virtual void repaintEvent(RepaintEvent* e) override {}; - virtual void buttonEvent(ButtonEvent* e) override; - virtual void mouseLeaveEvent() override; - virtual void mouseEnterEvent() override; - - bool enabled{true}; - bool in_button{false}; - - enum class State { - Up, - Down - }; - - std::string text; - - State draw_state{State::Up}; - State button_state{State::Up}; -}; - -} // GUI:: diff --git a/plugingui/canvas.h b/plugingui/canvas.h deleted file mode 100644 index d6e8f99..0000000 --- a/plugingui/canvas.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * canvas.h - * - * Sun Sep 4 13:03:51 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "pixelbuffer.h" - -namespace GUI -{ - -//! Abstract class that can be used by the Painter to draw on. -class Canvas -{ -public: - virtual ~Canvas() = default; - - //! @returns a reference to the pixel buffer. - virtual PixelBufferAlpha& getPixelBuffer() = 0; -}; - -} // GUI:: diff --git a/plugingui/checkbox.cc b/plugingui/checkbox.cc deleted file mode 100644 index f3601bd..0000000 --- a/plugingui/checkbox.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * checkbox.cc - * - * Sat Nov 26 15:07:44 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "checkbox.h" - -#include "painter.h" - -namespace GUI -{ - -CheckBox::CheckBox(Widget* parent) - : Toggle(parent) - , bg_on(getImageCache(), ":resources/switch_back_on.png") - , bg_off(getImageCache(), ":resources/switch_back_off.png") - , knob(getImageCache(), ":resources/switch_front.png") -{ -} - -void CheckBox::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - p.clear(); - p.drawImage(0, (knob.height() - bg_on.height()) / 2, state ? bg_on : bg_off); - - if(clicked) - { - p.drawImage((bg_on.width() - knob.width()) / 2 + 1, 0, knob); - return; - } - - if(state) - { - p.drawImage(bg_on.width() - 40 + 2, 0, knob); - } - else - { - p.drawImage(0, 0, knob); - } -} - -} // GUI:: diff --git a/plugingui/checkbox.h b/plugingui/checkbox.h deleted file mode 100644 index 6627304..0000000 --- a/plugingui/checkbox.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * checkbox.h - * - * Sat Nov 26 15:07:44 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "toggle.h" -#include "texture.h" - -namespace GUI { - -class CheckBox : public Toggle { -public: - CheckBox(Widget *parent); - virtual ~CheckBox() = default; - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - -private: - Texture bg_on; - Texture bg_off; - Texture knob; -}; - -} // GUI:: diff --git a/plugingui/colour.cc b/plugingui/colour.cc deleted file mode 100644 index 7fd649c..0000000 --- a/plugingui/colour.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * colour.cc - * - * Fri Oct 14 09:38:28 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "colour.h" - -#include - -namespace GUI -{ - -Colour::Colour() -{ -} - -Colour::Colour(float grey, float a) - : pixel({{(std::uint8_t)(grey * 255), - (std::uint8_t)(grey * 255), - (std::uint8_t)(grey * 255), - (std::uint8_t)(a * 255)}}) -{ -} - -Colour::Colour(float r, float g, float b, float a) - : pixel({{(std::uint8_t)(r * 255), - (std::uint8_t)(g * 255), - (std::uint8_t)(b * 255), - (std::uint8_t)(a * 255)}}) -{ -} - -Colour::Colour(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a) - : pixel({{r, g, b, a}}) -{ -} - -Colour::Colour(const Colour& other) - : pixel(other.pixel) -{ -} - -Colour& Colour::operator=(const Colour& other) -{ - pixel = other.pixel; - return *this; -} - -bool Colour::operator==(const Colour& other) const -{ - return pixel[0] == other.pixel[0] && - pixel[1] == other.pixel[1] && - pixel[2] == other.pixel[2]; -} - -bool Colour::operator!=(const Colour& other) const -{ - return !(*this == other); -} - -} // GUI:: diff --git a/plugingui/colour.h b/plugingui/colour.h deleted file mode 100644 index 0bc8659..0000000 --- a/plugingui/colour.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * colour.h - * - * Fri Oct 14 09:38:28 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -namespace GUI -{ - -class Colour -{ -public: - Colour(); - Colour(float grey, float alpha = 1.0f); - Colour(float red, float green, float blue, float alpha = 1.0f); - Colour(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a); - Colour(const Colour& other); - - Colour& operator=(const Colour& other); - - bool operator==(const Colour& other) const; - bool operator!=(const Colour& other) const; - - inline std::uint8_t red() const { return pixel[0]; } - inline std::uint8_t green() const { return pixel[1]; } - inline std::uint8_t blue() const { return pixel[2]; } - inline std::uint8_t alpha() const { return pixel[3]; } - - std::uint8_t* data() { return pixel.data(); } - const std::uint8_t* data() const { return pixel.data(); } - -private: - std::array pixel{{255, 255, 255, 255}}; -}; - -} // GUI:: diff --git a/plugingui/combobox.cc b/plugingui/combobox.cc deleted file mode 100644 index aa2058e..0000000 --- a/plugingui/combobox.cc +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * combobox.cc - * - * Sun Mar 10 19:04:50 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "combobox.h" - -#include "painter.h" -#include "font.h" - -#include - -#define BORDER 10 - -namespace GUI -{ - -void ComboBox::listboxSelectHandler() -{ - ButtonEvent buttonEvent; - buttonEvent.direction = Direction::down; - this->buttonEvent(&buttonEvent); -} - -ComboBox::ComboBox(Widget* parent) - : Widget(parent) - , listbox(parent) -{ - CONNECT(&listbox, selectionNotifier, this, &ComboBox::listboxSelectHandler); - CONNECT(&listbox, clickNotifier, this, &ComboBox::listboxSelectHandler); - - listbox.hide(); -} - -ComboBox::~ComboBox() -{ -} - -void ComboBox::addItem(std::string name, std::string value) -{ - listbox.addItem(name, value); -} - -void ComboBox::clear() -{ - listbox.clear(); - redraw(); -} - -bool ComboBox::selectItem(int index) -{ - listbox.selectItem(index); - redraw(); - return true; -} - -std::string ComboBox::selectedName() -{ - return listbox.selectedName(); -} - -std::string ComboBox::selectedValue() -{ - return listbox.selectedValue(); -} - -static void drawArrow(Painter &p, int x, int y, int w, int h) -{ - p.drawLine(x, y, x+(w/2), y+h); - p.drawLine(x+(w/2), y+h, x+w, y); - - y++; - p.drawLine(x, y, x+(w/2), y+h); - p.drawLine(x+(w/2), y+h, x+w, y); -} - -void ComboBox::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - std::string _text = selectedName(); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) - { - return; - } - - box.setSize(w, h); - p.drawImage(0, 0, box); - - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0/255.0f, 1.0f)); - p.drawText(BORDER - 4 + 3, height()/2+5 + 1 + 1, font, _text); - - // p.setColour(Colour(1, 1, 1)); - // p.drawText(BORDER - 4, (height()+font.textHeight()) / 2 + 1, font, _text); - - //int n = height() / 2; - - // p.drawLine(width() - n - 6, 1 + 6, width() - 1 - 6, 1 + 6); - { - int w = 10; - int h = 6; - drawArrow(p, width() - 6 - 4 - w, (height() - h) / 2, w, h); - p.drawLine(width() - 6 - 4 - w - 4, 7, - width() - 6 - 4 - w - 4, height() - 8); - } -} - -void ComboBox::scrollEvent(ScrollEvent* scrollEvent) -{ - /* - scroll_offset += e->delta; - if(scroll_offset < 0) - { - scroll_offset = 0; - } - if(scroll_offset > (items.size() - 1)) - { - scroll_offset = (items.size() - 1); - } - redraw(); - */ -} - -void ComboBox::keyEvent(KeyEvent* keyEvent) -{ - if(keyEvent->direction != Direction::up) - { - return; - } - - /* - switch(keyEvent->keycode) { - case Key::up: - { - selected--; - if(selected < 0) - { - selected = 0; - } - if(selected < scroll_offset) - { - scroll_offset = selected; - if(scroll_offset < 0) - { - scroll_offset = 0; - } - } - } - break; - case Key::down: - { - // Number of items that can be displayed at a time. - int numitems = height() / (font.textHeight() + padding); - - selected++; - if(selected > (items.size() - 1)) - { - selected = (items.size() - 1); - } - if(selected > (scroll_offset + numitems - 1)) - { - scroll_offset = selected - numitems + 1; - if(scroll_offset > (items.size() - 1)) - { - scroll_offset = (items.size() - 1); - } - } - } - break; - case Key::home: - selected = 0; - break; - case Key::end: - selected = items.size() - 1; - break; - default: - break; - } - - redraw(); - */ -} - -void ComboBox::buttonEvent(ButtonEvent* buttonEvent) -{ - // Ignore everything except left clicks. - if(buttonEvent->button != MouseButton::left) - { - return; - } - - if(buttonEvent->direction != Direction::down) - { - return; - } - - if(!listbox.visible()) - { - listbox.resize(width() - 10, 100); - listbox.move(x() + 5, y() + height() - 7); - } - else - { - valueChangedNotifier(listbox.selectedName(), listbox.selectedValue()); - } - - listbox.setVisible(!listbox.visible()); -} - -} // GUI:: diff --git a/plugingui/combobox.h b/plugingui/combobox.h deleted file mode 100644 index 778d54c..0000000 --- a/plugingui/combobox.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * combobox.h - * - * Sun Mar 10 19:04:50 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include "widget.h" -#include "font.h" -#include "listboxthin.h" -#include "painter.h" -#include "texturedbox.h" - -namespace GUI -{ - -class ComboBox - : public Widget -{ -public: - ComboBox(Widget* parent); - virtual ~ComboBox(); - - void addItem(std::string name, std::string value); - - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); - - // From Widget: - bool isFocusable() override { return true; } - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - virtual void buttonEvent(ButtonEvent* buttonEvent) override; - virtual void scrollEvent(ScrollEvent* scrollEvent) override; - virtual void keyEvent(KeyEvent* keyEvent) override; - - Notifier valueChangedNotifier; - -private: - TexturedBox box{getImageCache(), ":resources/widget.png", - 0, 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 7, 63, 7}; // dy1, dy2, dy3 - - void listboxSelectHandler(); - - Font font; - ListBoxThin listbox; -}; - -} // GUI:: diff --git a/plugingui/dialog.cc b/plugingui/dialog.cc deleted file mode 100644 index 9ba579d..0000000 --- a/plugingui/dialog.cc +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * dialog.cc - * - * Sun Apr 16 10:31:04 CEST 2017 - * Copyright 2017 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "dialog.h" - -namespace GUI -{ - -Dialog::Dialog(Widget* parent, bool modal) - : parent(parent) -{ - parent->window()->eventHandler()->registerDialog(this); - setModal(modal); -} - -Dialog::~Dialog() -{ - parent->window()->eventHandler()->unregisterDialog(this); -} - -void Dialog::setModal(bool modal) -{ - is_modal = modal; -} - -bool Dialog::isModal() const -{ - return is_modal; -} - -} // GUI:: diff --git a/plugingui/dialog.h b/plugingui/dialog.h deleted file mode 100644 index 1b0c6da..0000000 --- a/plugingui/dialog.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * dialog.h - * - * Sun Apr 16 10:31:04 CEST 2017 - * Copyright 2017 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "window.h" - -namespace GUI -{ - -//! This class is used the base window for pop-up dialogs, such as a file -//! browser. -class Dialog - : public Window -{ -public: - //! - The dialog is placed near the parent window. - //! - The parent window event handler will call the dialog event handler - //! - While the dialog is visible, all mouse click and keyboard events - //! are ignored by the parent event handler. - //! - The Dialog registers itself in the parent event handler when contructed - //! and removes itself when destructed. - //! - The parent event handler will delete all registered Dialogs when itself - //! deleted. - Dialog(Widget* parent, bool modal = false); - - ~Dialog(); - - //! Change modality. - void setModal(bool modal); - - //! Get current modality state. - bool isModal() const; - -private: - bool is_modal{false}; - Widget* parent{nullptr}; -}; - -} // GUI:: diff --git a/plugingui/diskstreamingframecontent.h b/plugingui/diskstreamingframecontent.h index eabc6e2..1f7ab39 100644 --- a/plugingui/diskstreamingframecontent.h +++ b/plugingui/diskstreamingframecontent.h @@ -26,10 +26,10 @@ */ #pragma once -#include "button.h" -#include "label.h" -#include "slider.h" -#include "widget.h" +#include +#include +#include +#include struct Settings; class SettingsNotifier; diff --git a/plugingui/drawable.h b/plugingui/drawable.h deleted file mode 100644 index 95492d6..0000000 --- a/plugingui/drawable.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * drawable.h - * - * Sat Jun 4 21:39:38 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -namespace GUI -{ - -class Colour; - -class Drawable -{ -public: - virtual ~Drawable() = default; - - virtual std::size_t width() const = 0; - virtual std::size_t height() const = 0; - - virtual const Colour& getPixel(std::size_t x, std::size_t y) const = 0; - virtual const std::uint8_t* line(std::size_t y, - std::size_t x_offset = 0) const = 0; - - virtual bool hasAlpha() const = 0; -}; - -} // GUI:: diff --git a/plugingui/drumkitframecontent.cc b/plugingui/drumkitframecontent.cc index 7dd2234..2bdff7a 100644 --- a/plugingui/drumkitframecontent.cc +++ b/plugingui/drumkitframecontent.cc @@ -28,7 +28,6 @@ #include -#include "label.h" #include "pluginconfig.h" #include diff --git a/plugingui/drumkitframecontent.h b/plugingui/drumkitframecontent.h index 921927d..3661d8e 100644 --- a/plugingui/drumkitframecontent.h +++ b/plugingui/drumkitframecontent.h @@ -28,11 +28,12 @@ #include -#include "button.h" -#include "label.h" -#include "lineedit.h" -#include "progressbar.h" -#include "widget.h" +#include +#include +#include +#include +#include + #include "filebrowser.h" namespace GUI diff --git a/plugingui/drumkittab.cc b/plugingui/drumkittab.cc index 8d85f1e..46c448e 100644 --- a/plugingui/drumkittab.cc +++ b/plugingui/drumkittab.cc @@ -31,7 +31,9 @@ #include #include "cpp11fix.h" // required for c++11 -#include "painter.h" + +#include + #include "settings.h" #include diff --git a/plugingui/drumkittab.h b/plugingui/drumkittab.h index a14a9c5..3243fba 100644 --- a/plugingui/drumkittab.h +++ b/plugingui/drumkittab.h @@ -32,9 +32,9 @@ #include -#include "image.h" -#include "label.h" -#include "widget.h" +#include +#include +#include struct Settings; class SettingsNotifier; diff --git a/plugingui/eventhandler.cc b/plugingui/eventhandler.cc deleted file mode 100644 index fd333b8..0000000 --- a/plugingui/eventhandler.cc +++ /dev/null @@ -1,297 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * eventhandler.cc - * - * Sun Oct 9 18:58:29 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "eventhandler.h" - -#include "window.h" -#include "painter.h" -#include "dialog.h" - -namespace GUI -{ - -EventHandler::EventHandler(NativeWindow& nativeWindow, Window& window) - : window(window) - , nativeWindow(nativeWindow) - , lastWasDoubleClick(false) -{} - -bool EventHandler::hasEvent() -{ - return !events.empty(); -} - -bool EventHandler::queryNextEventType(EventType type) -{ - return !events.empty() && - (events.front()->type() == type); -} - -std::shared_ptr EventHandler::getNextEvent() -{ - if(events.empty()) - { - return nullptr; - } - - auto event = events.front(); - events.pop_front(); - return event; -} - -void EventHandler::processEvents() -{ - bool block_interaction{false}; - for(auto dialog : dialogs) - { - // Check if the dialog nativewindow (not the contained widget) is visible - if(dialog->native->visible()) - { - block_interaction |= dialog->isModal(); - dialog->eventHandler()->processEvents(); - } - } - - events = nativeWindow.getEvents(); - - while(hasEvent()) - { - auto event = getNextEvent(); - - if(event == nullptr) - { - continue; - } - - switch(event->type()) { - case EventType::repaint: - break; - - case EventType::move: - { - auto moveEvent = static_cast(event.get()); - window.moved(moveEvent->x, moveEvent->y); - } - break; - - case EventType::resize: - { - auto resizeEvent = static_cast(event.get()); - if((resizeEvent->width != window.width()) || - (resizeEvent->height != window.height())) - { - window.resized(resizeEvent->width, resizeEvent->height); - } - } - break; - - case EventType::mouseMove: - { - // Skip all consecutive mouse move events and handle only the last one. - while(queryNextEventType(EventType::mouseMove)) - { - event = getNextEvent(); - } - - auto moveEvent = static_cast(event.get()); - - auto widget = window.find(moveEvent->x, moveEvent->y); - auto oldwidget = window.mouseFocus(); - if(widget != oldwidget) - { - // Send focus leave to oldwidget - if(oldwidget) - { - oldwidget->mouseLeaveEvent(); - } - - // Send focus enter to widget - if(widget) - { - widget->mouseEnterEvent(); - } - - window.setMouseFocus(widget); - } - - if(window.buttonDownFocus()) - { - auto widget = window.buttonDownFocus(); - moveEvent->x -= widget->translateToWindowX(); - moveEvent->y -= widget->translateToWindowY(); - - window.buttonDownFocus()->mouseMoveEvent(moveEvent); - break; - } - - if(widget) - { - moveEvent->x -= widget->translateToWindowX(); - moveEvent->y -= widget->translateToWindowY(); - widget->mouseMoveEvent(moveEvent); - } - } - break; - - case EventType::button: - { - if(block_interaction) - { - continue; - } - - auto buttonEvent = static_cast(event.get()); - if(lastWasDoubleClick && (buttonEvent->direction == Direction::down)) - { - lastWasDoubleClick = false; - continue; - } - - lastWasDoubleClick = buttonEvent->doubleClick; - - auto widget = window.find(buttonEvent->x, buttonEvent->y); - - if(window.buttonDownFocus()) - { - if(buttonEvent->direction == Direction::up) - { - auto widget = window.buttonDownFocus(); - buttonEvent->x -= widget->translateToWindowX(); - buttonEvent->y -= widget->translateToWindowY(); - - widget->buttonEvent(buttonEvent); - window.setButtonDownFocus(nullptr); - break; - } - } - - if(widget) - { - buttonEvent->x -= widget->translateToWindowX(); - buttonEvent->y -= widget->translateToWindowY(); - - widget->buttonEvent(buttonEvent); - - if((buttonEvent->direction == Direction::down) && - widget->catchMouse()) - { - window.setButtonDownFocus(widget); - } - - if(widget->isFocusable()) - { - window.setKeyboardFocus(widget); - } - } - } - break; - - case EventType::scroll: - { - if(block_interaction) - { - continue; - } - - auto scrollEvent = static_cast(event.get()); - - auto widget = window.find(scrollEvent->x, scrollEvent->y); - if(widget) - { - scrollEvent->x -= widget->translateToWindowX(); - scrollEvent->y -= widget->translateToWindowY(); - - widget->scrollEvent(scrollEvent); - } - } - break; - - case EventType::key: - { - if(block_interaction) - { - continue; - } - - // TODO: Filter out multiple arrow events. - - auto keyEvent = static_cast(event.get()); - if(window.keyboardFocus()) - { - window.keyboardFocus()->keyEvent(keyEvent); - } - } - break; - - case EventType::close: - if(block_interaction) - { - continue; - } - - closeNotifier(); - break; - - case EventType::mouseEnter: - { - auto enterEvent = static_cast(event.get()); - auto widget = window.find(enterEvent->x, enterEvent->y); - if(widget) - { - widget->mouseEnterEvent(); - } - } - break; - - case EventType::mouseLeave: - { - auto widget = window.mouseFocus(); - if(widget) - { - widget->mouseLeaveEvent(); - } - } - break; - } - } - - // Probe window and children to redraw as needed. - // NOTE: This method will invoke native->redraw() if a redraw is needed. - window.updateBuffer(); -} - -void EventHandler::registerDialog(Dialog* dialog) -{ - dialogs.push_back(dialog); -} - -void EventHandler::unregisterDialog(Dialog* dialog) -{ - dialogs.remove(dialog); -} - - -} // GUI:: diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h deleted file mode 100644 index 8d6f492..0000000 --- a/plugingui/eventhandler.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * eventhandler.h - * - * Sun Oct 9 18:58:29 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include -#include -#include - -#include "guievent.h" -#include "nativewindow.h" - -namespace GUI -{ - -class Window; -class Dialog; - -class EventHandler -{ -public: - EventHandler(NativeWindow& nativeWindow, Window& window); - - //! Process all events currently in the event queue. - void processEvents(); - - //! Query if any events are currently in the event queue. - bool hasEvent(); - - //! Query if the topmost event in the event queue is of type. - bool queryNextEventType(EventType type); - - //! Get a single event from the event queue. - //! \return A pointer to the event or nullptr if there are none. - std::shared_ptr getNextEvent(); - - void registerDialog(Dialog* dialog); - void unregisterDialog(Dialog* dialog); - - Notifier<> closeNotifier; - -private: - Window& window; - NativeWindow& nativeWindow; - - // Used to ignore mouse button release after a double click. - bool lastWasDoubleClick; - - EventQueue events; - - std::list dialogs; -}; - -} // GUI:: diff --git a/plugingui/filebrowser.cc b/plugingui/filebrowser.cc index 59daab4..9f322c8 100644 --- a/plugingui/filebrowser.cc +++ b/plugingui/filebrowser.cc @@ -26,8 +26,8 @@ */ #include "filebrowser.h" -#include "painter.h" -#include "button.h" +#include +#include #include #include diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h index bc7adb3..53a058d 100644 --- a/plugingui/filebrowser.h +++ b/plugingui/filebrowser.h @@ -30,12 +30,12 @@ #include #include -#include "dialog.h" -#include "button.h" -#include "listbox.h" -#include "lineedit.h" -#include "label.h" -#include "image.h" +#include +#include +#include +#include +#include +#include namespace GUI { diff --git a/plugingui/font.cc b/plugingui/font.cc deleted file mode 100644 index 0500e81..0000000 --- a/plugingui/font.cc +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * font.cc - * - * Sat Nov 12 11:13:41 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "font.h" - -#include - -namespace GUI -{ - -Font::Font(const std::string& fontfile) - : img_font(fontfile) -{ - std::size_t px = 0; - std::size_t c; - - for(c = 0; c < characters.size() && px < img_font.width(); ++c) - { - auto& character = characters[c]; - character.offset = px + 1; - - if(c > 0) - { - assert(character.offset >= characters[c - 1].offset); - characters[c - 1].width = character.offset - characters[c - 1].offset; - if(characters[c].offset != characters[c - 1].offset) - { - --characters[c - 1].width; - } - } - - ++px; - - while(px < img_font.width()) - { - auto& pixel = img_font.getPixel(px, 0); - - // Find next purple pixel in top row: - if((pixel.red() == 255) && (pixel.green() == 0) && - (pixel.blue() == 255) && (pixel.alpha() == 255)) - { - break; - } - - ++px; - } - - characters[c] = character; - } - - --c; - - assert(characters[c].offset >= characters[c - 1].offset); - characters[c - 1].width = characters[c].offset - characters[c - 1].offset; - if(characters[c].offset != characters[c - 1].offset) - { - --characters[c - 1].width; - } -} - -size_t Font::textWidth(const std::string& text) const -{ - size_t len = 0; - - for(unsigned char cha : text) - { - auto& character = characters[cha]; - len += character.width + spacing + character.post_bias; - } - - return len; -} - -size_t Font::textHeight(const std::string& text) const -{ - return img_font.height(); -} - -void Font::setLetterSpacing(int letterSpacing) -{ - spacing = letterSpacing; -} - -int Font::letterSpacing() const -{ - return spacing; -} - -PixelBufferAlpha *Font::render(const std::string& text) const -{ - PixelBufferAlpha *pb = - new PixelBufferAlpha(textWidth(text), textHeight(text)); - - int x_offset = 0; - for(std::size_t i = 0; i < text.length(); ++i) - { - unsigned char cha = text[i]; - auto& character = characters.at(cha); - for(size_t x = 0; x < character.width; ++x) - { - for(size_t y = 0; y < img_font.height(); ++y) - { - auto& c = img_font.getPixel(x + character.offset, y); - pb->setPixel(x + x_offset + character.pre_bias, y, c); - } - } - x_offset += character.width + spacing + character.post_bias; - } - - return pb; -} - -} // GUI:: diff --git a/plugingui/font.h b/plugingui/font.h deleted file mode 100644 index 2e3f87a..0000000 --- a/plugingui/font.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * font.h - * - * Sat Nov 12 11:13:41 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include "pixelbuffer.h" -#include "image.h" - -namespace GUI { - -class Font { -public: - Font(const std::string& fontfile = ":resources/font.png"); - - size_t textWidth(const std::string& text) const; - size_t textHeight(const std::string& text = "") const; - - void setLetterSpacing(int letterSpacing); - int letterSpacing() const; - - PixelBufferAlpha *render(const std::string& text) const; - -private: - Image img_font; - - class Character { - public: - std::size_t offset{0}; - std::size_t width{0}; - int pre_bias{0}; - int post_bias{0}; - }; - - std::array characters; - int spacing{1}; -}; - -} // GUI:: diff --git a/plugingui/frame.cc b/plugingui/frame.cc deleted file mode 100644 index d375b6d..0000000 --- a/plugingui/frame.cc +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * frame.cc - * - * Tue Feb 7 21:07:56 CET 2017 - * Copyright 2017 André Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "frame.h" - -#include "painter.h" - -namespace GUI -{ - -FrameWidget::FrameWidget(Widget* parent, bool has_switch, bool has_help_text) - : Widget(parent) - , is_switched_on(!has_switch) - , bar_height(24) -{ - if(has_switch) - { - // We only have to set this once as nothing happens on a resize - power_button.move(4, 4); - power_button.resize(16, 16); - - power_button.setChecked(is_switched_on); - CONNECT(&power_button, stateChangedNotifier, this, - &FrameWidget::powerButtonStateChanged); - } - power_button.setVisible(has_switch); - - if(has_help_text) - { - // We only have to set this once as nothing happens on a resize - help_button.resize(16, 16); - help_button.move(width() - 4 - 16, 4); - help_button.setText("?"); - } - help_button.setVisible(has_help_text); - - CONNECT(this, sizeChangeNotifier, this, &FrameWidget::sizeChanged); -} - -void FrameWidget::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - int center_x = width() / 2; - auto title_buf = title.c_str(); - - // draw the dark grey box - p.setColour(enabled ? grey_box_colour : grey_box_colour_disabled); - p.drawFilledRectangle(1, 1, width() - 2, bar_height); - - // frame - p.setColour(frame_colour_top); - p.drawLine(0, 0, width() - 1, 0); - p.setColour(frame_colour_bottom); - p.drawLine(0, height() - 1, width() - 1, height() - 1); - p.setColour(frame_colour_side); - p.drawLine(0, 0, 0, height() - 1); - p.drawLine(width() - 1, 0, width() - 1, height() - 1); - - // background - p.setColour(background_colour); - p.drawFilledRectangle(1, bar_height, width() - 2, height() - 2); - - // draw the label - p.setColour(enabled ? label_colour : label_colour_disabled); - p.drawText(center_x - label_width, bar_height - 4, font, title_buf); - power_button.setEnabled(enabled); -} - -void FrameWidget::powerButtonStateChanged(bool new_state) -{ - is_switched_on = new_state; - onSwitchChangeNotifier(is_switched_on); -} - -void FrameWidget::setTitle(std::string const& title) -{ - this->title = title; - label_width = font.textWidth(title.c_str()) / 2 + 1; -} - -void FrameWidget::setHelpText(const std::string& help_text) -{ - help_button.setHelpText(help_text); -} - -void FrameWidget::setContent(Widget* content) -{ - this->content = content; - content->reparent(this); -} - -void FrameWidget::setOnSwitch(bool on) -{ - is_switched_on = on; - power_button.setChecked(is_switched_on); -} - -void FrameWidget::setEnabled(bool enabled) -{ - this->enabled = enabled; - onEnabledChanged(enabled); - - redraw(); -} - -void FrameWidget::sizeChanged(int width, int height) -{ - if(content) - { - content_start_x = content_margin; - content_start_y = bar_height + content_margin; - content_width = std::max((int)width - 2 * content_margin, 0); - content_height = std::max((int)height - (bar_height + 2 * content_margin), 0); - - content->move(content_start_x, content_start_y); - content->resize(content_width, content_height); - } - - help_button.move(width - 4 - 16, help_button.y()); -} - -} // GUI:: diff --git a/plugingui/frame.h b/plugingui/frame.h deleted file mode 100644 index db26ea9..0000000 --- a/plugingui/frame.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * frame.h - * - * Tue Feb 7 21:07:56 CET 2017 - * Copyright 2017 André Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "font.h" -#include "powerbutton.h" -#include "helpbutton.h" -#include "widget.h" - -namespace GUI -{ - -class FrameWidget - : public Widget -{ -public: - FrameWidget(Widget* parent, bool has_switch = false, bool has_help_text = false); - virtual ~FrameWidget() = default; - - // From Widget: - virtual bool isFocusable() override { return false; } - virtual bool catchMouse() override { return false; } - - bool isSwitchedOn() { return is_switched_on; } - - void setTitle(const std::string& title); - void setHelpText(const std::string& help_text); - void setContent(Widget* content); - - void setOnSwitch(bool on); - void setEnabled(bool enabled); - - Notifier onSwitchChangeNotifier; // (bool on) - Notifier onEnabledChanged; // (bool enabled) - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - - //! Callback for Widget::sizeChangeNotifier - void sizeChanged(int width, int height); - - bool enabled = true; - -private: - // - // upper bar - // - - // label - Font font; - std::string title; - GUI::Colour label_colour{0.1}; - GUI::Colour label_colour_disabled{0.5}; - std::size_t label_width; - - // switch - bool is_switched_on; - PowerButton power_button{this}; - HelpButton help_button{this}; - - void powerButtonStateChanged(bool clicked); - - // grey box - int bar_height; - GUI::Colour grey_box_colour{0.7}; - GUI::Colour grey_box_colour_disabled{0.7}; - GUI::Colour background_colour{0.85, 0.8}; - - // - // content - // - - // content frame - GUI::Colour frame_colour_top{0.95}; - GUI::Colour frame_colour_bottom{0.4}; - GUI::Colour frame_colour_side{0.6}; - - // content box - Widget* content{nullptr}; - int content_margin{12}; - - int content_start_x; - int content_start_y; - int content_width; - int content_height; -}; - -} // GUI:: diff --git a/plugingui/guievent.h b/plugingui/guievent.h deleted file mode 100644 index 4ad0798..0000000 --- a/plugingui/guievent.h +++ /dev/null @@ -1,212 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * event.h - * - * Sun Oct 9 16:11:47 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include -#include - -namespace GUI -{ - -enum class EventType -{ - mouseMove, - repaint, - button, - scroll, - key, - close, - resize, - move, - mouseEnter, - mouseLeave, -}; - -class Event -{ -public: - virtual ~Event() {} - - virtual EventType type() = 0; -}; - -class MouseMoveEvent - : public Event -{ -public: - EventType type() { return EventType::mouseMove; } - - int x; - int y; -}; - - -enum class Direction -{ - up, - down, -}; - -enum class MouseButton -{ - right, - middle, - left, -}; - -class ButtonEvent - : public Event -{ -public: - EventType type() { return EventType::button; } - - int x; - int y; - - Direction direction; - MouseButton button; - - bool doubleClick; -}; - -class ScrollEvent - : public Event -{ -public: - EventType type() { return EventType::scroll; } - - int x; - int y; - - float delta; -}; - -class RepaintEvent - : public Event -{ -public: - EventType type() { return EventType::repaint; } - - int x; - int y; - size_t width; - size_t height; -}; - -enum class Key -{ - unknown, - left, - right, - up, - down, - deleteKey, - backspace, - home, - end, - pageDown, - pageUp, - enter, - character, //!< The actual character is stored in KeyEvent::text -}; - -class KeyEvent - : public Event -{ -public: - EventType type() { return EventType::key; } - - Direction direction; - - Key keycode; - std::string text; -}; - -class CloseEvent - : public Event -{ -public: - EventType type() { return EventType::close; } -}; - -class ResizeEvent - : public Event -{ -public: - EventType type() { return EventType::resize; } - - size_t width; - size_t height; -}; - -class MoveEvent - : public Event -{ -public: - EventType type() { return EventType::move; } - - int x; - int y; -}; - -class MouseEnterEvent - : public Event -{ -public: - EventType type() { return EventType::mouseEnter; } - - int x; - int y; -}; - -class MouseLeaveEvent - : public Event -{ -public: - EventType type() { return EventType::mouseLeave; } - - int x; - int y; -}; - -using EventQueue = std::list>; - -struct Rect -{ - std::size_t x1; - std::size_t y1; - std::size_t x2; - std::size_t y2; - - bool empty() const - { - return x1 == x2 && y1 == y2; - } -}; - -} // GUI:: diff --git a/plugingui/helpbutton.cc b/plugingui/helpbutton.cc deleted file mode 100644 index fa061a6..0000000 --- a/plugingui/helpbutton.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * helpbutton.cc - * - * Wed May 8 17:10:08 CEST 2019 - * Copyright 2019 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "helpbutton.h" - -#include "painter.h" - -#include - -namespace GUI -{ - -HelpButton::HelpButton(Widget* parent) - : ButtonBase(parent) - , tip(this) -{ - CONNECT(this, clickNotifier, this, &HelpButton::showHelpText); - tip.hide(); -} - -void HelpButton::setHelpText(const std::string& help_text) -{ - tip.setText(help_text); -} - -void HelpButton::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - bool state = true; - - // enabled and on - if(state) - { - if(button_state == ButtonBase::State::Down) - { - p.drawImage(0, 0, pushed); - } - else - { - p.drawImage(0, 0, normal); - } - return; - } -} - -void HelpButton::showHelpText() -{ - tip.show(); -} - -} // GUI:: diff --git a/plugingui/helpbutton.h b/plugingui/helpbutton.h deleted file mode 100644 index 6e97eca..0000000 --- a/plugingui/helpbutton.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * helpbutton.h - * - * Wed May 8 17:10:08 CEST 2019 - * Copyright 2019 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "texture.h" -#include "button_base.h" -#include "tooltip.h" - -namespace GUI -{ - -class HelpButton - : public ButtonBase -{ -public: - HelpButton(Widget* parent); - virtual ~HelpButton() = default; - - void setHelpText(const std::string& help_text); - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - -private: - void showHelpText(); - - Texture normal{getImageCache(), ":resources/help_button.png", 0, 0, 16, 16}; - Texture pushed{getImageCache(), ":resources/help_button.png", 16, 0, 16, 16}; - - Tooltip tip; -}; - -} // GUI:: diff --git a/plugingui/humaniservisualiser.cc b/plugingui/humaniservisualiser.cc index 92da164..2a17197 100644 --- a/plugingui/humaniservisualiser.cc +++ b/plugingui/humaniservisualiser.cc @@ -26,7 +26,7 @@ */ #include "humaniservisualiser.h" -#include "painter.h" +#include #include #include diff --git a/plugingui/humaniservisualiser.h b/plugingui/humaniservisualiser.h index 55e37d2..41179fa 100644 --- a/plugingui/humaniservisualiser.h +++ b/plugingui/humaniservisualiser.h @@ -26,9 +26,9 @@ */ #pragma once -#include "widget.h" -#include "texturedbox.h" -#include "texture.h" +#include +#include +#include struct Settings; class SettingsNotifier; diff --git a/plugingui/humanizerframecontent.cc b/plugingui/humanizerframecontent.cc index 475f16d..a4f71e5 100644 --- a/plugingui/humanizerframecontent.cc +++ b/plugingui/humanizerframecontent.cc @@ -28,7 +28,7 @@ #include -#include "painter.h" +#include namespace GUI { diff --git a/plugingui/humanizerframecontent.h b/plugingui/humanizerframecontent.h index 10ae0f3..ef60b8e 100644 --- a/plugingui/humanizerframecontent.h +++ b/plugingui/humanizerframecontent.h @@ -26,10 +26,11 @@ */ #pragma once -#include "knob.h" +#include +#include +#include + #include "labeledcontrol.h" -#include "layout.h" -#include "widget.h" #include diff --git a/plugingui/image.cc b/plugingui/image.cc deleted file mode 100644 index 118203e..0000000 --- a/plugingui/image.cc +++ /dev/null @@ -1,216 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * image.cc - * - * Sat Mar 16 15:05:09 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "image.h" - -#include -#include -#include -#include - -#include - -#include "resource.h" -#include "lodepng/lodepng.h" - -namespace GUI -{ - -Image::Image(const char* data, size_t size) -{ - load(data, size); -} - -Image::Image(const std::string& filename) - : filename(filename) -{ - Resource rc(filename); - if(!rc.valid()) - { - setError(); - return; - } - load(rc.data(), rc.size()); -} - -Image::Image(Image&& other) - : _width(other._width) - , _height(other._height) - , image_data(std::move(other.image_data)) - , image_data_raw(std::move(other.image_data_raw)) - , filename(other.filename) -{ - other._width = 0; - other._height = 0; -} - -Image::~Image() -{ -} - -Image& Image::operator=(Image&& other) -{ - image_data.clear(); - image_data = std::move(other.image_data); - image_data_raw.clear(); - image_data_raw = std::move(other.image_data_raw); - _width = other._width; - _height = other._height; - valid = other.valid; - - other._width = 0; - other._height = 0; - other.valid = false; - return *this; -} - -void Image::setError() -{ - valid = false; - Resource rc(":resources/png_error"); - if(!rc.valid()) - { - _width = _height = 0u; - return; - } - - const unsigned char* ptr = (const unsigned char*)rc.data(); - - std::uint32_t iw, ih; - - iw = (uint32_t) ptr[0] | - (uint32_t) ptr[1] << 8 | - (uint32_t) ptr[2] << 16 | - (uint32_t) ptr[3] << 24; - ptr += sizeof(uint32_t); - - ih = (uint32_t) ptr[0] | - (uint32_t) ptr[1] << 8 | - (uint32_t) ptr[2] << 16 | - (uint32_t) ptr[3] << 24; - ptr += sizeof(uint32_t); - - _width = iw; - _height = ih; - - image_data.clear(); - image_data.reserve(_width * _height); - - image_data_raw.clear(); - image_data_raw.reserve(_width * _height * 4); - memcpy(image_data_raw.data(), ptr, _height * _width); - - for(std::size_t y = 0; y < _height; ++y) - { - for(std::size_t x = 0; x < _width; ++x) - { - image_data.emplace_back(Colour{ptr[0] / 255.0f, ptr[1] / 255.0f, - ptr[2] / 255.0f, ptr[3] / 255.0f}); - } - } - - assert(image_data.size() == (_width * _height)); -} - -void Image::load(const char* data, size_t size) -{ - has_alpha = false; - unsigned int iw{0}, ih{0}; - std::uint8_t* char_image_data{nullptr}; - unsigned int res = lodepng_decode32((std::uint8_t**)&char_image_data, - &iw, &ih, - (const std::uint8_t*)data, size); - - if(res != 0) - { - ERR(image, "Error in lodepng_decode32: %d while loading '%s'", - res, filename.c_str()); - setError(); - return; - } - - _width = iw; - _height = ih; - - image_data.clear(); - image_data.reserve(_width * _height); - - image_data_raw.clear(); - image_data_raw.reserve(_width * _height * 4); - memcpy(image_data_raw.data(), char_image_data, _height * _width * 4); - - for(std::size_t y = 0; y < _height; ++y) - { - for(std::size_t x = 0; x < _width; ++x) - { - std::uint8_t* ptr = &char_image_data[(x + y * _width) * 4]; - image_data.emplace_back(Colour{ptr[0], ptr[1], ptr[2], ptr[3]}); - has_alpha |= ptr[3] != 0xff; - } - } - - assert(image_data.size() == (_width * _height)); - - std::free(char_image_data); - valid = true; -} - -size_t Image::width() const -{ - return _width; -} - -size_t Image::height() const -{ - return _height; -} - -const Colour& Image::getPixel(size_t x, size_t y) const -{ - if(x > _width || y > _height) - { - return out_of_range; - } - - return image_data[x + y * _width]; -} - -const std::uint8_t* Image::line(std::size_t y, std::size_t x_offset) const -{ - return image_data_raw.data() + y * _width * 4 + x_offset * 4; -} - -bool Image::hasAlpha() const -{ - return has_alpha; -} - -bool Image::isValid() const -{ - return valid; -} - -} // GUI:: diff --git a/plugingui/image.h b/plugingui/image.h deleted file mode 100644 index d162a75..0000000 --- a/plugingui/image.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * image.h - * - * Sat Mar 16 15:05:08 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include "drawable.h" -#include "colour.h" -#include "resource.h" - -namespace GUI { - -class Image - : public Drawable -{ -public: - Image(const char* data, size_t size); - Image(const std::string& filename); - Image(Image&& other); - virtual ~Image(); - - Image& operator=(Image&& other); - - size_t width() const override; - size_t height() const override; - - const Colour& getPixel(size_t x, size_t y) const override; - const std::uint8_t* line(std::size_t y, - std::size_t x_offset = 0) const override; - - bool hasAlpha() const override; - - bool isValid() const; - -protected: - void setError(); - bool valid{false}; - - void load(const char* data, size_t size); - - std::size_t _width{0}; - std::size_t _height{0}; - std::vector image_data; - std::vector image_data_raw; - Colour out_of_range{0.0f, 0.0f, 0.0f, 0.0f}; - std::string filename; - bool has_alpha{false}; -}; - -} // GUI:: diff --git a/plugingui/imagecache.cc b/plugingui/imagecache.cc deleted file mode 100644 index d3130fe..0000000 --- a/plugingui/imagecache.cc +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * imagecache.cc - * - * Thu Jun 2 17:12:05 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "imagecache.h" - -#include - -#include "image.h" - -namespace GUI -{ - -ScopedImageBorrower::ScopedImageBorrower(ImageCache& imageCache, - const std::string& filename) - : imageCache(imageCache) - , filename(filename) - , image(imageCache.borrow(filename)) -{ -} - -ScopedImageBorrower::ScopedImageBorrower(ScopedImageBorrower&& other) - : imageCache(other.imageCache) - , filename(other.filename) - , image(other.image) -{ - other.filename.clear(); -} - -ScopedImageBorrower::~ScopedImageBorrower() -{ - if(!filename.empty()) - { - imageCache.giveBack(filename); - } -} - -Image& ScopedImageBorrower::operator*() -{ - return image; -} - -Image& ScopedImageBorrower::operator()() -{ - return image; -} - -ScopedImageBorrower ImageCache::getImage(const std::string& filename) -{ - return ScopedImageBorrower(*this, filename); -} - -Image& ImageCache::borrow(const std::string& filename) -{ - auto cacheIterator = imageCache.find(filename); - if(cacheIterator == imageCache.end()) - { - Image image(filename); - auto insertValue = - imageCache.emplace(filename, std::make_pair(0, std::move(image))); - cacheIterator = insertValue.first; - } - - auto& cacheEntry = cacheIterator->second; - ++cacheEntry.first; - return cacheEntry.second; -} - -void ImageCache::giveBack(const std::string& filename) -{ - auto cacheIterator = imageCache.find(filename); - assert(cacheIterator != imageCache.end()); - auto& cacheEntry = cacheIterator->second; - --cacheEntry.first; - if(cacheEntry.first == 0) - { - imageCache.erase(cacheIterator); - } -} - -} // GUI:: diff --git a/plugingui/imagecache.h b/plugingui/imagecache.h deleted file mode 100644 index d31a844..0000000 --- a/plugingui/imagecache.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * imagecache.h - * - * Thu Jun 2 17:12:05 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include -#include - -namespace GUI -{ - -class Image; -class ImageCache; - -class ScopedImageBorrower -{ -public: - ScopedImageBorrower(ImageCache& imageCache, const std::string& filename); - ScopedImageBorrower(ScopedImageBorrower&& other); - virtual ~ScopedImageBorrower(); - - ScopedImageBorrower& operator=(ScopedImageBorrower&& other); - - Image& operator*(); - Image& operator()(); - -protected: - ImageCache& imageCache; - std::string filename; - Image& image; -}; - -class ImageCache -{ -public: - ScopedImageBorrower getImage(const std::string& filename); - -private: - friend class ScopedImageBorrower; - - Image& borrow(const std::string& filename); - void giveBack(const std::string& filename); - -protected: - std::map> imageCache; -}; - -} // GUI:: diff --git a/plugingui/knob.cc b/plugingui/knob.cc deleted file mode 100644 index 25200a7..0000000 --- a/plugingui/knob.cc +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * knob.cc - * - * Thu Feb 28 07:37:27 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "knob.h" - -#include "painter.h" - -#include -#include - -namespace -{ -const double pi = std::atan(1.0) * 4.0; -} - -namespace GUI -{ - -Knob::Knob(Widget *parent) - : Widget(parent) - , img_knob(getImageCache(), ":resources/knob.png") -{ - state = up; - - maximum = 1.0; - minimum = 0.0; - - current_value = 0.0; - - mouse_offset_x = 0; -} - -void Knob::setValue(float value) -{ - value -= minimum; - value /= (maximum - minimum); - internalSetValue(value); -} - -void Knob::setDefaultValue(float value) -{ - default_value = value; -} - -void Knob::setRange(float minimum, float maximum) -{ - this->minimum = minimum; - this->maximum = maximum; - internalSetValue(current_value); -} - -float Knob::value() -{ - return current_value * (maximum - minimum) + minimum; -} - -void Knob::showValue(bool show_value) -{ - this->show_value = show_value; -} - -void Knob::scrollEvent(ScrollEvent* scrollEvent) -{ - float value = (current_value - (scrollEvent->delta / 200.0)); - internalSetValue(value); -} - -void Knob::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) -{ - if(state == down) - { - if(mouse_offset_x == (mouseMoveEvent->x + (-1 * mouseMoveEvent->y))) - { - return; - } - - float dval = - mouse_offset_x - (mouseMoveEvent->x + (-1 * mouseMoveEvent->y)); - float value = current_value - (dval / 300.0); - - internalSetValue(value); - - mouse_offset_x = mouseMoveEvent->x + (-1 * mouseMoveEvent->y); - } -} - -void Knob::keyEvent(KeyEvent* keyEvent) -{ - if(keyEvent->direction != Direction::up) - { - return; - } - - float value = current_value; - switch(keyEvent->keycode) { - case Key::up: - value += 0.01; - break; - case Key::down: - value -= 0.01; - break; - case Key::right: - value += 0.01; - break; - case Key::left: - value -= 0.01; - break; - case Key::home: - value = 0; - break; - case Key::end: - value = 1; - break; - default: - break; - } - - internalSetValue(value); -} - -void Knob::buttonEvent(ButtonEvent* buttonEvent) -{ - // Ignore everything except left clicks. - if(buttonEvent->button != MouseButton::left) - { - return; - } - - if(buttonEvent->doubleClick) - { - float value = default_value; - value -= minimum; - value /= (maximum - minimum); - internalSetValue(value); - return; - } - - if(buttonEvent->direction == Direction::down) - { - state = down; - mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y); - return; - } - - if(buttonEvent->direction == Direction::up) - { - state = up; - mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y); - clicked(); - return; - } -} - -void Knob::repaintEvent(RepaintEvent* repaintEvent) -{ - int diameter = (width()>height()?height():width()); - int radius = diameter / 2; - int center_x = width() / 2; - int center_y = height() / 2; - - Painter p(*this); - p.clear(); - - p.drawImageStretched(0, 0, img_knob, diameter, diameter); - - float range = maximum - minimum; - - if (show_value) { - // Show 0, 1 or 2 decimal point depending on the size of the range - char buf[64]; - if(range> 100.0f) - { - sprintf(buf, "%.0f", current_value * range + minimum); - } - else if(range > 10.0f) - { - sprintf(buf, "%.1f", current_value * range + minimum); - } - else - { - sprintf(buf, "%.2f", current_value * range + minimum); - } - p.drawText(center_x - font.textWidth(buf) / 2 + 1, - center_y + font.textHeight(buf) / 2 + 1, font, buf); - } - - // Make it start from 20% and stop at 80% - double padval = current_value * 0.8 + 0.1; - - double from_x = sin((-1 * padval + 1) * 2 * pi) * radius * 0.6; - double from_y = cos((-1 * padval + 1) * 2 * pi) * radius * 0.6; - - double to_x = sin((-1 * padval + 1) * 2 * pi) * radius * 0.8; - double to_y = cos((-1 * padval + 1) * 2 * pi) * radius * 0.8; - - // Draw "fat" line by drawing 9 lines with moved start/ending points. - p.setColour(Colour(1.0f, 0.0f, 0.0f, 1.0f)); - for(int _x = -1; _x < 2; _x++) - { - for(int _y = -1; _y < 2; _y++) - { - p.drawLine(from_x + center_x + _x, - from_y + center_y + _y, - to_x + center_x + _x, - to_y + center_y + _y); - } - } -} - -void Knob::internalSetValue(float new_value) -{ - if(new_value < 0.0) - { - new_value = 0.0; - } - - if(new_value > 1.0) - { - new_value = 1.0; - } - - if(new_value == current_value) - { - return; - } - - current_value = new_value; - valueChangedNotifier(value()); - redraw(); -} - -} // GUI:: diff --git a/plugingui/knob.h b/plugingui/knob.h deleted file mode 100644 index fc71511..0000000 --- a/plugingui/knob.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * knob.h - * - * Thu Feb 28 07:37:27 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "widget.h" -#include "texture.h" -#include "font.h" - -namespace GUI { - -class Knob : public Widget { -public: - Knob(Widget *parent); - virtual ~Knob() = default; - - // From Widget: - bool catchMouse() override { return true; } - bool isFocusable() override { return true; } - - void setValue(float value); - void setDefaultValue(float value); - void setRange(float minimum, float maximum); - float value(); - void showValue(bool show_value); - - Notifier valueChangedNotifier; // (float newValue) - -protected: - virtual void clicked() {} - - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - virtual void buttonEvent(ButtonEvent* buttonEvent) override; - virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; - virtual void scrollEvent(ScrollEvent* scrollEvent) override; - virtual void keyEvent(KeyEvent* keyEvent) override; - -private: - //! Sets the internal value and sends out the changed notification. - void internalSetValue(float value); - - typedef enum { - up, - down - } state_t; - - state_t state; - - float current_value; - float default_value = 0.0; - float maximum; - float minimum; - - bool show_value{true}; - - Texture img_knob; - - int mouse_offset_x; - Font font; -}; - -} // GUI:: diff --git a/plugingui/label.cc b/plugingui/label.cc deleted file mode 100644 index b5239ec..0000000 --- a/plugingui/label.cc +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * label.cc - * - * Sun Oct 9 13:02:18 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "label.h" - -#include "painter.h" -#include "guievent.h" - -#include - -namespace GUI { - -Label::Label(Widget *parent) - : Widget(parent) -{ -} - -void Label::setText(const std::string& text) -{ - _text = text; - redraw(); -} - -void Label::setAlignment(TextAlignment alignment) -{ - this->alignment = alignment; -} - -void Label::setColour(Colour colour) -{ - this->colour = std::make_unique(colour); - redraw(); -} - -void Label::resetColour() -{ - colour.release(); - redraw(); -} - -void Label::resizeToText() -{ - resize(font.textWidth(_text) + border, font.textHeight()); -} - -void Label::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - p.clear(); - - int offset = 0; - switch(alignment) { - case TextAlignment::left: - offset = border; - break; - case TextAlignment::center: - offset = (width() - font.textWidth(_text)) / 2; - break; - case TextAlignment::right: - offset = width() - font.textWidth(_text) - border; - break; - } - - if (colour) { - p.setColour(*colour); - p.drawText(offset, (height() + font.textHeight()) / 2, font, _text); - } - else { - p.drawText(offset, (height() + font.textHeight()) / 2, font, _text, true); - } -} - -} // GUI:: diff --git a/plugingui/label.h b/plugingui/label.h deleted file mode 100644 index 45b4176..0000000 --- a/plugingui/label.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * label.h - * - * Sun Oct 9 13:02:17 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "widget.h" - -#include "font.h" - -#include -#include - -namespace GUI { - -enum class TextAlignment { - left, - center, - right, -}; - -class Label : public Widget { -public: - Label(Widget *parent); - virtual ~Label() = default; - - void setText(const std::string& text); - void setAlignment(TextAlignment alignment); - void setColour(Colour colour); - void resetColour(); - void resizeToText(); - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - -private: - std::string _text; - Font font{":resources/fontemboss.png"}; - TextAlignment alignment{TextAlignment::left}; - int border{0}; - - // optional colour - std::unique_ptr colour; -}; - -} // GUI:: diff --git a/plugingui/labeledcontrol.h b/plugingui/labeledcontrol.h index 3cbae39..1972072 100644 --- a/plugingui/labeledcontrol.h +++ b/plugingui/labeledcontrol.h @@ -26,8 +26,8 @@ */ #pragma once -#include "label.h" -#include "widget.h" +#include +#include #include #include diff --git a/plugingui/layout.cc b/plugingui/layout.cc deleted file mode 100644 index 61e4f77..0000000 --- a/plugingui/layout.cc +++ /dev/null @@ -1,386 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * layout.cc - * - * Sat Mar 21 15:12:36 CET 2015 - * Copyright 2015 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "layout.h" - -#include "widget.h" - -#include - -namespace GUI -{ - -LayoutItem::LayoutItem() - : parent(nullptr) -{ -} - -LayoutItem::~LayoutItem() -{ - setLayoutParent(nullptr); // Will disconnect from layout if any. -} - -void LayoutItem::setLayoutParent(Layout* p) -{ - if(this->parent) - { - this->parent->removeItem(this); - } - - this->parent = p; -} - -Layout::Layout(LayoutItem* parent) : parent(parent) -{ - auto widget = dynamic_cast(parent); - if(widget) - { - CONNECT(widget, sizeChangeNotifier, this, &Layout::sizeChanged); - } -} - -void Layout::addItem(LayoutItem* item) -{ - items.push_back(item); - item->setLayoutParent(this); - layout(); -} - -void Layout::removeItem(LayoutItem* item) -{ - auto new_end = std::remove(items.begin(), items.end(), item); - items.erase(new_end, items.end()); - - layout(); -} - -void Layout::sizeChanged(int width, int height) -{ - layout(); -} - -// -// BoxLayout -// - -BoxLayout::BoxLayout(LayoutItem* parent) : Layout(parent) -{ -} - -void BoxLayout::setResizeChildren(bool resizeChildren) -{ - this->resizeChildren = resizeChildren; - layout(); -} - -void BoxLayout::setSpacing(size_t spacing) -{ - this->spacing = spacing; - layout(); -} - -// -// VBoxLayout -// - -VBoxLayout::VBoxLayout(LayoutItem* parent) - : BoxLayout(parent) - , align(HAlignment::center) -{ -} - -void VBoxLayout::layout() -{ - size_t y = 0; - size_t w = parent->width(); - // size_t h = parent->height() / items.size(); - - LayoutItemList::iterator i = items.begin(); - while(i != items.end()) - { - LayoutItem* item = *i; - - if(resizeChildren) - { - auto num_items = items.size(); - auto empty_space = (num_items - 1) * spacing; - auto available_space = parent->height(); - - if(available_space >= empty_space) - { - auto item_height = (available_space - empty_space) / num_items; - item->resize(w, item_height); - } - else - { - // TODO: Should this case be handled differently? - item->resize(w, 0); - } - } - - size_t x = 0; - switch(align) - { - case HAlignment::left: - x = 0; - break; - case HAlignment::center: - x = (w / 2) - (item->width() / 2); - break; - case HAlignment::right: - x = w - item->width(); - break; - } - - item->move(x, y); - y += item->height() + spacing; - ++i; - } -} - -void VBoxLayout::setHAlignment(HAlignment alignment) -{ - align = alignment; -} - -// -// HBoxLayout -// - -HBoxLayout::HBoxLayout(LayoutItem* parent) - : BoxLayout(parent) - , align(VAlignment::center) -{ -} - -void HBoxLayout::layout() -{ - if(items.empty()) - { - return; - } - - // size_t w = parent->width() / items.size(); - size_t h = parent->height(); - size_t x = 0; - - LayoutItemList::iterator i = items.begin(); - while(i != items.end()) - { - LayoutItem* item = *i; - if(resizeChildren) - { - auto num_items = items.size(); - auto empty_space = (num_items - 1) * spacing; - auto available_space = parent->width(); - - if(available_space >= empty_space) - { - auto item_width = (available_space - empty_space) / num_items; - item->resize(item_width, h); - } - else - { - // TODO: Should this case be handled differently? - item->resize(0, h); - } - - item->move(x, 0); - } - else - { - size_t y = 0; - switch(align) - { - case VAlignment::top: - y = 0; - break; - case VAlignment::center: - y = (h / 2) - (item->height() / 2); - break; - case VAlignment::bottom: - y = h - item->height(); - break; - } - - int diff = 0; // w - item->width(); - item->move(x + diff / 2, y); - } - x += item->width() + spacing; - ++i; - } -} - -void HBoxLayout::setVAlignment(VAlignment alignment) -{ - align = alignment; -} - -// -// GridLayout -// - -GridLayout::GridLayout(LayoutItem* parent, std::size_t number_of_columns, - std::size_t number_of_rows) - : BoxLayout(parent) - , number_of_columns(number_of_columns) - , number_of_rows(number_of_rows) -{ -} - -void GridLayout::removeItem(LayoutItem* item) -{ - // manually remove from grid_ranges as remove_if doesn't work on an - // unordered_map. - auto it = grid_ranges.begin(); - while(it != grid_ranges.end()) - { - if(it->first == item) - { - it = grid_ranges.erase(it); - } - else - { - ++it; - } - } - - Layout::removeItem(item); -} - -void GridLayout::layout() -{ - if(grid_ranges.empty()) - { - return; - } - - // Calculate cell sizes - auto cell_size = calculateCellSize(); - - for(auto const& pair : grid_ranges) - { - auto& item = *pair.first; - auto const& range = pair.second; - - moveAndResize(item, range, cell_size); - } -} - -void GridLayout::setPosition(LayoutItem* item, GridRange const& range) -{ - grid_ranges[item] = range; -} - -int GridLayout::lastUsedRow(int column) const -{ - int last_row = -1; - - for (auto const& grid_range : grid_ranges) - { - auto const& range = grid_range.second; - if (column >= range.column_begin && column < range.column_end) - { - last_row = std::max(last_row, range.row_end - 1); - } - } - - return last_row; -} - -int GridLayout::lastUsedColumn(int row) const -{ - int last_column = -1; - - for (auto const& grid_range : grid_ranges) - { - auto const& range = grid_range.second; - if (row >= range.row_begin && row < range.row_end) - { - last_column = std::max(last_column, range.column_end - 1); - } - } - - return last_column; - -} - -auto GridLayout::calculateCellSize() const -> CellSize -{ - auto empty_width = (number_of_columns - 1) * spacing; - auto available_width = parent->width(); - auto empty_height = (number_of_rows - 1) * spacing; - auto available_height = parent->height(); - - CellSize cell_size; - if(available_width > empty_width && available_height > empty_height) - { - cell_size.width = (available_width - empty_width) / number_of_columns; - cell_size.height = (available_height - empty_height) / number_of_rows; - } - else - { - cell_size.width = 0; - cell_size.height = 0; - } - - return cell_size; -} - -void GridLayout::moveAndResize( - LayoutItem& item, GridRange const& range, CellSize cell_size) const -{ - std::size_t x = range.column_begin * (cell_size.width + spacing); - std::size_t y = range.row_begin * (cell_size.height + spacing); - - std::size_t column_count = (range.column_end - range.column_begin); - std::size_t row_count = (range.row_end - range.row_begin); - std::size_t width = column_count * (cell_size.width + spacing) - spacing; - std::size_t height = row_count * (cell_size.height + spacing) - spacing; - - if(resizeChildren) - { - item.move(x, y); - - if(cell_size.width * cell_size.height != 0) - { - item.resize(width, height); - } - else - { - item.resize(0, 0); - } - } - else - { - auto x_new = (item.width() > width) ? x : x + (width - item.width()) / 2; - auto y_new = (item.height() > height) ? y : y + (height - item.height()) / 2; - - item.move(x_new, y_new); - } -} - -} // GUI:: diff --git a/plugingui/layout.h b/plugingui/layout.h deleted file mode 100644 index 210c86e..0000000 --- a/plugingui/layout.h +++ /dev/null @@ -1,195 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * layout.h - * - * Sat Mar 21 15:12:36 CET 2015 - * Copyright 2015 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include -#include - -#include - -namespace GUI -{ - -class Layout; - -class LayoutItem -{ -public: - LayoutItem(); - virtual ~LayoutItem(); - - void setLayoutParent(Layout* parent); - - virtual void resize(std::size_t width, std::size_t height) = 0; - virtual void move(int x, int y) = 0; - virtual int x() const = 0; - virtual int y() const = 0; - virtual std::size_t width() const = 0; - virtual std::size_t height() const = 0; - -private: - Layout* parent; -}; - -//! \brief Abtract Layout class. -class Layout : public Listener -{ -public: - Layout(LayoutItem* parent); - virtual ~Layout() - { - } - - virtual void addItem(LayoutItem* item); - virtual void removeItem(LayoutItem* item); - - //! \brief Reimplement this method to create a new Layout rule. - virtual void layout() = 0; - -protected: - void sizeChanged(int width, int height); - - LayoutItem* parent; - typedef std::list LayoutItemList; - LayoutItemList items; -}; - -//! \brief Abstract box layout -class BoxLayout : public Layout -{ -public: - BoxLayout(LayoutItem* parent); - - //! \brief Set to false to only move the items, not scale them. - void setResizeChildren(bool resize_children); - - void setSpacing(size_t spacing); - - // From Layout: - virtual void layout() override = 0; - -protected: - bool resizeChildren{false}; - size_t spacing{0}; -}; - -enum class HAlignment -{ - left, - center, - right, -}; - -//! \brief A Layout that lays out its elements vertically. -class VBoxLayout : public BoxLayout -{ -public: - VBoxLayout(LayoutItem* parent); - - void setHAlignment(HAlignment alignment); - - // From BoxLayout: - virtual void layout() override; - -protected: - HAlignment align; -}; - -enum class VAlignment -{ - top, - center, - bottom, -}; - -//! \brief A Layout that lays out its elements vertically. -class HBoxLayout : public BoxLayout -{ -public: - HBoxLayout(LayoutItem* parent); - - void setVAlignment(VAlignment alignment); - - // From BoxLayout: - virtual void layout() override; - -protected: - VAlignment align; -}; - -//! \brief A Layout class which places the items in a regular grid. An item can -//! span multiple rows/columns. -class GridLayout : public BoxLayout -{ -public: - // The range is open, i.e. end is one past the last one. - struct GridRange - { - int column_begin; - int column_end; - int row_begin; - int row_end; - }; - - GridLayout(LayoutItem* parent, std::size_t number_of_columns, - std::size_t number_of_rows); - - virtual ~GridLayout() - { - } - - // From Layout: - virtual void removeItem(LayoutItem* item); - virtual void layout(); - - void setPosition(LayoutItem* item, GridRange const& range); - - int lastUsedRow(int column) const; - int lastUsedColumn(int row) const; - -protected: - std::size_t number_of_columns; - std::size_t number_of_rows; - - // Note: Yes, this is somewhat redundant to the LayoutItemList of the Layout - // class. However, this was the best idea I had such that I could still - // derive from Layout. If you find this ugly, feel free to fix it. - std::unordered_map grid_ranges; - -private: - struct CellSize { - std::size_t width; - std::size_t height; - }; - - CellSize calculateCellSize() const; - void moveAndResize( - LayoutItem& item, GridRange const& range, CellSize cell_size) const; -}; - -} // GUI:: diff --git a/plugingui/led.cc b/plugingui/led.cc deleted file mode 100644 index f77e31a..0000000 --- a/plugingui/led.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * led.cc - * - * Sat Oct 15 19:12:33 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "led.h" - -#include "painter.h" - -namespace GUI { - -LED::LED(Widget *parent) - : Widget(parent) - , state(Off) -{ -} - -void LED::setState(state_t state) -{ - if(this->state != state) - { - this->state = state; - redraw(); - } -} - -void LED::repaintEvent(RepaintEvent* repaintEvent) -{ - size_t h = height() - 1; - size_t w = width() - 1; - - Painter p(*this); - float alpha = 0.9; - switch(state) { - case Red: - p.setColour(Colour(1, 0, 0,alpha)); - break; - case Green: - p.setColour(Colour(0, 1, 0, alpha)); - break; - case Blue: - p.setColour(Colour(0, 0, 1, alpha)); - break; - case Off: - p.setColour(Colour(0.2, 0.2, 0.2, alpha)); - break; - } - - size_t size = w / 2; - if((h / 2) < size) - { - size = h / 2; - } - p.drawFilledCircle(w / 2, h / 2, size); - - switch(state) { - case Red: - p.setColour(Colour(0.4, 0, 0, alpha)); - break; - case Green: - p.setColour(Colour(0, 0.4, 0, alpha)); - break; - case Blue: - p.setColour(Colour(0, 0, 0.4, alpha)); - break; - case Off: - p.setColour(Colour(0.1, 0.1, 0.1, alpha)); - break; - } - p.drawCircle(w / 2, h / 2, size); - - p.setColour(Colour(1, alpha)); - p.drawFilledCircle(w / 3, h / 3, size / 6); -} - -} // GUI:: diff --git a/plugingui/led.h b/plugingui/led.h deleted file mode 100644 index 14ab6ef..0000000 --- a/plugingui/led.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * led.h - * - * Sat Oct 15 19:12:33 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "widget.h" - -namespace GUI { - -class LED : public Widget { -public: - typedef enum { - Red, - Green, - Blue, - Off - } state_t; - - LED(Widget *parent); - - void setState(state_t state); - -protected: - // From Widget: - void repaintEvent(RepaintEvent* repaintEvent) override; - -private: - state_t state; -}; - -} // GUI:: diff --git a/plugingui/lineedit.cc b/plugingui/lineedit.cc deleted file mode 100644 index 14cc234..0000000 --- a/plugingui/lineedit.cc +++ /dev/null @@ -1,285 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * lineedit.cc - * - * Sun Oct 9 13:01:52 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "lineedit.h" - -#include -#include - -#define BORDER 10 - -namespace GUI { - -LineEdit::LineEdit(Widget *parent) - : Widget(parent) -{ - setReadOnly(false); -} - -LineEdit::~LineEdit() -{ -} - -void LineEdit::setReadOnly(bool ro) -{ - readonly = ro; -} - -bool LineEdit::readOnly() -{ - return readonly; -} - -void LineEdit::setText(const std::string& text) -{ - _text = text; - pos = text.size(); - - visibleText = _text; - offsetPos = 0; - - redraw(); - textChanged(); -} - -std::string LineEdit::getText() -{ - return _text; -} - -void LineEdit::buttonEvent(ButtonEvent *buttonEvent) -{ - if(readOnly()) - { - return; - } - - // Ignore everything except left clicks. - if(buttonEvent->button != MouseButton::left) - { - return; - } - - if(buttonEvent->direction == Direction::down) - { - for(int i = 0; i < (int)visibleText.length(); ++i) - { - int textWidth = font.textWidth(visibleText.substr(0, i)); - if(buttonEvent->x < (textWidth + BORDER)) - { - pos = i + offsetPos; - break; - } - } - redraw(); - } -} - -void LineEdit::keyEvent(KeyEvent *keyEvent) -{ - if(readOnly()) - { - return; - } - - bool change = false; - - if(keyEvent->direction == Direction::down) - { - switch(keyEvent->keycode) { - case Key::left: - if(pos == 0) - { - return; - } - - pos--; - - if(offsetPos >= pos) - { - walkstate = WalkLeft; - } - break; - - case Key::right: - if(pos == _text.length()) - { - return; - } - - pos++; - - if((pos < _text.length()) && ((offsetPos + visibleText.length()) <= pos)) - { - walkstate = WalkRight; - } - break; - - case Key::home: - pos = 0; - visibleText = _text; - offsetPos = 0; - break; - - case Key::end: - pos = _text.length(); - visibleText = _text; - offsetPos = 0; - break; - - case Key::deleteKey: - if(pos < _text.length()) - { - std::string t = _text.substr(0, pos); - t += _text.substr(pos + 1, std::string::npos); - _text = t; - change = true; - } - break; - - case Key::backspace: - if(pos > 0) - { - std::string t = _text.substr(0, pos - 1); - t += _text.substr(pos, std::string::npos); - _text = t; - pos--; - change = true; - } - break; - - case Key::character: - { - std::string pre = _text.substr(0, pos); - std::string post = _text.substr(pos, std::string::npos); - _text = pre + keyEvent->text + post; - change = true; - pos++; - } - break; - - case Key::enter: - enterPressedNotifier(); - break; - - default: - break; - } - - redraw(); - } - - if(change) - { - textChanged(); - } -} - -void LineEdit::repaintEvent(RepaintEvent *repaintEvent) -{ - Painter p(*this); - - int w = width(); - int h = height(); - if((w == 0) || (h == 0)) - { - return; - } - - box.setSize(w, h); - p.drawImage(0, 0, box); - - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); - - switch(walkstate) { - case WalkLeft: - visibleText = _text.substr(pos, std::string::npos); - offsetPos = pos; - break; - - case WalkRight: - { - int delta = (offsetPos < _text.length()) ? 1 : 0; - visibleText = _text.substr(offsetPos + delta); - offsetPos = offsetPos + delta; - } - break; - - case Noop: - visibleText = _text; - offsetPos = 0; - break; - } - - while(true) - { - int textWidth = font.textWidth(visibleText); - if(textWidth <= std::max(w - BORDER - 4 + 3, 0)) - { - break; - } - - switch(walkstate) { - case WalkLeft: - visibleText = visibleText.substr(0, visibleText.length() - 1); - break; - - case WalkRight: - visibleText = visibleText.substr(0, visibleText.length() - 1); - break; - - case Noop: - if(offsetPos < pos) - { - visibleText = visibleText.substr(1); - offsetPos++; - } - else - { - visibleText = visibleText.substr(0, visibleText.length() - 1); - } - break; - } - } - - walkstate = Noop; - - p.drawText(BORDER - 4 + 3, height() / 2 + 5 + 1 + 1 + 1, font, visibleText); - - if(readOnly()) - { - return; - } - - if(hasKeyboardFocus()) - { - size_t px = font.textWidth(visibleText.substr(0, pos - offsetPos)); - p.drawLine(px + BORDER - 1 - 4 + 3, 6, - px + BORDER - 1 - 4 + 3, height() - 7); - } -} - -} // GUI:: diff --git a/plugingui/lineedit.h b/plugingui/lineedit.h deleted file mode 100644 index 86ad986..0000000 --- a/plugingui/lineedit.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * lineedit.h - * - * Sun Oct 9 13:01:52 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "widget.h" -#include "font.h" -#include "painter.h" -#include "texturedbox.h" - -namespace GUI -{ - -class LineEdit - : public Widget -{ -public: - LineEdit(Widget *parent); - virtual ~LineEdit(); - - bool isFocusable() override { return true; } - - std::string getText(); - void setText(const std::string& text); - - void setReadOnly(bool readonly); - bool readOnly(); - - Notifier<> enterPressedNotifier; - - //protected: - virtual void keyEvent(KeyEvent *keyEvent) override; - virtual void repaintEvent(RepaintEvent *repaintEvent) override; - virtual void buttonEvent(ButtonEvent *buttonEvent) override; - -protected: - virtual void textChanged() {} - -private: - TexturedBox box{getImageCache(), ":resources/widget.png", - 0, 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 7, 63, 7}; // dy1, dy2, dy3 - - Font font; - - std::string _text; - size_t pos{0}; - std::string visibleText; - size_t offsetPos{0}; - - enum state_t { - Noop, - WalkLeft, - WalkRight, - }; - state_t walkstate{Noop}; - - bool readonly; -}; - -} // GUI:: diff --git a/plugingui/listbox.cc b/plugingui/listbox.cc deleted file mode 100644 index 28c074e..0000000 --- a/plugingui/listbox.cc +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * listbox.cc - * - * Mon Feb 25 21:21:41 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "listbox.h" - -#include "painter.h" -#include "font.h" - -namespace GUI { - -ListBox::ListBox(Widget *parent) - : Widget(parent) - , selectionNotifier(basic.selectionNotifier) - , clickNotifier(basic.clickNotifier) - , valueChangedNotifier(basic.valueChangedNotifier) - , basic(this) -{ - basic.move(7, 7); -} - -ListBox::~ListBox() -{ -} - -void ListBox::addItem(std::string name, std::string value) -{ - basic.addItem(name, value); -} - -void ListBox::addItems(std::vector &items) -{ - basic.addItems(items); -} - -void ListBox::clear() -{ - basic.clear(); -} - -bool ListBox::selectItem(int index) -{ - return basic.selectItem(index); -} - -std::string ListBox::selectedName() -{ - return basic.selectedName(); -} - -std::string ListBox::selectedValue() -{ - return basic.selectedValue(); -} - -void ListBox::clearSelectedValue() -{ - basic.clearSelectedValue(); -} - -void ListBox::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) - { - return; - } - - box.setSize(w, h); - p.drawImage(0, 0, box); -} - -void ListBox::resize(std::size_t width, std::size_t height) -{ - Widget::resize(width, height); - basic.resize(width - (7 + 7), - height - (7 + 7)); -} - -} // GUI:: diff --git a/plugingui/listbox.h b/plugingui/listbox.h deleted file mode 100644 index 0d9ad4d..0000000 --- a/plugingui/listbox.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * listbox.h - * - * Mon Feb 25 21:21:40 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include "widget.h" -#include "painter.h" -#include "listboxbasic.h" -#include "texturedbox.h" - -namespace GUI -{ - -class ListBox - : public Widget -{ -public: - ListBox(Widget *parent); - virtual ~ListBox(); - - void addItem(std::string name, std::string value); - void addItems(std::vector &items); - - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); - void clearSelectedValue(); - - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - virtual void resize(std::size_t width, std::size_t height) override; - - // Forwarded notifiers from ListBoxBasic::basic - Notifier<>& selectionNotifier; - Notifier<>& clickNotifier; - Notifier<>& valueChangedNotifier; - -private: - ListBoxBasic basic; - - TexturedBox box{getImageCache(), ":resources/widget.png", - 0, 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 7, 63, 7}; // dy1, dy2, dy3 -}; - -} // GUI:: diff --git a/plugingui/listboxbasic.cc b/plugingui/listboxbasic.cc deleted file mode 100644 index b2637eb..0000000 --- a/plugingui/listboxbasic.cc +++ /dev/null @@ -1,362 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * listboxbasic.cc - * - * Thu Apr 4 20:28:10 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "listboxbasic.h" - -#include "painter.h" -#include "font.h" - -namespace GUI { - -ListBoxBasic::ListBoxBasic(Widget *parent) - : Widget(parent) - , scroll(this) -{ - scroll.move(0,0); - scroll.resize(16, 100); - - CONNECT(&scroll, valueChangeNotifier, - this, &ListBoxBasic::onScrollBarValueChange); - - padding = 4; - btn_size = 18; - - selected = -1; - marked = -1; -} - -ListBoxBasic::~ListBoxBasic() -{ -} - -void ListBoxBasic::setSelection(int index) -{ - selected = index; - if(marked == -1) - { - marked = index; - } - valueChangedNotifier(); -} - -void ListBoxBasic::addItem(const std::string& name, const std::string& value) -{ - std::vector items; - ListBoxBasic::Item item; - item.name = name; - item.value = value; - items.push_back(item); - addItems(items); -} - -void ListBoxBasic::addItems(const std::vector& newItems) -{ - for(auto& item : newItems) - { - items.push_back(item); - } - - if(selected == -1) - { - //setSelection((int)items.size() - 1); - setSelection(0); - } - redraw(); -} - -void ListBoxBasic::clear() -{ - items.clear(); - setSelection(-1); - marked = -1; - scroll.setValue(0); - redraw(); -} - -bool ListBoxBasic::selectItem(int index) -{ - if(index < 0 || (index > (int)items.size() - 1)) - { - return false; - } - - setSelection(index); - redraw(); - - return true; -} - -std::string ListBoxBasic::selectedName() -{ - if(selected < 0 || (selected > (int)items.size() - 1)) - { - return ""; - } - - return items[selected].name; -} - -std::string ListBoxBasic::selectedValue() -{ - if(selected < 0 || (selected > (int)items.size() - 1)) - { - return ""; - } - - return items[selected].value; -} - -void ListBoxBasic::clearSelectedValue() -{ - setSelection(-1); -} - -void ListBoxBasic::onScrollBarValueChange(int value) -{ - redraw(); -} - -void ListBoxBasic::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - int w = width(); - int h = height(); - - if((w == 0) || (h == 0)) - { - return; - } - - p.drawImageStretched(0, 0, bg_img, w, h); - - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); - - int yoffset = padding / 2; - int skip = scroll.value(); - int numitems = height() / (font.textHeight() + padding) + 1; - for(int idx = skip; (idx < (int)items.size()) && (idx < (skip + numitems)); - idx++) - { - auto& item = items[idx]; - if(idx == selected) - { - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 0.5f)); - p.drawFilledRectangle(0, - yoffset - (padding / 2), - width() - 1, - yoffset + (font.textHeight() + 1)); - } - - if(idx == marked) - { - p.drawRectangle(0, - yoffset - (padding / 2), - width() - 1, - yoffset + (font.textHeight() + 1)); - } - - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); - - p.drawText(2, yoffset + font.textHeight(), font, item.name); - yoffset += font.textHeight() + padding; - } - - scroll.setRange(numitems); - scroll.setMaximum(items.size()); -} - -void ListBoxBasic::scrollEvent(ScrollEvent* scrollEvent) -{ - // forward scroll event to scroll bar. - scroll.scrollEvent(scrollEvent); -} - -void ListBoxBasic::keyEvent(KeyEvent* keyEvent) -{ - if(keyEvent->direction != Direction::down) - { - return; - } - - switch(keyEvent->keycode) { - case Key::up: - if(marked == 0) - { - return; - } - - marked--; - - if(marked < scroll.value()) - { - scroll.setValue(marked); - } - break; - - case Key::down: - { - // Number of items that can be displayed at a time. - int numitems = height() / (font.textHeight() + padding); - - if(marked == ((int)items.size() - 1)) - { - return; - } - - marked++; - - if(marked > (scroll.value() + numitems - 1)) - { - scroll.setValue(marked - numitems + 1); - } - } - break; - - case Key::home: - marked = 0; - if(marked < scroll.value()) - { - scroll.setValue(marked); - } - break; - - case Key::end: - { - // Number of items that can be displayed at a time. - int numitems = height() / (font.textHeight() + padding); - - marked = (int)items.size() - 1; - if(marked > (scroll.value() + numitems - 1)) - { - scroll.setValue(marked - numitems + 1); - } - } - break; - - case Key::character: - if(keyEvent->text == " ") - { - setSelection(marked); - //selectionNotifier(); - } - break; - - case Key::enter: - setSelection(marked); - selectionNotifier(); - break; - - default: - break; - } - - redraw(); -} - -void ListBoxBasic::buttonEvent(ButtonEvent* buttonEvent) -{ - // Ignore everything except left clicks. - if(buttonEvent->button != MouseButton::left) - { - return; - } - - if((buttonEvent->x > ((int)width() - btn_size)) && - (buttonEvent->y < ((int)width() - 1))) - { - if(buttonEvent->y > 0 && buttonEvent->y < btn_size) - { - if(buttonEvent->direction == Direction::up) - { - return; - } - scroll.setValue(scroll.value() - 1); - return; - } - - if(buttonEvent->y > ((int)height() - btn_size) && - buttonEvent->y < ((int)height() - 1)) - { - if(buttonEvent->direction == Direction::up) - { - return; - } - scroll.setValue(scroll.value() + 1); - return; - } - } - - if(buttonEvent->direction == Direction::up) - { - int skip = scroll.value(); - size_t yoffset = padding / 2; - for(int idx = skip; idx < (int)items.size(); idx++) - { - yoffset += font.textHeight() + padding; - if(buttonEvent->y < (int)yoffset - (padding / 2)) - { - setSelection(idx); - marked = selected; - clickNotifier(); - break; - } - } - - redraw(); - } - - if(buttonEvent->direction != Direction::up) - { - int skip = scroll.value(); - size_t yoffset = padding / 2; - for(int idx = skip; idx < (int)items.size(); idx++) - { - yoffset += font.textHeight() + padding; - if(buttonEvent->y < ((int)yoffset - (padding / 2))) - { - marked = idx; - break; - } - } - - redraw(); - } - - if(buttonEvent->doubleClick) - { - selectionNotifier(); - } -} - -void ListBoxBasic::resize(std::size_t width, std::size_t height) -{ - Widget::resize(width, height); - scroll.move(width - scroll.width(), 0); - scroll.resize(scroll.width(), height); -} - -} // GUI:: diff --git a/plugingui/listboxbasic.h b/plugingui/listboxbasic.h deleted file mode 100644 index 27822e6..0000000 --- a/plugingui/listboxbasic.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * listboxbasic.h - * - * Thu Apr 4 20:28:10 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include - -#include "widget.h" -#include "font.h" -#include "painter.h" -#include "scrollbar.h" - -namespace GUI { - -class ListBoxBasic : public Widget { -public: - class Item { - public: - std::string name; - std::string value; - }; - - ListBoxBasic(Widget *parent); - virtual ~ListBoxBasic(); - - void addItem(const std::string& name, const std::string& value); - void addItems(const std::vector& items); - - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); - - void clearSelectedValue(); - - Notifier<> selectionNotifier; - Notifier<> clickNotifier; - Notifier<> valueChangedNotifier; - - // From Widget: - virtual void resize(std::size_t width, std::size_t height) override; - -protected: - void onScrollBarValueChange(int value); - - // From Widget: - bool isFocusable() override { return true; } - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - virtual void buttonEvent(ButtonEvent* buttonEvent) override; - virtual void keyEvent(KeyEvent* keyEvent) override; - virtual void scrollEvent(ScrollEvent* scrollEvent) override; - - ScrollBar scroll; - - Texture bg_img{getImageCache(), ":resources/widget.png", 7, 7, 1, 63}; - - void setSelection(int index); - - std::vector items; - - int selected; - int marked; - Font font; - int padding; - int btn_size; -}; - -} // GUI:: diff --git a/plugingui/listboxthin.cc b/plugingui/listboxthin.cc deleted file mode 100644 index d224f11..0000000 --- a/plugingui/listboxthin.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * listboxthin.cc - * - * Sun Apr 7 19:39:36 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "listboxthin.h" - -#include "painter.h" -#include "font.h" - -namespace GUI -{ - -ListBoxThin::ListBoxThin(Widget *parent) - : Widget(parent) - , selectionNotifier(basic.selectionNotifier) - , clickNotifier(basic.clickNotifier) - , valueChangedNotifier(basic.valueChangedNotifier) - , basic(this) -{ - basic.move(1, 1); -} - -ListBoxThin::~ListBoxThin() -{ -} - -void ListBoxThin::addItem(std::string name, std::string value) -{ - basic.addItem(name, value); -} - -void ListBoxThin::addItems(std::vector &items) -{ - basic.addItems(items); -} - -void ListBoxThin::clear() -{ - basic.clear(); -} - -bool ListBoxThin::selectItem(int index) -{ - return basic.selectItem(index); -} - -std::string ListBoxThin::selectedName() -{ - return basic.selectedName(); -} - -std::string ListBoxThin::selectedValue() -{ - return basic.selectedValue(); -} - -void ListBoxThin::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) - { - return; - } - - box.setSize(w,h); - p.drawImage(0, 0, box); -} - -void ListBoxThin::resize(std::size_t height, std::size_t width) -{ - Widget::resize(width, height); - basic.resize(width - (1 + 1), - height - (1 + 1)); -} - -} // GUI:: diff --git a/plugingui/listboxthin.h b/plugingui/listboxthin.h deleted file mode 100644 index e861745..0000000 --- a/plugingui/listboxthin.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * listboxthin.h - * - * Sun Apr 7 19:39:35 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include - -#include "widget.h" -#include "painter.h" -#include "listboxbasic.h" -#include "texturedbox.h" - -namespace GUI -{ - -class ListBoxThin - : public Widget -{ -public: - ListBoxThin(Widget *parent); - virtual ~ListBoxThin(); - - void addItem(std::string name, std::string value); - void addItems(std::vector &items); - - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); - - // From Widget: - virtual void repaintEvent(GUI::RepaintEvent* repaintEvent) override; - virtual void resize(std::size_t height, std::size_t width) override; - - // Forwarded notifier from ListBoxBasic::basic - Notifier<>& selectionNotifier; - Notifier<>& clickNotifier; - Notifier<>& valueChangedNotifier; - -private: - ListBoxBasic basic; - - TexturedBox box{getImageCache(), ":resources/thinlistbox.png", - 0, 0, // atlas offset (x, y) - 1, 1, 1, // dx1, dx2, dx3 - 1, 1, 1}; // dy1, dy2, dy3 -}; - -} // GUI:: diff --git a/plugingui/lodepng b/plugingui/lodepng deleted file mode 160000 index a71964e..0000000 --- a/plugingui/lodepng +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a71964ed5fe4f82a32ac7f8201338900f66e855d diff --git a/plugingui/maintab.h b/plugingui/maintab.h index 57aec72..74b970a 100644 --- a/plugingui/maintab.h +++ b/plugingui/maintab.h @@ -26,9 +26,10 @@ */ #pragma once -#include "widget.h" -#include "layout.h" -#include "frame.h" +#include +#include +#include + #include "drumkitframecontent.h" #include "statusframecontent.h" #include "humanizerframecontent.h" diff --git a/plugingui/mainwindow.cc b/plugingui/mainwindow.cc index 932e8f3..ea79cb5 100644 --- a/plugingui/mainwindow.cc +++ b/plugingui/mainwindow.cc @@ -32,7 +32,7 @@ #include -#include "painter.h" +#include namespace GUI { diff --git a/plugingui/mainwindow.h b/plugingui/mainwindow.h index 219f851..efacf07 100644 --- a/plugingui/mainwindow.h +++ b/plugingui/mainwindow.h @@ -28,12 +28,13 @@ #include +#include +#include +#include +#include + #include "abouttab.h" #include "drumkittab.h" -#include "image.h" -#include "tabwidget.h" -#include "texturedbox.h" -#include "window.h" #include "maintab.h" #include "pluginconfig.h" diff --git a/plugingui/nativewindow.h b/plugingui/nativewindow.h deleted file mode 100644 index 400ff57..0000000 --- a/plugingui/nativewindow.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow.h - * - * Fri Dec 28 18:46:01 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include -#include -#include -#include - -#include "guievent.h" - -namespace GUI -{ - -struct Point; - -//! Interface class for native window implementations. -class NativeWindow -{ -public: - NativeWindow() {} - virtual ~NativeWindow() {} - - //! Set a fixed size to the window. - //! It resizes the window and disallows user resizing. - virtual void setFixedSize(std::size_t width, std::size_t height) = 0; - - //! Force window to stay on top of other windows - virtual void setAlwaysOnTop(bool always_on_top) = 0; - - //! Set a new size of the window. - virtual void resize(std::size_t width, std::size_t height) = 0; - - //! Query size of the native window. - virtual std::pair getSize() const = 0; - - //! Move the window to a new position. - //! Note: negative value are allowed. - virtual void move(int x, int y) = 0; - - //! Query the screen position of the native window. - //! Note: returned values can be negative. - virtual std::pair getPosition() const = 0; - - //! Show the window if it is hidden. - virtual void show() = 0; - - //! Hides the window. - virtual void hide() = 0; - - //! Return visibility state of the native window. - virtual bool visible() const = 0; - - //! Sets the window caption in the title bar (if it has one). - virtual void setCaption(const std::string &caption) = 0; - - //! Draw the internal rendering buffer to the window buffer. - virtual void redraw(const Rect& dirty_rect) = 0; - - //! Toggle capture mouse mode. - virtual void grabMouse(bool grab) = 0; - - //! Reads all currently enqueued events from the native window system. - //! \return A queue of shared pointers to events. - virtual EventQueue getEvents() = 0; - - //! \returns the native window handle, it HWND on Win32 or Window id on X11 - virtual void* getNativeWindowHandle() const = 0; - - //! Translate a the local native window coordinate to a global screen - //! coordinate. - virtual Point translateToScreen(const Point& point) = 0; -}; - -} // GUI:: diff --git a/plugingui/nativewindow_cocoa.h b/plugingui/nativewindow_cocoa.h deleted file mode 100644 index 8dc73e6..0000000 --- a/plugingui/nativewindow_cocoa.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_cocoa.h - * - * Sun Dec 4 15:55:14 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "nativewindow.h" - -namespace GUI -{ - -class Window; -class NativeWindowCocoa - : public NativeWindow -{ -public: - NativeWindowCocoa(void* native_window, Window& window); - ~NativeWindowCocoa(); - - // From NativeWindow: - virtual void setFixedSize(std::size_t width, std::size_t height) override; - virtual void setAlwaysOnTop(bool always_on_top) override; - virtual void resize(std::size_t width, std::size_t height) override; - virtual std::pair getSize() const override; - virtual void move(int x, int y) override; - virtual std::pair getPosition() const override; - virtual void show() override; - virtual void hide() override; - virtual bool visible() const override; - virtual void setCaption(const std::string &caption) override; - virtual void redraw(const Rect& dirty_rect) override; - virtual void grabMouse(bool grab) override; - virtual EventQueue getEvents() override; - virtual void* getNativeWindowHandle() const override; - virtual Point translateToScreen(const Point& point) override; - - // Expose friend members of Window to ObjC++ implementation. - class Window& getWindow(); - class PixelBuffer& getWindowPixbuf(); - void resized(); - void pushBackEvent(std::shared_ptr event); - -private: - void updateLayerOffset(); - - Window& window; - std::unique_ptr priv; - EventQueue event_queue; - void* native_window{nullptr}; - bool first{true}; - float scale{1.0}; -}; - -} // GUI:: diff --git a/plugingui/nativewindow_cocoa.mm b/plugingui/nativewindow_cocoa.mm deleted file mode 100644 index 7b6ecc8..0000000 --- a/plugingui/nativewindow_cocoa.mm +++ /dev/null @@ -1,832 +0,0 @@ -/* -*- Mode: ObjC; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_cocoa.mm - * - * Fri Dec 2 20:31:03 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "nativewindow_cocoa.h" - -#include "guievent.h" - -#include -#include - -#import - -#include "window.h" - -#include - -#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101300 // Before MacOSX 10.13 (High-Sierra) -#define STYLE_MASK \ - (NSClosableWindowMask | \ - NSTitledWindowMask | \ - NSResizableWindowMask) -#define IMAGE_FLAGS \ - (kCGBitmapByteOrder32Big | \ - kCGImageAlphaPremultipliedLast) -#define EVENT_MASK \ - NSAnyEventMask -#else -#define STYLE_MASK \ - (NSWindowStyleMaskClosable | \ - NSWindowStyleMaskTitled | \ - NSWindowStyleMaskResizable) -#define IMAGE_FLAGS \ - (kCGImageByteOrder32Big | \ - kCGImageAlphaPremultipliedLast) -#define EVENT_MASK \ - NSEventMaskAny -#endif - -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101400 // Before MacOSX 10.14 (Mojave) -// Nothing here yet... -#endif -#endif - -@interface DGListener : NSWindow -{ -@public - NSWindow* window; - GUI::NativeWindowCocoa* native; -} - -- (id) initWithWindow:(NSWindow*)ref - native:(GUI::NativeWindowCocoa*)_native; -- (void) dealloc; -- (void) windowDidResize; -- (void) windowWillResize; -- (void) windowWillClose; -- (void) unbindNative; -@end - -@implementation DGListener -- (id) initWithWindow:(NSWindow*)ref - native:(GUI::NativeWindowCocoa*)_native -{ - [super init]; - - native = _native; - window = ref; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(windowDidResize) - name:NSWindowDidResizeNotification - object:ref]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(windowWillResize) - name:NSWindowWillStartLiveResizeNotification - object:ref]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(windowWillClose) - name:NSWindowWillCloseNotification - object:ref]; - - [self windowWillResize]; // trigger to get the initial size as a size change - - return self; -} - -- (void) dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; -} - -- (void)windowDidResize -{ - if(!native) - { - return; - } - - native->resized(); -} - -- (void)windowWillResize -{ - if(!native) - { - return; - } - - native->resized(); -} - -- (void) windowWillClose -{ - if(!native) - { - return; - } - - auto closeEvent = std::make_shared(); - native->pushBackEvent(closeEvent); -} - -- (void) unbindNative -{ - native = nullptr; -} -@end - -@interface DGView : NSView -{ - int colorBits; - int depthBits; - -@private - GUI::NativeWindowCocoa* native; - NSTrackingArea* trackingArea; -} - -//- (id) initWithFrame:(NSRect)frame -// colorBits:(int)numColorBits -// depthBits:(int)numDepthBits; -- (void) updateTrackingAreas; - -- (void) mouseEntered:(NSEvent *)event; -- (void) mouseExited:(NSEvent *)event; -- (void) mouseMoved:(NSEvent*)event; -- (void) mouseDown:(NSEvent*)event; -- (void) mouseUp:(NSEvent*)event; -- (void) rightMouseDown:(NSEvent*)event; -- (void) rightMouseUp:(NSEvent*)event; -- (void) otherMouseDown:(NSEvent*)event; -- (void) otherMouseUp:(NSEvent*)event; -- (void) mouseDragged:(NSEvent*)event; -- (void) rightMouseDragged:(NSEvent*)event; -- (void) otherMouseDragged:(NSEvent*)event; -- (void) scrollWheel:(NSEvent*)event; -- (void) keyDown:(NSEvent*)event; -- (void) keyUp:(NSEvent*)event; - -- (void) dealloc; -- (void) bindNative:(GUI::NativeWindowCocoa*)native; -- (void) unbindNative; -@end - -@implementation DGView -//- (id) initWithFrame:(NSRect)frame -// colorBits:(int)numColorBits -// depthBits:(int)numDepthBits -//{ -// [super init]; -// [self updateTrackingAreas]; -// return self; -//} - -- (void) updateTrackingAreas -{ - if(trackingArea != nil) - { - [self removeTrackingArea:trackingArea]; - [trackingArea release]; - } - - int opts = - NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved | - NSTrackingActiveAlways; - - trackingArea = - [[NSTrackingArea alloc] initWithRect:[self bounds] - options:opts - owner:self - userInfo:nil]; - [self addTrackingArea:trackingArea]; -} - -- (void) mouseEntered:(NSEvent *)event -{ - [super mouseEntered:event]; - auto frame = [self frame]; - NSPoint loc = [event locationInWindow]; - auto mouseEnterEvent = std::make_shared(); - mouseEnterEvent->x = loc.x - frame.origin.x; - mouseEnterEvent->y = frame.size.height - loc.y - frame.origin.y; - native->pushBackEvent(mouseEnterEvent); - //[[NSCursor pointingHandCursor] set]; -} - -- (void) mouseExited:(NSEvent *)event -{ - [super mouseExited:event]; - auto frame = [self frame]; - NSPoint loc = [event locationInWindow]; - auto mouseLeaveEvent = std::make_shared(); - mouseLeaveEvent->x = loc.x - frame.origin.x; - mouseLeaveEvent->y = frame.size.height - loc.y - frame.origin.y; - native->pushBackEvent(mouseLeaveEvent); - //[[NSCursor arrowCursor] set]; -} - -- (void) mouseMoved:(NSEvent*)event -{ - auto frame = [self frame]; - NSPoint loc = [event locationInWindow]; - auto mouseMoveEvent = std::make_shared(); - mouseMoveEvent->x = loc.x - frame.origin.x; - mouseMoveEvent->y = frame.size.height - loc.y - frame.origin.y; - native->pushBackEvent(mouseMoveEvent); -} - -- (void) mouseDown:(NSEvent*)event -{ - auto frame = [self frame]; - NSPoint loc = [event locationInWindow]; - - auto buttonEvent = std::make_shared(); - buttonEvent->x = loc.x - frame.origin.x; - buttonEvent->y = frame.size.height - loc.y - frame.origin.y; - switch((int)[event buttonNumber]) - { - case 0: - buttonEvent->button = GUI::MouseButton::left; - break; - case 1: - buttonEvent->button = GUI::MouseButton::right; - break; - case 2: - buttonEvent->button = GUI::MouseButton::middle; - break; - default: - return; - } - buttonEvent->direction = GUI::Direction::down; - buttonEvent->doubleClick = [event clickCount] == 2; - native->pushBackEvent(buttonEvent); - - [super mouseDown: event]; -} - -- (void) mouseUp:(NSEvent*)event -{ - auto frame = [self frame]; - NSPoint loc = [event locationInWindow]; - - auto buttonEvent = std::make_shared(); - buttonEvent->x = loc.x - frame.origin.x; - buttonEvent->y = frame.size.height - loc.y - frame.origin.y; - switch((int)[event buttonNumber]) - { - case 0: - buttonEvent->button = GUI::MouseButton::left; - break; - case 1: - buttonEvent->button = GUI::MouseButton::right; - break; - case 2: - buttonEvent->button = GUI::MouseButton::middle; - break; - default: - return; - } - buttonEvent->direction = GUI::Direction::up; - buttonEvent->doubleClick = false; - native->pushBackEvent(buttonEvent); - - [super mouseUp: event]; -} - -- (void) rightMouseDown:(NSEvent*)event -{ - [self mouseDown: event]; - [super rightMouseDown: event]; -} - -- (void) rightMouseUp:(NSEvent*)event -{ - [self mouseUp: event]; - [super rightMouseUp: event]; -} - -- (void) otherMouseDown:(NSEvent*)event -{ - [self mouseDown: event]; - [super otherMouseDown: event]; -} - -- (void) otherMouseUp:(NSEvent*)event -{ - [self mouseUp: event]; - [super otherMouseUp: event]; -} - -- (void) mouseDragged:(NSEvent*)event -{ - [self mouseMoved: event]; - [super mouseDragged: event]; -} - -- (void) rightMouseDragged:(NSEvent*)event -{ - [self mouseMoved: event]; - [super rightMouseDragged: event]; -} - -- (void) otherMouseDragged:(NSEvent*)event -{ - [self mouseMoved: event]; - [super otherMouseDragged: event]; -} - -- (void) scrollWheel:(NSEvent*)event -{ - auto frame = [self frame]; - NSPoint loc = [event locationInWindow]; - - auto scrollEvent = std::make_shared(); - scrollEvent->x = loc.x - frame.origin.x; - scrollEvent->y = frame.size.height - loc.y - frame.origin.y; - scrollEvent->delta = [event deltaY] * -1.0f; - native->pushBackEvent(scrollEvent); - - [super scrollWheel: event]; -} - -- (void) keyDown:(NSEvent*)event -{ - const NSString* chars = [event characters]; - const char* str = [chars UTF8String]; - - auto keyEvent = std::make_shared(); - - switch([event keyCode]) - { - case 123: keyEvent->keycode = GUI::Key::left; break; - case 124: keyEvent->keycode = GUI::Key::right; break; - case 126: keyEvent->keycode = GUI::Key::up; break; - case 125: keyEvent->keycode = GUI::Key::down; break; - case 117: keyEvent->keycode = GUI::Key::deleteKey; break; - case 51: keyEvent->keycode = GUI::Key::backspace; break; - case 115: keyEvent->keycode = GUI::Key::home; break; - case 119: keyEvent->keycode = GUI::Key::end; break; - case 121: keyEvent->keycode = GUI::Key::pageDown; break; - case 116: keyEvent->keycode = GUI::Key::pageUp; break; - case 36: keyEvent->keycode = GUI::Key::enter; break; - default: keyEvent->keycode = GUI::Key::unknown; break; - } - - if(strlen(str) && keyEvent->keycode == GUI::Key::unknown) - { - keyEvent->keycode = GUI::Key::character; - } - - keyEvent->text = str; // TODO: UTF8 decode - keyEvent->direction = GUI::Direction::down; - - native->pushBackEvent(keyEvent); - [super keyDown: event]; -} - -- (void) keyUp:(NSEvent*)event -{ - const NSString* chars = [event characters]; - const char* str = [chars UTF8String]; - auto keyEvent = std::make_shared(); - - switch([event keyCode]) - { - case 123: keyEvent->keycode = GUI::Key::left; break; - case 124: keyEvent->keycode = GUI::Key::right; break; - case 126: keyEvent->keycode = GUI::Key::up; break; - case 125: keyEvent->keycode = GUI::Key::down; break; - case 117: keyEvent->keycode = GUI::Key::deleteKey; break; - case 51: keyEvent->keycode = GUI::Key::backspace; break; - case 115: keyEvent->keycode = GUI::Key::home; break; - case 119: keyEvent->keycode = GUI::Key::end; break; - case 121: keyEvent->keycode = GUI::Key::pageDown; break; - case 116: keyEvent->keycode = GUI::Key::pageUp; break; - case 36: keyEvent->keycode = GUI::Key::enter; break; - default: keyEvent->keycode = GUI::Key::unknown; break; - } - - if(strlen(str) && keyEvent->keycode == GUI::Key::unknown) - { - keyEvent->keycode = GUI::Key::character; - } - - keyEvent->text = str; // TODO: UTF8 decode - keyEvent->direction = GUI::Direction::up; - - native->pushBackEvent(keyEvent); - [super keyUp: event]; -} - -- (void) dealloc -{ - [super dealloc]; -} - -- (void)bindNative:(GUI::NativeWindowCocoa*)_native -{ - native = _native; -} - -- (void) unbindNative -{ - native = nullptr; -} -@end - - -namespace GUI -{ - -struct priv -{ - NSWindow* window; - DGView* view; - id listener; - id parent_view; - std::uint8_t* pixel_buffer{nullptr}; - std::size_t pixel_buffer_width{0}; - std::size_t pixel_buffer_height{0}; -}; - -NativeWindowCocoa::NativeWindowCocoa(void* native_window, Window& window) - : window(window) - , priv(new struct priv()) - , native_window(native_window) -{ - [NSAutoreleasePool new]; - [NSApplication sharedApplication]; - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - - priv->view = [DGView new]; - - [priv->view bindNative:this]; - - if(native_window) - { - if(sizeof(std::size_t) == sizeof(unsigned int)) // 32 bit machine - { - WindowRef ptr = (WindowRef)native_window; - priv->window = [[[NSWindow alloc] initWithWindowRef:ptr] retain]; - priv->parent_view = [priv->window contentView]; - } - else // 64 bit machine - { - priv->parent_view = (NSView*)native_window; - priv->window = [priv->parent_view window]; - } - - [priv->parent_view addSubview:priv->view]; - [priv->view display]; - [priv->parent_view setNeedsDisplay:YES]; - } - else - { - priv->window = - [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 10, 10) - styleMask:STYLE_MASK - backing:NSBackingStoreBuffered - defer:NO] - retain]; - [priv->window setLevel:NSStatusWindowLevel]; - } - - priv->listener = - [[[DGListener alloc] initWithWindow:priv->window - native:this] - retain]; - - if(native_window) - { - [[priv->window contentView] addSubview:priv->view]; - } - else - { - [priv->window setReleasedWhenClosed:NO]; - [priv->window setContentView:priv->view]; - } - - scale = [[NSScreen mainScreen] backingScaleFactor]; - - [priv->view setWantsLayer:YES]; - [priv->view setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft]; - [priv->view updateTrackingAreas]; - - if(!native_window) - { - hide(); - } -} - -NativeWindowCocoa::~NativeWindowCocoa() -{ - // Make the garbage collector able to collect the ObjC objects: - if(visible()) - { - hide(); - } - - [priv->listener unbindNative]; - [priv->listener release]; - - [priv->view unbindNative]; - [priv->view release]; - - if(native_window) - { - if(sizeof(std::size_t) == sizeof(unsigned int)) // 32 bit machine - { - [priv->window release]; - } - else - { - // in 64-bit the window was not created by us - } - } - else - { - [priv->window release]; - } -} - -void NativeWindowCocoa::setFixedSize(std::size_t width, std::size_t height) -{ - resize(width, height); - [priv->window setMinSize:NSMakeSize(width, height + 22)]; - [priv->window setMaxSize:NSMakeSize(width, height + 22)]; -} - -void NativeWindowCocoa::setAlwaysOnTop(bool always_on_top) -{ - if(always_on_top) - { - [priv->window setLevel: NSStatusWindowLevel]; - } - else - { - [priv->window setLevel: NSNormalWindowLevel]; - } -} - -void NativeWindowCocoa::resize(std::size_t width, std::size_t height) -{ - [priv->window setContentSize:NSMakeSize(width, height)]; -} - -std::pair NativeWindowCocoa::getSize() const -{ - if(native_window) - { - auto frame = [priv->parent_view frame]; - return {frame.size.width, frame.size.height - frame.origin.y}; - } - else - { - NSSize size = [priv->view frame].size; - return {size.width, size.height}; - } -} - -void NativeWindowCocoa::move(int x, int y) -{ - NSRect screen = [[NSScreen mainScreen] frame]; - [priv->window setFrameTopLeftPoint:NSMakePoint(x, screen.size.height - y)]; -} - -std::pair NativeWindowCocoa::getPosition() const -{ - NSRect screen = [[NSScreen mainScreen] frame]; - NSPoint pos = [[priv->window contentView] frame].origin; - return {pos.x, screen.size.height - pos.y}; -} - -void NativeWindowCocoa::show() -{ - if(!native_window) - { - [priv->window makeKeyAndOrderFront:priv->window]; - [NSApp activateIgnoringOtherApps:YES]; - } -} - -void NativeWindowCocoa::hide() -{ - if(!native_window) - { - [priv->window orderOut:priv->window]; - } -} - -bool NativeWindowCocoa::visible() const -{ - return [priv->window isVisible]; -} - -void NativeWindowCocoa::redraw(const Rect& dirty_rect) -{ - NSSize size; - if(native_window) - { - size = [priv->parent_view frame].size; - } - else - { - size = [priv->view frame].size; - } - - std::size_t width = size.width; - std::size_t height = size.height; - - if(priv->pixel_buffer == nullptr || - priv->pixel_buffer_width != width || - priv->pixel_buffer_height != height) - { - if(priv->pixel_buffer) delete[] priv->pixel_buffer; - priv->pixel_buffer = new std::uint8_t[width * height * 4]; - priv->pixel_buffer_width = width; - priv->pixel_buffer_height = height; - } - - CGColorSpaceRef rgb = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - CGContextRef gc = - CGBitmapContextCreate(priv->pixel_buffer, width, height, - 8, width * 4, rgb, - IMAGE_FLAGS); - CGColorSpaceRelease(rgb); - - size_t pitch = CGBitmapContextGetBytesPerRow(gc); - uint8_t *buffer = (uint8_t *)CGBitmapContextGetData(gc); - - struct Pixel - { - std::uint8_t red; - std::uint8_t green; - std::uint8_t blue; - std::uint8_t alpha; - }; - std::uint8_t* pixels = window.wpixbuf.buf; - for(std::size_t y = dirty_rect.y1; y < std::min(dirty_rect.y2, height); ++y) - { - Pixel *row = (Pixel *)(buffer + y * pitch); - for(std::size_t x = dirty_rect.x1; x < std::min(dirty_rect.x2, width); ++x) - { - row[x] = *(Pixel*)&pixels[(y * width + x) * 3]; - row[x].alpha = 0xff; - } - } - CGImageRef image = CGBitmapContextCreateImage(gc); - CGContextRelease(gc); - - auto nsImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize]; - - id layerContents = [nsImage layerContentsForContentsScale:scale]; - [[priv->view layer] setContents:layerContents]; - updateLayerOffset(); - [[priv->view layer] setContentsScale:scale]; -} - -void NativeWindowCocoa::setCaption(const std::string &caption) -{ - NSString* title = - [NSString stringWithCString:caption.data() - encoding:[NSString defaultCStringEncoding]]; - [priv->window setTitle:title]; -} - -void NativeWindowCocoa::grabMouse(bool grab) -{ -} - -void NativeWindowCocoa::updateLayerOffset() -{ - if(native_window) - { - //auto r1 = [priv->parent_view frame]; - auto r2 = [priv->view frame]; - - CATransform3D t = [[priv->view layer] transform]; - if(t.m42 != -r2.origin.y) - { - t.m42 = -r2.origin.y; // y - [[priv->view layer] setTransform:t]; - } - } -} - -EventQueue NativeWindowCocoa::getEvents() -{ - if(first) - { - resized(); - first = false; - } - - // If this is the root window, process the events - event processing will - // be handled by the hosting window if the window is embedded. - if(!native_window) - { - NSEvent* event = nil; - do - { - event = [NSApp nextEventMatchingMask:EVENT_MASK - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - [NSApp sendEvent:event]; - } - while(event != nil); - } - - EventQueue events; - std::swap(events, event_queue); - return events; -} - -void* NativeWindowCocoa::getNativeWindowHandle() const -{ - if(sizeof(std::size_t) == sizeof(unsigned int)) // 32 bit machine - { - return [priv->window windowRef]; - } - else // 64 bit machine - { - return [priv->window contentView]; - } -} - -Point NativeWindowCocoa::translateToScreen(const Point& point) -{ - NSRect e = [[NSScreen mainScreen] frame]; - NSRect frame; - if(native_window) - { - frame = [priv->parent_view frame]; - } - else - { - frame = [priv->view frame]; - } - - NSRect rect { { point.x + frame.origin.x, - frame.size.height - point.y + frame.origin.y}, - {0.0, 0.0} }; - rect = [priv->window convertRectToScreen:rect]; - - return { (int)rect.origin.x, (int)(e.size.height - rect.origin.y) }; -} - -Window& NativeWindowCocoa::getWindow() -{ - return window; -} - -PixelBuffer& NativeWindowCocoa::getWindowPixbuf() -{ - window.updateBuffer(); - return window.wpixbuf; -} - -void NativeWindowCocoa::resized() -{ - if(native_window) - { - NSRect frame = [priv->parent_view frame]; - [priv->view setFrame:frame]; - [priv->view updateTrackingAreas]; - updateLayerOffset(); - } - - auto resizeEvent = std::make_shared(); - resizeEvent->width = 42; // size is not actually used - resizeEvent->height = 42; // size is not actually used - pushBackEvent(resizeEvent); -} - -void NativeWindowCocoa::pushBackEvent(std::shared_ptr event) -{ - event_queue.push_back(event); -} - -} // GUI:: diff --git a/plugingui/nativewindow_pugl.cc b/plugingui/nativewindow_pugl.cc deleted file mode 100644 index f94b82b..0000000 --- a/plugingui/nativewindow_pugl.cc +++ /dev/null @@ -1,382 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_pugl.cc - * - * Fri Dec 28 18:45:57 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "nativewindow_pugl.h" - -#include -#include - -#ifdef __APPLE__ -#include -#else -#include -#include -#include -#endif - -#include "window.h" -#include "guievent.h" - -#include - -namespace GUI -{ - -NativeWindowPugl::NativeWindowPugl(void* native_window, Window& window) - : window(window) -{ - INFO(nativewindow, "Running with PuGL native window\n"); - view = puglInit(nullptr, nullptr); - puglInitContextType(view, PUGL_GL); - if(native_window) - { - puglInitWindowParent(view, (PuglNativeWindow)native_window); - } - puglInitWindowClass(view, "DrumgGizmo"); - puglInitWindowSize(view, 750, 466); - puglInitResizable(view, true); - puglCreateWindow(view, "DrumGizmo"); - - puglSetHandle(view, (PuglHandle)this); - puglSetEventFunc(view, onEvent); -} - -NativeWindowPugl::~NativeWindowPugl() -{ - puglDestroy(view); -} - -void NativeWindowPugl::setFixedSize(std::size_t width, std::size_t height) -{ -// redraw(); -} - -void NativeWindowPugl::resize(std::size_t width, std::size_t height) -{ -// DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height); -// init(); -// redraw(); -} - -std::pair NativeWindowPugl::getSize() const -{ - int width, height; - puglGetSize(view, &width, &height); - return {width, height}; -} - -void NativeWindowPugl::move(int x, int y) -{ -// redraw(); -} - -void NativeWindowPugl::show() -{ - puglShowWindow(view); -} - -void NativeWindowPugl::hide() -{ - puglHideWindow(view); -} - -bool NativeWindowPugl::visible() const -{ - return puglGetVisible(view); -} - -void NativeWindowPugl::redraw(const Rect& dirty_rect) -{ - //puglPostRedisplay(view);// handleBuffer(); - onDisplay(view); -} - -void NativeWindowPugl::setCaption(const std::string &caption) -{ -// redraw(); -} - -void NativeWindowPugl::grabMouse(bool grab) -{ - puglGrabFocus(view); -} - -EventQueue NativeWindowPugl::getEvents() -{ - puglProcessEvents(view); - EventQueue events; - std::swap(events, event_queue); - return events; -} - -void* NativeWindowPugl::getNativeWindowHandle() const -{ - return (void*)puglGetNativeWindow(view); -} - -void NativeWindowPugl::onEvent(PuglView* view, const PuglEvent* event) -{ - NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); - - switch(event->type) - { - case PUGL_NOTHING: - break; - case PUGL_CONFIGURE: - onReshape(view, event->configure.width, event->configure.height); - { - auto resize_event = std::make_shared(); - resize_event->width = event->configure.width; - resize_event->height = event->configure.height; - native->event_queue.push_back(resize_event); - } - break; - case PUGL_EXPOSE: - onDisplay(view); - break; - case PUGL_CLOSE: - //quit = 1; - break; - case PUGL_KEY_PRESS: - fprintf(stderr, "Key %u (char %u) press (%s)%s\n", - event->key.keycode, event->key.character, event->key.utf8, - event->key.filter ? " (filtered)" : ""); - if (event->key.character == 'q' || - event->key.character == 'Q' || - event->key.character == PUGL_CHAR_ESCAPE) { - //quit = 1; - } - break; - case PUGL_KEY_RELEASE: - fprintf(stderr, "Key %u (char %u) release (%s)%s\n", - event->key.keycode, event->key.character, event->key.utf8, - event->key.filter ? " (filtered)" : ""); - break; - case PUGL_MOTION_NOTIFY: - { - auto mouseMoveEvent = std::make_shared(); - mouseMoveEvent->x = event->motion.x; - mouseMoveEvent->y = event->motion.y; - native->event_queue.push_back(mouseMoveEvent); - } - break; - case PUGL_BUTTON_PRESS: - case PUGL_BUTTON_RELEASE: - { - auto buttonEvent = std::make_shared(); - buttonEvent->x = event->button.x; - buttonEvent->y = event->button.y; - switch(event->button.button) { - case 1: - buttonEvent->button = MouseButton::left; - break; - case 2: - buttonEvent->button = MouseButton::middle; - break; - case 3: - buttonEvent->button = MouseButton::right; - break; - default: - WARN(X11, "Unknown button %d, setting to MouseButton::left\n", - event->button.button); - buttonEvent->button = MouseButton::left; - break; - } - - buttonEvent->direction = - (event->type == PUGL_BUTTON_PRESS) ? - Direction::down : Direction::up; - - buttonEvent->doubleClick = - (event->type == PUGL_BUTTON_PRESS) && - ((event->button.time - native->last_click) < 200); - - if(event->type == PUGL_BUTTON_PRESS) - { - native->last_click = event->button.time; - } - native->event_queue.push_back(buttonEvent); - } - fprintf(stderr, "Mouse %d %s at %f,%f ", - event->button.button, - (event->type == PUGL_BUTTON_PRESS) ? "down" : "up", - event->button.x, - event->button.y); - ///printModifiers(view, event->scroll.state); - break; - case PUGL_SCROLL: - { - auto scrollEvent = std::make_shared(); - scrollEvent->x = event->scroll.x; - scrollEvent->y = event->scroll.y; - scrollEvent->delta = event->scroll.dy * -1;//scroll * ((xevent.xbutton.button == 4) ? -1 : 1); - native->event_queue.push_back(scrollEvent); - } - fprintf(stderr, "Scroll %f %f %f %f ", - event->scroll.x, event->scroll.y, event->scroll.dx, event->scroll.dy); - //printModifiers(view, event->scroll.state); - //dist += event->scroll.dy; - //if (dist < 10.0f) { - // dist = 10.0f; - //} - puglPostRedisplay(view); - break; - case PUGL_ENTER_NOTIFY: - fprintf(stderr, "Entered\n"); - break; - case PUGL_LEAVE_NOTIFY: - fprintf(stderr, "Exited\n"); - break; - case PUGL_FOCUS_IN: - fprintf(stderr, "Focus in\n"); - break; - case PUGL_FOCUS_OUT: - fprintf(stderr, "Focus out\n"); - break; - } -} - -void NativeWindowPugl::onReshape(PuglView* view, int width, int height) -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glViewport(0, 0, width, height); -} - -void NativeWindowPugl::onDisplay(PuglView* view) -{ - NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); - Window& window = native->window; - //window.redraw(); - - if((window.wpixbuf.width < 16) || (window.wpixbuf.height < 16)) - { - return; - } - - puglEnterContext(view); - - glDisable(GL_DEPTH_TEST); - glClear(GL_COLOR_BUFFER_BIT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, 0.0f); - - GLuint image; - - glGenTextures(1, &image); - - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, - 0, GL_RGBA, - window.wpixbuf.width, - window.wpixbuf.height, - 0, GL_RGB, GL_UNSIGNED_BYTE, - window.wpixbuf.buf); - - glEnable(GL_TEXTURE_2D); - - glBegin(GL_QUADS); - glTexCoord2d(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); - glTexCoord2d(0.0f, -1.0f); glVertex2f(-1.0f, 1.0f); - glTexCoord2d(1.0f, -1.0f); glVertex2f( 1.0f, 1.0f); - glTexCoord2d(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); - glEnd(); - - glDeleteTextures(1, &image); - glDisable(GL_TEXTURE_2D); - glFlush(); - - puglLeaveContext(view, true); -} - -void NativeWindowPugl::onMouse(PuglView* view, int button, bool press, int x, int y) -{ - NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); - - DEBUG(nativewindow_pugl, "Mouse %d %s at (%d,%d)\n", button, - press? "down":"up", x, y); - - ButtonEvent* e = new ButtonEvent(); - e->x = x; - e->y = y; - - switch(button) { - case 1: - e->button = MouseButton::left; - break; - case 2: - e->button = MouseButton::middle; - break; - case 3: - default: - e->button = MouseButton::right; - break; - } - - e->direction = press ? Direction::down : Direction::up; - e->doubleClick = false; - - native->eventq.push_back(e); -} - -void NativeWindowPugl::onKeyboard(PuglView* view, bool press, uint32_t key) -{ - NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); - - KeyEvent* e = new KeyEvent(); - e->direction = press ? Direction::down : Direction::up; - - switch(key) - { - case PUGL_KEY_LEFT: e->keycode = Key::left; break; - case PUGL_KEY_RIGHT: e->keycode = Key::right; break; - case PUGL_KEY_UP: e->keycode = Key::up; break; - case PUGL_KEY_DOWN: e->keycode = Key::down; break; - case PUGL_KEY_PAGE_UP: e->keycode = Key::pageDown; break; - case PUGL_KEY_PAGE_DOWN: e->keycode = Key::pageUp; break; - default: e->keycode = Key::unknown; break; - } - - // TODO: perform character type check - if(e->keycode == Key::unknown) - { - e->keycode = Key::character; - e->text.assign(1, (char)key); - } - - native->eventq.push_back(e); -} - -} // GUI:: diff --git a/plugingui/nativewindow_pugl.h b/plugingui/nativewindow_pugl.h deleted file mode 100644 index 6a667f4..0000000 --- a/plugingui/nativewindow_pugl.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_pugl.h - * - * Fri Dec 28 18:45:56 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "nativewindow.h" -extern "C" -{ -#include -} - -#include - -namespace GUI -{ - -class Event; -class Window; - -class NativeWindowPugl : public NativeWindow { -public: - NativeWindowPugl(void* native_window, Window& window); - ~NativeWindowPugl(); - - void setFixedSize(std::size_t width, std::size_t height) override; - void resize(std::size_t width, std::size_t height) override; - std::pair getSize() const override; - - void move(int x, int y) override; - std::pair getPosition() const override{ return {}; } - - void show() override; - void setCaption(const std::string &caption) override; - void hide() override; - bool visible() const override; - void redraw(const Rect& dirty_rect) override; - void grabMouse(bool grab) override; - - EventQueue getEvents() override; - - void* getNativeWindowHandle() const override; - -private: - Window& window; - PuglView* view{nullptr}; - - std::list eventq; - - // Internal pugl c-callbacks - static void onEvent(PuglView* view, const PuglEvent* event); - static void onReshape(PuglView* view, int width, int height); - static void onDisplay(PuglView* view); - static void onMouse(PuglView* view, int button, bool press, int x, int y); - static void onKeyboard(PuglView* view, bool press, uint32_t key); - - EventQueue event_queue; - std::uint32_t last_click{0}; -}; - -} // GUI:: diff --git a/plugingui/nativewindow_win32.cc b/plugingui/nativewindow_win32.cc deleted file mode 100644 index 4b31130..0000000 --- a/plugingui/nativewindow_win32.cc +++ /dev/null @@ -1,584 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_win32.cc - * - * Fri Dec 28 18:45:52 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "nativewindow_win32.h" - -#include -#include -#include - -#include "window.h" - -namespace GUI -{ - -static BOOL trackMouse(HWND hwnd) -{ - TRACKMOUSEEVENT ev{}; - ev.cbSize = sizeof(ev); - ev.dwFlags = TME_HOVER | TME_LEAVE; - ev.hwndTrack = hwnd; - ev.dwHoverTime = 1; - return TrackMouseEvent(&ev); -} - -LRESULT CALLBACK NativeWindowWin32::dialogProc(HWND hwnd, UINT msg, - WPARAM wp, LPARAM lp) -{ - NativeWindowWin32* native = - (NativeWindowWin32*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled. - if(!native) - { - return DefWindowProc(hwnd, msg, wp, lp); - } - - Window& window = native->window; - - switch(msg) - { - case WM_SIZE: - if(wp > 4) - { - // Bogus value - ignore - break; - } - { - auto resizeEvent = std::make_shared(); - resizeEvent->width = LOWORD(lp); - resizeEvent->height = HIWORD(lp); - native->event_queue.push_back(resizeEvent); - } - break; - - case WM_MOVE: - { - auto moveEvent = std::make_shared(); - moveEvent->x = (short)LOWORD(lp); - moveEvent->y = (short)HIWORD(lp); - native->event_queue.push_back(moveEvent); - } - break; - - case WM_CLOSE: - { - auto closeEvent = std::make_shared(); - native->event_queue.push_back(closeEvent); - } - return 0; // Do not call DefWindowProc for this event. -// HWND child, old; -// old = 0; - -// numDialogs--; - -// while(old != (child = GetNextDlgGroupItem(hwnd, hwnd, false))) { -// old = child; -// EndDialog(child, 0); -// } - -// if(numDialogs) EndDialog(hwnd, 0); -// else PostQuitMessage(0); -// return 0; - case WM_MOUSEMOVE: - { - trackMouse(native->m_hwnd); - auto mouseMoveEvent = std::make_shared(); - mouseMoveEvent->x = (short)LOWORD(lp); - mouseMoveEvent->y = (short)HIWORD(lp); - native->last_mouse_position = { mouseMoveEvent->x, mouseMoveEvent->y }; - - if(!native->mouse_in_window) - { - auto enterEvent = std::make_shared(); - enterEvent->x = native->last_mouse_position.first; - enterEvent->y = native->last_mouse_position.second; - native->event_queue.push_back(enterEvent); - native->mouse_in_window = true; - } - native->event_queue.push_back(mouseMoveEvent); - } - break; - - case WM_MOUSEWHEEL: - { - auto scrollEvent = std::make_shared(); - - // NOTE: lp is coordinates in screen space, not client space. - POINT p; - p.x = (short)LOWORD(lp); - p.y = (short)HIWORD(lp); - ScreenToClient(hwnd, &p); - - scrollEvent->x = p.x; - scrollEvent->y = p.y; - scrollEvent->delta = -1 * (short)HIWORD(wp) / 60.0f; - native->event_queue.push_back(scrollEvent); - } - break; - - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_RBUTTONUP: - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MBUTTONDBLCLK: - case WM_MBUTTONDOWN: - { - auto buttonEvent = std::make_shared(); - - buttonEvent->x = (short)LOWORD(lp); - buttonEvent->y = (short)HIWORD(lp); - - if(msg == WM_LBUTTONUP || - msg == WM_LBUTTONDBLCLK || - msg == WM_LBUTTONDOWN) - { - buttonEvent->button = MouseButton::left; - } - else if(msg == WM_MBUTTONUP || - msg == WM_MBUTTONDBLCLK || - msg == WM_MBUTTONDOWN) - { - buttonEvent->button = MouseButton::middle; - } - else if(msg == WM_RBUTTONUP || - msg == WM_RBUTTONDBLCLK || - msg == WM_RBUTTONDOWN) - { - buttonEvent->button = MouseButton::right; - } - else - { - break; // unknown button - } - - // Double-clicking the a mouse button actually generates a sequence - // of four messages: WM_xBUTTONDOWN, WM_xBUTTONUP, WM_xBUTTONDBLCLK, and - // WM_xBUTTONUP. In other words the second WM_xBUTTONDOWN is replaced by a - // WM_xBUTTONDBLCLK. We simply 'return it' as a WM_xBUTTONDOWN but set the - // doubleClick boolean hint accordingly. - if(msg == WM_LBUTTONUP || - msg == WM_RBUTTONUP || - msg == WM_MBUTTONUP) - { - buttonEvent->direction = Direction::up; - } - else if(msg == WM_LBUTTONDOWN || - msg == WM_RBUTTONDOWN || - msg == WM_MBUTTONDOWN || - msg == WM_LBUTTONDBLCLK || - msg == WM_RBUTTONDBLCLK || - msg == WM_MBUTTONDBLCLK) - { - buttonEvent->direction = Direction::down; - } - - buttonEvent->doubleClick = (msg == WM_LBUTTONDBLCLK || - msg == WM_RBUTTONDBLCLK || - msg == WM_MBUTTONDBLCLK); - - native->event_queue.push_back(buttonEvent); - } - break; - - case WM_KEYDOWN: - case WM_KEYUP: - { - auto keyEvent = std::make_shared(); - - switch(wp) { - case VK_LEFT: keyEvent->keycode = Key::left; break; - case VK_RIGHT: keyEvent->keycode = Key::right; break; - case VK_UP: keyEvent->keycode = Key::up; break; - case VK_DOWN: keyEvent->keycode = Key::down; break; - case VK_BACK: keyEvent->keycode = Key::backspace; break; - case VK_DELETE: keyEvent->keycode = Key::deleteKey; break; - case VK_HOME: keyEvent->keycode = Key::home; break; - case VK_END: keyEvent->keycode = Key::end; break; - case VK_PRIOR: keyEvent->keycode = Key::pageUp; break; - case VK_NEXT: keyEvent->keycode = Key::pageDown; break; - case VK_RETURN: keyEvent->keycode = Key::enter; break; - default: keyEvent->keycode = Key::unknown; break; - } - - keyEvent->text = ""; - keyEvent->direction = - (msg == WM_KEYDOWN) ? Direction::down : Direction::up; - - native->event_queue.push_back(keyEvent); - } - break; - - case WM_CHAR: - { - if(wp >= ' ') // Filter control chars. - { - auto keyEvent = std::make_shared(); - keyEvent->keycode = Key::character; - keyEvent->text += (char)wp; - keyEvent->direction = Direction::up; - native->event_queue.push_back(keyEvent); - } - } - break; - - case WM_PAINT: - { - RECT rect; - GetUpdateRect(hwnd, &rect, FALSE); - - // Bypass partial update, which is apparrently broken. - rect.left = 0; - rect.top = 0; - rect.right = window.wpixbuf.width; - rect.bottom = window.wpixbuf.height; - - auto repaintEvent = std::make_shared(); - repaintEvent->x = rect.left; - repaintEvent->y = rect.top; - repaintEvent->width = rect.right - rect.left; - repaintEvent->height = rect.bottom - rect.top; - native->event_queue.push_back(repaintEvent); - - // Move to window.h (in class) - HDC pDC; - HBITMAP old; - HBITMAP ourbitmap; - int* framebuf; - PixelBuffer& px = window.wpixbuf; - - { // Create bitmap - HDC hDC; - BITMAPINFO bitmapinfo; - hDC = CreateCompatibleDC(nullptr); - bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bitmapinfo.bmiHeader.biWidth = px.width; - bitmapinfo.bmiHeader.biHeight = -px.height; // top-down - bitmapinfo.bmiHeader.biPlanes = 1; - bitmapinfo.bmiHeader.biBitCount = 32; - bitmapinfo.bmiHeader.biCompression = BI_RGB; - bitmapinfo.bmiHeader.biSizeImage = 0; - bitmapinfo.bmiHeader.biClrUsed = 256; - bitmapinfo.bmiHeader.biClrImportant = 256; - ourbitmap = CreateDIBSection(hDC, &bitmapinfo, - DIB_RGB_COLORS, (void**)&framebuf, 0, 0); - pDC=CreateCompatibleDC(nullptr); - old = (HBITMAP__*)SelectObject(pDC, ourbitmap); - DeleteDC(hDC); - } - - int from_x = rect.left; - int to_x = std::min(rect.right, (long)px.width); - int from_y = rect.top; - int to_y = std::min(rect.bottom, (long)px.height); - { // Copy PixelBuffer to framebuffer - int idx = 0; - for(int y = from_y; y < to_y; ++y) - { - for(int x = from_x; x < to_x; ++x) - { - *(framebuf + idx) = RGB(px.buf[(x + y * px.width) * 3 + 2], - px.buf[(x + y * px.width) * 3 + 1], - px.buf[(x + y * px.width) * 3 + 0]); - ++idx; - } - } - } - - PAINTSTRUCT ps; - HDC hdc = BeginPaint(native->m_hwnd, &ps); - BitBlt(hdc, from_x, from_y, to_x, to_y, pDC, from_x, from_y, SRCCOPY); - EndPaint(native->m_hwnd, &ps); - - { // Destroy bitmap (move to window.cc) - SelectObject(pDC,old); - DeleteDC(pDC); - DeleteObject(ourbitmap); - } - } - break; - - case WM_MOUSELEAVE: - { - auto leaveEvent = std::make_shared(); - leaveEvent->x = native->last_mouse_position.first; - leaveEvent->y = native->last_mouse_position.second; - native->event_queue.push_back(leaveEvent); - native->mouse_in_window = false; - } - break; - } - - return DefWindowProc(hwnd, msg, wp, lp); -} - -LRESULT CALLBACK NativeWindowWin32::subClassProc(HWND hwnd, UINT msg, - WPARAM wp, LPARAM lp, - UINT_PTR id, DWORD_PTR data) -{ - NativeWindowWin32* native = (NativeWindowWin32*)data; - - // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled. - if(!native) - { - return DefWindowProc(hwnd, msg, wp, lp); - } - - switch(msg) - { - case WM_SIZE: - if(wp > 4) - { - // Bogus value - ignore - break; - } - { - // Parent window size changed, replicate this size in inner window. - int width = LOWORD(lp); - int height = HIWORD(lp); - SetWindowPos(native->m_hwnd, nullptr, -1, -1, width, height, SWP_NOMOVE); - } - break; - } - - return DefSubclassProc(hwnd, msg, wp, lp); -} - -NativeWindowWin32::NativeWindowWin32(void* native_window, Window& window) - : window(window) -{ - WNDCLASSEX wcex{}; - - //Time to register a window class. - //Generic flags and everything. cbWndExtra is the size of a pointer to an - // object - we need this in the wndproc handler. - - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_DBLCLKS;//class_style; - wcex.lpfnWndProc = (WNDPROC)dialogProc; - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - // Set data: - wcex.cbWndExtra = sizeof(NativeWindowWin32*); // Size of data. - wcex.hInstance = GetModuleHandle(nullptr); - - // if(ex_style && WS_EX_TRANSPARENT == WS_EX_TRANSPARENT) { - // wcex.hbrBackground = nullptr; - // } else { - wcex.hbrBackground = nullptr;//(HBRUSH) COLOR_BACKGROUND + 1; - // } - - const char* name = "DrumGizmoClass"; - char* c_name = (char*)malloc(strlen(name) + 1); - strcpy(c_name, name); - wcex.lpszClassName = m_className = c_name; - - RegisterClassEx(&wcex); - - parent_window = (HWND)native_window; - - int width = 1, height = 1; - if(parent_window) - { - // Listen in on parent size changes. - SetWindowSubclass(parent_window, subClassProc, 42, (LONG_PTR)this); - - // Resize newly created window to fit into parent. - RECT rect; - GetClientRect(parent_window, &rect); - - auto resizeEvent = std::make_shared(); - width = resizeEvent->width = rect.right - rect.left; - height = resizeEvent->height = rect.bottom - rect.top; - event_queue.push_back(resizeEvent); - } - - m_hwnd = CreateWindowEx(0/*ex_style*/, m_className, - "DGBasisWidget", - (native_window?WS_CHILD:WS_OVERLAPPEDWINDOW) | - (native_window?WS_VISIBLE:0), - 0, 0, - width, height, - parent_window, nullptr, - GetModuleHandle(nullptr), nullptr); - - SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); - - // Set up initial tracking of the mouse leave events - trackMouse(m_hwnd); -} - -NativeWindowWin32::~NativeWindowWin32() -{ - if(parent_window) - { - RemoveWindowSubclass(parent_window, subClassProc, 42); - } - DestroyWindow(m_hwnd); - UnregisterClass(m_className, GetModuleHandle(nullptr)); - free(m_className); -} - -void NativeWindowWin32::setFixedSize(std::size_t width, std::size_t height) -{ - resize(width, height); - LONG style = GetWindowLong(m_hwnd, GWL_STYLE); - style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); - SetWindowLong(m_hwnd, GWL_STYLE, style); -} - -void NativeWindowWin32::setAlwaysOnTop(bool always_on_top) -{ - this->always_on_top = always_on_top; - SetWindowPos(m_hwnd, always_on_top ? HWND_TOPMOST : nullptr, - 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); -} - -void NativeWindowWin32::resize(std::size_t width, std::size_t height) -{ - auto hwnd = m_hwnd; - //if(parent_window) - //{ - // hwnd = parent_window; - //} - - // Set requested size on the window (or parent) - SetWindowPos(hwnd, always_on_top ? HWND_TOPMOST : nullptr, - -1, -1, (int)width, (int)height, SWP_NOMOVE); - - // Ask the client window what size it actually got - RECT rect; - GetClientRect(m_hwnd, &rect); - int w = width - rect.right; - int h = height - rect.bottom; - - // Set the compensated size on the window (or parent) - SetWindowPos(hwnd, always_on_top ? HWND_TOPMOST : nullptr, - -1, -1, width + w, height + h, SWP_NOMOVE); -} - -std::pair NativeWindowWin32::getSize() const -{ - RECT rect; - GetClientRect(m_hwnd, &rect); - return std::make_pair(rect.right - rect.left, rect.bottom - rect.top); -} - -void NativeWindowWin32::move(int x, int y) -{ - SetWindowPos(m_hwnd, always_on_top ? HWND_TOPMOST : nullptr, - (int)x, (int)y, -1, -1, SWP_NOSIZE); -} - -std::pair NativeWindowWin32::getPosition() const -{ - RECT rect; - GetClientRect(m_hwnd, &rect); - return std::make_pair(rect.left, rect.top); -} - -void NativeWindowWin32::show() -{ - ShowWindow(m_hwnd, SW_SHOW); -} - -void NativeWindowWin32::hide() -{ - ShowWindow(m_hwnd, SW_HIDE); -} - -bool NativeWindowWin32::visible() const -{ - return IsWindowVisible(m_hwnd); -} - -void NativeWindowWin32::redraw(const Rect& dirty_rect) -{ - // Send WM_PAINT message. Buffer transfering is handled in MessageHandler. - if(parent_window == nullptr) - { - RECT rect = - { - (long)dirty_rect.x1, - (long)dirty_rect.y1, - (long)dirty_rect.x2, - (long)dirty_rect.y2 - }; - RedrawWindow(m_hwnd, &rect, nullptr, RDW_INVALIDATE); - UpdateWindow(m_hwnd); - } - else - { - InvalidateRect(m_hwnd, 0, TRUE); - } -} - -void NativeWindowWin32::setCaption(const std::string &caption) -{ - SetWindowText(m_hwnd, caption.c_str()); -} - -void NativeWindowWin32::grabMouse(bool grab) -{ - if(grab) - { - SetCapture(m_hwnd); - } - else - { - ReleaseCapture(); - } -} - -EventQueue NativeWindowWin32::getEvents() -{ - MSG msg; - while(PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE) != 0) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - EventQueue events; - std::swap(events, event_queue); - return events; -} - -void* NativeWindowWin32::getNativeWindowHandle() const -{ - return (void*)m_hwnd; -} - -Point NativeWindowWin32::translateToScreen(const Point& point) -{ - POINT p{ point.x, point.y }; - ClientToScreen(m_hwnd, &p); - return { p.x, p.y }; -} - -} // GUI:: diff --git a/plugingui/nativewindow_win32.h b/plugingui/nativewindow_win32.h deleted file mode 100644 index 046b38a..0000000 --- a/plugingui/nativewindow_win32.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_win32.h - * - * Fri Dec 28 18:45:51 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "nativewindow.h" - -#define WIN32_LEAN_AND_MEAN -#include -typedef HWND WNDID; - -namespace GUI { - -class Window; -class Event; - -class NativeWindowWin32 : public NativeWindow { -public: - NativeWindowWin32(void* native_window, Window& window); - ~NativeWindowWin32(); - - void setFixedSize(std::size_t width, std::size_t height) override; - void setAlwaysOnTop(bool always_on_top) override; - void resize(std::size_t width, std::size_t height) override; - std::pair getSize() const override; - void move(int x, int y) override; - std::pair getPosition() const override; - void show() override; - bool visible() const override; - void hide() override; - void redraw(const Rect& dirty_rect) override; - void setCaption(const std::string &caption) override; - void grabMouse(bool grab) override; - EventQueue getEvents() override; - void* getNativeWindowHandle() const override; - Point translateToScreen(const Point& point) override; - -private: - static LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); - static LRESULT CALLBACK subClassProc(HWND hwnd, UINT msg, WPARAM wp, - LPARAM lp, UINT_PTR id, DWORD_PTR data); - - HWND parent_window; - Window& window; - WNDID m_hwnd = 0; - bool mouse_in_window{false}; - std::pair last_mouse_position{0, 0}; - char* m_className = nullptr; - EventQueue event_queue; - bool always_on_top{false}; -}; - -} // GUI:: diff --git a/plugingui/nativewindow_x11.cc b/plugingui/nativewindow_x11.cc deleted file mode 100644 index 33dde7b..0000000 --- a/plugingui/nativewindow_x11.cc +++ /dev/null @@ -1,715 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_x11.cc - * - * Fri Dec 28 18:45:57 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "nativewindow_x11.h" - -//http://www.mesa3d.org/brianp/xshm.c - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "window.h" - -namespace GUI -{ - -#define _NET_WM_STATE_REMOVE 0 // remove/unset property -#define _NET_WM_STATE_ADD 1 // add/set property - -void setWindowFront(Display *disp, ::Window wind, bool enable) -{ - Atom wm_state, wm_state_above; - XEvent event; - - if((wm_state = XInternAtom(disp, "_NET_WM_STATE", False)) == None) - { - return; - } - - if((wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False)) == None) - { - return; - } - // - //window = the respective client window - //message_type = _NET_WM_STATE - //format = 32 - //data.l[0] = the action, as listed below - //data.l[1] = first property to alter - //data.l[2] = second property to alter - //data.l[3] = source indication (0-unk,1-normal app,2-pager) - //other data.l[] elements = 0 - // - - // sending a ClientMessage - event.xclient.type = ClientMessage; - - // value unimportant in this case - event.xclient.serial = 0; - - // coming from a SendEvent request, so True - event.xclient.send_event = True; - - // the event originates from disp - event.xclient.display = disp; - - // the window whose state will be modified - event.xclient.window = wind; - - // the component Atom being modified in the window - event.xclient.message_type = wm_state; - - // specifies that data.l will be used - event.xclient.format = 32; - - // 0 is _NET_WM_STATE_REMOVE, 1 is _NET_WM_STATE_ADD - event.xclient.data.l[0] = - enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; - - // the atom being added - event.xclient.data.l[1] = wm_state_above; - - // unused - event.xclient.data.l[2] = 0; - event.xclient.data.l[3] = 0; - event.xclient.data.l[4] = 0; - - // actually send the event - XSendEvent(disp, DefaultRootWindow(disp), False, - SubstructureRedirectMask | SubstructureNotifyMask, &event); -} - -NativeWindowX11::NativeWindowX11(void* native_window, Window& window) - : window(window) -{ - display = XOpenDisplay(nullptr); - if(display == nullptr) - { - ERR(X11, "XOpenDisplay failed"); - return; - } - - screen = DefaultScreen(display); - visual = DefaultVisual(display, screen); - depth = DefaultDepth(display, screen); - - if(native_window) - { - parent_window = (::Window)native_window; - - // Track size changes on the parent window - XSelectInput(display, parent_window, StructureNotifyMask); - } - else - { - parent_window = DefaultRootWindow(display); - } - - // Create the window - XSetWindowAttributes swa; - swa.backing_store = Always; - xwindow = XCreateWindow(display, - parent_window, - 0, 0, //window.x(), window.y(), - 1, 1, //window.width(), window.height(), - 0, // border - CopyFromParent, // depth - CopyFromParent, // class - CopyFromParent, // visual - 0,//CWBackingStore, - &swa); - - long mask = (StructureNotifyMask | - PointerMotionMask | - ButtonPressMask | - ButtonReleaseMask | - KeyPressMask | - KeyReleaseMask| - ExposureMask | - StructureNotifyMask | - SubstructureNotifyMask | - EnterWindowMask | - LeaveWindowMask); - XSelectInput(display, xwindow, mask); - - // Register the delete window message: - wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false); - - Atom protocols[] = { wmDeleteMessage }; - XSetWMProtocols(display, xwindow, protocols, - sizeof(protocols) / sizeof(*protocols)); - - // Create a "Graphics Context" - gc = XCreateGC(display, xwindow, 0, nullptr); -} - -NativeWindowX11::~NativeWindowX11() -{ - if(display == nullptr) - { - return; - } - - deallocateShmImage(); - - XFreeGC(display, gc); - - XDestroyWindow(display, xwindow); - XCloseDisplay(display); -} - -void NativeWindowX11::setFixedSize(std::size_t width, std::size_t height) -{ - if(display == nullptr) - { - return; - } - - resize(width, height); - - XSizeHints size_hints; - memset(&size_hints, 0, sizeof(size_hints)); - - size_hints.flags = PMinSize|PMaxSize; - size_hints.min_width = size_hints.max_width = (int)width; - size_hints.min_height = size_hints.max_height = (int)height; - - XSetNormalHints(display, xwindow, &size_hints); -} - -void NativeWindowX11::setAlwaysOnTop(bool always_on_top) -{ - setWindowFront(display, xwindow, always_on_top); -} - -void NativeWindowX11::resize(std::size_t width, std::size_t height) -{ - if(display == nullptr) - { - return; - } - - XResizeWindow(display, xwindow, width, height); -} - -std::pair NativeWindowX11::getSize() const -{ -// XWindowAttributes attributes; -// XGetWindowAttributes(display, xwindow, &attributes); -// return std::make_pair(attributes.width, attributes.height); - - ::Window root_window; - int x, y; - unsigned int width, height, border, depth; - - XGetGeometry(display, xwindow, &root_window, - &x, &y, - &width, &height, &border, &depth); - - return {width, height}; -} - -void NativeWindowX11::move(int x, int y) -{ - if(display == nullptr) - { - return; - } - - XMoveWindow(display, xwindow, x, y); -} - -std::pair NativeWindowX11::getPosition() const -{ - ::Window root_window; - ::Window child_window; - int x, y; - unsigned int width, height, border, depth; - - XGetGeometry(display, xwindow, &root_window, - &x, &y, - &width, &height, &border, &depth); - - XTranslateCoordinates(display, xwindow, root_window, - 0, 0, &x, &y, &child_window); - - return std::make_pair(x, y); -} - -void NativeWindowX11::show() -{ - if(display == nullptr) - { - return; - } - - XMapWindow(display, xwindow); -} - -void NativeWindowX11::hide() -{ - if(display == nullptr) - { - return; - } - - XUnmapWindow(display, xwindow); -} - -bool NativeWindowX11::visible() const -{ - if(display == nullptr) - { - return false; - } - - XWindowAttributes xwa; - XGetWindowAttributes(display, xwindow, &xwa); - return (xwa.map_state == IsViewable); -} - -void NativeWindowX11::redraw(const Rect& dirty_rect) -{ - if(display == nullptr) - { - return; - } - - auto x1 = dirty_rect.x1; - auto y1 = dirty_rect.y1; - auto x2 = dirty_rect.x2; - auto y2 = dirty_rect.y2; - - // Assert that we don't try to paint a backwards rect. - assert(x1 <= x2); - assert(y1 <= y2); - - updateImageFromBuffer(x1, y1, x2, y2); - - XShmPutImage(display, xwindow, gc, image, x1, y1, x1, y1, - std::min((std::size_t)image->width, (x2 - x1)), - std::min((std::size_t)image->height, (y2 - y1)), false); - XFlush(display); -} - -void NativeWindowX11::setCaption(const std::string &caption) -{ - if(display == nullptr) - { - return; - } - - XStoreName(display, xwindow, caption.c_str()); -} - -void NativeWindowX11::grabMouse(bool grab) -{ - (void)grab; - // Don't need to do anything on this platform... -} - -EventQueue NativeWindowX11::getEvents() -{ - while(XPending(display)) - { - XEvent xEvent; - XNextEvent(display, &xEvent); - translateXMessage(xEvent); - } - - EventQueue events; - std::swap(events, event_queue); - return events; -} - -void* NativeWindowX11::getNativeWindowHandle() const -{ - return (void*)xwindow; -} - -Point NativeWindowX11::translateToScreen(const Point& point) -{ - ::Window child_window; - Point p; - XTranslateCoordinates(display, xwindow, DefaultRootWindow(display), - point.x, point.y, &p.x, &p.y, &child_window); - return p; -} - -void NativeWindowX11::translateXMessage(XEvent& xevent) -{ - switch(xevent.type) - { - case MotionNotify: - //DEBUG(x11, "MotionNotify"); - { - auto mouseMoveEvent = std::make_shared(); - mouseMoveEvent->x = xevent.xmotion.x; - mouseMoveEvent->y = xevent.xmotion.y; - event_queue.push_back(mouseMoveEvent); - } - break; - - case Expose: - //DEBUG(x11, "Expose"); - if(xevent.xexpose.count == 0) - { - auto repaintEvent = std::make_shared(); - repaintEvent->x = xevent.xexpose.x; - repaintEvent->y = xevent.xexpose.y; - repaintEvent->width = xevent.xexpose.width; - repaintEvent->height = xevent.xexpose.height; - event_queue.push_back(repaintEvent); - - if(image) - { - // Redraw the entire window. - Rect rect{0, 0, window.wpixbuf.width, window.wpixbuf.height}; - redraw(rect); - } - } - break; - - case ConfigureNotify: - //DEBUG(x11, "ConfigureNotify"); - - // The parent window size changed, reflect the new size in our own window. - if(xevent.xconfigure.window == parent_window) - { - resize(xevent.xconfigure.width, xevent.xconfigure.height); - return; - } - - { - if((window.width() != (std::size_t)xevent.xconfigure.width) || - (window.height() != (std::size_t)xevent.xconfigure.height)) - { - auto resizeEvent = std::make_shared(); - resizeEvent->width = xevent.xconfigure.width; - resizeEvent->height = xevent.xconfigure.height; - event_queue.push_back(resizeEvent); - } - - if((window.x() != xevent.xconfigure.x) || - (window.y() != xevent.xconfigure.y)) - { - auto moveEvent = std::make_shared(); - moveEvent->x = xevent.xconfigure.x; - moveEvent->y = xevent.xconfigure.y; - event_queue.push_back(moveEvent); - } - } - break; - - case ButtonPress: - case ButtonRelease: - //DEBUG(x11, "ButtonPress"); - { - if((xevent.xbutton.button == 4) || (xevent.xbutton.button == 5)) - { - if(xevent.type == ButtonPress) - { - int scroll = 1; - auto scrollEvent = std::make_shared(); - scrollEvent->x = xevent.xbutton.x; - scrollEvent->y = xevent.xbutton.y; - scrollEvent->delta = scroll * ((xevent.xbutton.button == 4) ? -1 : 1); - event_queue.push_back(scrollEvent); - } - } - else if ((xevent.xbutton.button == 6) || (xevent.xbutton.button == 7)) - { - // Horizontal scrolling case - // FIXME Introduce horizontal scrolling event to handle this. - } - else - { - auto buttonEvent = std::make_shared(); - buttonEvent->x = xevent.xbutton.x; - buttonEvent->y = xevent.xbutton.y; - switch(xevent.xbutton.button) { - case 1: - buttonEvent->button = MouseButton::left; - break; - case 2: - buttonEvent->button = MouseButton::middle; - break; - case 3: - buttonEvent->button = MouseButton::right; - break; - default: - WARN(X11, "Unknown button %d, setting to MouseButton::left\n", - xevent.xbutton.button); - buttonEvent->button = MouseButton::left; - break; - } - - buttonEvent->direction = - (xevent.type == ButtonPress) ? - Direction::down : Direction::up; - - // This is a fix for hosts (e.g. those using JUCE) that set the - // event time to '0'. - if(xevent.xbutton.time == 0) - { - auto now = std::chrono::system_clock::now().time_since_epoch(); - xevent.xbutton.time = - std::chrono::duration_cast(now).count(); - } - - buttonEvent->doubleClick = - (xevent.type == ButtonPress) && - ((xevent.xbutton.time - last_click) < 200); - - if(xevent.type == ButtonPress) - { - last_click = xevent.xbutton.time; - } - event_queue.push_back(buttonEvent); - } - } - break; - - case KeyPress: - case KeyRelease: - //DEBUG(x11, "KeyPress"); - { - auto keyEvent = std::make_shared(); - - switch(xevent.xkey.keycode) { - case 113: keyEvent->keycode = Key::left; break; - case 114: keyEvent->keycode = Key::right; break; - case 111: keyEvent->keycode = Key::up; break; - case 116: keyEvent->keycode = Key::down; break; - case 119: keyEvent->keycode = Key::deleteKey; break; - case 22: keyEvent->keycode = Key::backspace; break; - case 110: keyEvent->keycode = Key::home; break; - case 115: keyEvent->keycode = Key::end; break; - case 117: keyEvent->keycode = Key::pageDown; break; - case 112: keyEvent->keycode = Key::pageUp; break; - case 36: keyEvent->keycode = Key::enter; break; - default: keyEvent->keycode = Key::unknown; break; - } - - char stringBuffer[1024]; - int size = XLookupString(&xevent.xkey, stringBuffer, - sizeof(stringBuffer), nullptr, nullptr); - if(size && keyEvent->keycode == Key::unknown) - { - keyEvent->keycode = Key::character; - } - - keyEvent->text.append(stringBuffer, size); - - keyEvent->direction = - (xevent.type == KeyPress) ? Direction::down : Direction::up; - - event_queue.push_back(keyEvent); - } - break; - - case ClientMessage: - //DEBUG(x11, "ClientMessage"); - if(((unsigned int)xevent.xclient.data.l[0] == wmDeleteMessage)) - { - auto closeEvent = std::make_shared(); - event_queue.push_back(closeEvent); - } - break; - - case EnterNotify: - //DEBUG(x11, "EnterNotify"); - { - auto enterEvent = std::make_shared(); - enterEvent->x = xevent.xcrossing.x; - enterEvent->y = xevent.xcrossing.y; - event_queue.push_back(enterEvent); - } - break; - - case LeaveNotify: - //DEBUG(x11, "LeaveNotify"); - { - auto leaveEvent = std::make_shared(); - leaveEvent->x = xevent.xcrossing.x; - leaveEvent->y = xevent.xcrossing.y; - event_queue.push_back(leaveEvent); - } - break; - - case MapNotify: - case MappingNotify: - //DEBUG(x11, "EnterNotify"); - // There's nothing to do here atm. - break; - - default: - WARN(X11, "Unhandled xevent.type: %d\n", xevent.type); - break; - } -} - -void NativeWindowX11::allocateShmImage(std::size_t width, std::size_t height) -{ - DEBUG(x11, "(Re)alloc XShmImage (%d, %d)", (int)width, (int)height); - - if(image) - { - deallocateShmImage(); - } - - if(!XShmQueryExtension(display)) - { - ERR(x11, "XShmExtension not available"); - return; - } - - image = XShmCreateImage(display, visual, depth, - ZPixmap, nullptr, &shm_info, - width, height); - if(image == nullptr) - { - ERR(x11, "XShmCreateImage failed!\n"); - return; - } - - std::size_t byte_size = image->bytes_per_line * image->height; - - // Allocate shm buffer - int shm_id = shmget(IPC_PRIVATE, byte_size, IPC_CREAT|0777); - if(shm_id == -1) - { - ERR(x11, "shmget failed: %s", strerror(errno)); - return; - } - - shm_info.shmid = shm_id; - - // Attach share memory bufer - void* shm_addr = shmat(shm_id, nullptr, 0); - if(reinterpret_cast(shm_addr) == -1) - { - ERR(x11, "shmat failed: %s", strerror(errno)); - return; - } - - shm_info.shmaddr = reinterpret_cast(shm_addr); - image->data = shm_info.shmaddr; - shm_info.readOnly = false; - - // This may trigger the X protocol error we're ready to catch: - XShmAttach(display, &shm_info); - XSync(display, false); - - // Make the shm id unavailable to others - shmctl(shm_id, IPC_RMID, 0); -} - -void NativeWindowX11::deallocateShmImage() -{ - if(image == nullptr) - { - return; - } - - XFlush(display); - XShmDetach(display, &shm_info); - XDestroyImage(image); - image = nullptr; - shmdt(shm_info.shmaddr); -} - -void NativeWindowX11::updateImageFromBuffer(std::size_t x1, std::size_t y1, - std::size_t x2, std::size_t y2) -{ - //DEBUG(x11, "depth: %d", depth); - - auto width = window.wpixbuf.width; - auto height = window.wpixbuf.height; - - // If image hasn't been allocated yet or if the image backbuffer is - // too small, (re)allocate with a suitable size. - if((image == nullptr) || - ((int)width > image->width) || - ((int)height > image->height)) - { - constexpr std::size_t step_size = 128; // size increments - std::size_t new_width = ((width / step_size) + 1) * step_size; - std::size_t new_height = ((height / step_size) + 1) * step_size; - allocateShmImage(new_width, new_height); - x1 = 0; - y1 = 0; - x2 = width; - y2 = height; - } - - auto stride = image->width; - - std::uint8_t* pixel_buffer = (std::uint8_t*)window.wpixbuf.buf; - if(depth >= 24) // RGB 888 format - { - std::uint32_t* shm_addr = (std::uint32_t*)shm_info.shmaddr; - for(std::size_t y = y1; y < y2; ++y) - { - for(std::size_t x = x1; x < x2; ++x) - { - const std::size_t pin = y * width + x; - const std::size_t pout = y * stride + x; - const std::uint8_t red = pixel_buffer[pin * 3]; - const std::uint8_t green = pixel_buffer[pin * 3 + 1]; - const std::uint8_t blue = pixel_buffer[pin * 3 + 2]; - shm_addr[pout] = (red << 16) | (green << 8) | blue; - } - } - } - else if(depth >= 15) // RGB 565 format - { - std::uint16_t* shm_addr = (std::uint16_t*)shm_info.shmaddr; - - for(std::size_t y = y1; y < y2; ++y) - { - for(std::size_t x = x1; x < x2; ++x) - { - const std::size_t pin = y * width + x; - const std::size_t pout = y * stride + x; - const std::uint8_t red = pixel_buffer[pin * 3]; - const std::uint8_t green = pixel_buffer[pin * 3 + 1]; - const std::uint8_t blue = pixel_buffer[pin * 3 + 2]; - shm_addr[pout] = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); - } - } - } -} - -} // GUI:: diff --git a/plugingui/nativewindow_x11.h b/plugingui/nativewindow_x11.h deleted file mode 100644 index cb56fbc..0000000 --- a/plugingui/nativewindow_x11.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_x11.h - * - * Fri Dec 28 18:45:56 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include -#include - -#include "nativewindow.h" - -namespace GUI -{ - -class Window; - -class NativeWindowX11 - : public NativeWindow -{ -public: - NativeWindowX11(void* native_window, Window& window); - ~NativeWindowX11(); - - // From NativeWindow: - void setFixedSize(std::size_t width, std::size_t height) override; - void setAlwaysOnTop(bool always_on_top) override; - void resize(std::size_t width, std::size_t height) override; - std::pair getSize() const override; - void move(int x, int y) override; - std::pair getPosition() const override; - void show() override; - void hide() override; - bool visible() const override; - void setCaption(const std::string &caption) override; - void redraw(const Rect& dirty_rect) override; - void grabMouse(bool grab) override; - EventQueue getEvents() override; - void* getNativeWindowHandle() const override; - Point translateToScreen(const Point& point) override; - -private: - void translateXMessage(XEvent& xevent); - - //! Allocate new shared memory buffer for the pixel buffer. - //! Frees the existing buffer if there is one. - void allocateShmImage(std::size_t width, std::size_t height); - - //! Deallocate image and shm resources. - void deallocateShmImage(); - - //! Copy data from the pixel buffer into the shared memory - void updateImageFromBuffer(std::size_t x1, std::size_t y1, - std::size_t x2, std::size_t y2); - - XShmSegmentInfo shm_info; - XImage* image{nullptr}; - - ::Window xwindow{0}; - GC gc{0}; - - Window& window; - - Time last_click{0}; - - Display* display{nullptr}; - int screen{0}; - int depth{0}; - Visual* visual{nullptr}; - Atom wmDeleteMessage{0}; - ::Window parent_window; - - EventQueue event_queue; -}; - -} // GUI:: diff --git a/plugingui/painter.cc b/plugingui/painter.cc deleted file mode 100644 index f746f83..0000000 --- a/plugingui/painter.cc +++ /dev/null @@ -1,644 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * painter.cc - * - * Wed Oct 12 19:48:45 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "painter.h" - -#include -#include - -#include "pixelbuffer.h" -#include "font.h" -#include "drawable.h" -#include "image.h" -#include "canvas.h" - -namespace GUI -{ - -Painter::Painter(Canvas& canvas) - : pixbuf(canvas.getPixelBuffer()) -{ - colour = Colour(0.0f, 0.0f, 0.0f, 0.5f); -} - -Painter::~Painter() -{ -} - -void Painter::setColour(const Colour& colour) -{ - this->colour = colour; -} - -static void plot(PixelBufferAlpha& pixbuf, const Colour& colour, - int x, int y, double c) -{ - if((x >= (int)pixbuf.width) || - (y >= (int)pixbuf.height) || - (x < 0) || - (y < 0)) - { - return; - } - - // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1) - Colour col(colour); - if(c != 1) - { - col.data()[3] *= c; - } - pixbuf.addPixel(x, y, col); -} - -static inline double fpart(double x) -{ - return x - std::floor(x);// fractional part of x -} - -static inline double rfpart(double x) -{ - return 1 - fpart(x); // reverse fractional part of x -} - -void Painter::drawLine(int x0, int y0, int x1, int y1) -{ - bool steep = abs(y1 - y0) > abs(x1 - x0); - - if(steep) - { - std::swap(x0, y0); - std::swap(x1, y1); - } - if(x0 > x1) - { - std::swap(x0, x1); - std::swap(y0, y1); - } - - double dx = x1 - x0; - double dy = y1 - y0; - double gradient = dy / dx; - - // Handle first endpoint: - double xend = std::round(x0); - double yend = y0 + gradient * (xend - x0); - - double xpxl1 = xend; // this will be used in the main loop - double ypxl1 = std::floor(yend); - - if(steep) - { - pixbuf.addPixel(ypxl1, xpxl1, colour); - } - else - { - pixbuf.addPixel(xpxl1, ypxl1, colour); - } - - double intery = yend + gradient; // first y-intersection for the main loop - - // Handle second endpoint: - xend = std::round(x1); - yend = y1 + gradient * (xend - x1); - - double xpxl2 = xend; // this will be used in the main loop - double ypxl2 = std::floor(yend); - - if(steep) - { - pixbuf.addPixel(ypxl2, xpxl2, colour); - } - else - { - pixbuf.addPixel(xpxl2, ypxl2, colour); - } - - // main loop - for(int x = xpxl1 + 1; x <= xpxl2 - 1; ++x) - { - if(steep) - { - plot(pixbuf, colour, std::floor(intery) , x, rfpart(intery)); - plot(pixbuf, colour, std::floor(intery)+1, x, fpart(intery)); - } - else - { - plot(pixbuf, colour, x, std::floor(intery), rfpart(intery)); - plot(pixbuf, colour, x, std::floor(intery)+1, fpart(intery)); - } - intery += gradient; - } -} - -void Painter::drawRectangle(int x1, int y1, int x2, int y2) -{ - drawLine(x1, y1, x2 - 1, y1); - drawLine(x2, y1, x2, y2 - 1); - drawLine(x1 + 1, y2, x2, y2); - drawLine(x1, y1 + 1, x1, y2); -} - -void Painter::drawFilledRectangle(int x1, int y1, int x2, int y2) -{ - for(int y = y1; y <= y2; ++y) - { - drawLine(x1, y, x2, y); - } -} - -void Painter::clear() -{ - pixbuf.clear(); -} - -void Painter::drawText(int x0, int y0, const Font& font, - const std::string& text, bool nocolour, bool rotate) -{ - PixelBufferAlpha* textbuf = font.render(text); - - if(!rotate) - { - y0 -= textbuf->height; // The y0 offset (baseline) is the bottom of the text. - } - - // If the text offset is outside the buffer; skip it. - if((x0 > (int)pixbuf.width) || (y0 > (int)pixbuf.height)) - { - delete textbuf; - return; - } - - // Make sure we don't try to draw outside the pixbuf. - int renderWidth = textbuf->width; - if(renderWidth > (int)(pixbuf.width - x0)) - { - renderWidth = pixbuf.width - x0; - } - - int renderHeight = textbuf->height; - if(renderHeight > ((int)pixbuf.height - y0)) - { - renderHeight = ((int)pixbuf.height - y0); - } - - if(nocolour) - { - for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) - { - int x = -1 * std::min(0, x0); - - assert(x >= 0); - assert(y >= 0); - assert(x < (int)textbuf->width); - assert(y < (int)textbuf->height); - - auto c = textbuf->getLine(x, y); - - assert(x + x0 >= 0); - assert(y + y0 >= 0); - assert(x + x0 < (int)pixbuf.width); - assert(y + y0 < (int)pixbuf.height); - - pixbuf.blendLine(x + x0, y + y0, c, renderWidth - x); - } - } - else if(rotate) - { - int renderWidth = textbuf->height; - if(renderWidth > (int)(pixbuf.width - x0)) - { - renderWidth = pixbuf.width - x0; - } - - int renderHeight = textbuf->width; - if(renderHeight > ((int)pixbuf.height - y0)) - { - renderHeight = ((int)pixbuf.height - y0); - } - - for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) - { - for(int x = -1 * std::min(0, x0); x < renderWidth; ++x) - { - assert(x >= 0); - assert(y >= 0); - assert(x < (int)textbuf->height); - assert(y < (int)textbuf->width); - - auto c = textbuf->pixel(textbuf->width - y - 1, x); - - assert(x + x0 >= 0); - assert(y + y0 >= 0); - assert(x + x0 < (int)pixbuf.width); - assert(y + y0 < (int)pixbuf.height); - - Colour col(colour.red(), colour.green(), - colour.blue(), (int)(colour.alpha() * c.alpha()) / 255); - pixbuf.addPixel(x + x0, y + y0, col); - } - } - } - else - { - for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) - { - for(int x = -1 * std::min(0, x0); x < renderWidth; ++x) - { - assert(x >= 0); - assert(y >= 0); - assert(x < (int)textbuf->width); - assert(y < (int)textbuf->height); - - auto c = textbuf->pixel(x, y); - - assert(x + x0 >= 0); - assert(y + y0 >= 0); - assert(x + x0 < (int)pixbuf.width); - assert(y + y0 < (int)pixbuf.height); - - Colour col(colour.red(), colour.green(), - colour.blue(), (int)(colour.alpha() * c.alpha()) / 255); - pixbuf.addPixel(x + x0, y + y0, col); - } - } - } - - delete textbuf; -} - -void Painter::drawPoint(int x, int y) -{ - if(x >= 0 && y >= 0 && (std::size_t)x < pixbuf.width && (std::size_t)y < pixbuf.height) - { - pixbuf.setPixel(x, y, colour); - } -} - -static void plot4points(Painter *p, int cx, int cy, int x, int y) -{ - p->drawPoint(cx + x, cy + y); - if(x != 0) - { - p->drawPoint(cx - x, cy + y); - } - - if(y != 0) - { - p->drawPoint(cx + x, cy - y); - } - - if(x != 0 && y != 0) - { - p->drawPoint(cx - x, cy - y); - } -} - -void Painter::drawCircle(int cx, int cy, double radius) -{ - int error = -radius; - int x = radius; - int y = 0; - - while(x >= y) - { - plot4points(this, cx, cy, x, y); - - if(x != y) - { - plot4points(this, cx, cy, y, x); - } - - error += y; - ++y; - error += y; - - if(error >= 0) - { - --x; - error -= x; - error -= x; - } - } -} - -static void plot4lines(Painter *p, int cx, int cy, int x, int y) -{ - p->drawLine(cx + x, cy + y, cx - x, cy + y); - if(x != 0) - { - p->drawLine(cx - x, cy + y, cx + x, cy + y); - } - - if(y != 0) - { - p->drawLine(cx + x, cy - y, cx - x, cy - y); - } - - if(x != 0 && y != 0) - { - p->drawLine(cx - x, cy - y, cx + x, cy - y); - } -} - -void Painter::drawFilledCircle(int cx, int cy, int radius) -{ - int error = -radius; - int x = radius; - int y = 0; - - while(x >= y) - { - plot4lines(this, cx, cy, x, y); - - if(x != y) - { - plot4lines(this, cx, cy, y, x); - } - - error += y; - ++y; - error += y; - - if(error >= 0) - { - --x; - error -= x; - error -= x; - } - } -} - -void Painter::drawImage(int x0, int y0, const Drawable& image) -{ - int fw = image.width(); - int fh = image.height(); - - // Make sure we don't try to draw outside the pixbuf. - if(fw > (int)(pixbuf.width - x0)) - { - fw = (int)(pixbuf.width - x0); - } - - if(fh > (int)(pixbuf.height - y0)) - { - fh = (int)(pixbuf.height - y0); - } - - if((fw < 1) || (fh < 1)) - { - return; - } - - if(image.hasAlpha()) - { - if(!image.line(0)) - { - for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) - { - for(std::size_t x = -1 * std::min(0, x0); x < (std::size_t)fw; ++x) - { - assert(x >= 0); - assert(y >= 0); - assert(x < image.width()); - assert(y < image.height()); - auto& c = image.getPixel(x, y); - - assert(x0 + x >= 0); - assert(y0 + y >= 0); - assert(x0 + x < pixbuf.width); - assert(y0 + y < pixbuf.height); - - pixbuf.addPixel(x0 + x, y0 + y, c); - } - } - } - else - { - std::size_t x_offset = -1 * std::min(0, x0); - for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) - { - pixbuf.blendLine(x_offset + x0, y + y0, image.line(y, x_offset), - std::min((int)image.width(), fw - (int)x_offset)); - } - } - } - else - { - std::size_t x_offset = -1 * std::min(0, x0); - for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) - { - pixbuf.writeLine(x_offset + x0, y + y0, image.line(y, x_offset), - std::min((int)image.width(), fw - (int)x_offset)); - } - } -} - -void Painter::drawRestrictedImage(int x0, int y0, - const Colour& restriction_colour, - const Drawable& image) -{ - int fw = image.width(); - int fh = image.height(); - - // Make sure we don't try to draw outside the pixbuf. - if(fw > (int)(pixbuf.width - x0)) - { - fw = (int)(pixbuf.width - x0); - } - - if(fh > (int)(pixbuf.height - y0)) - { - fh = (int)(pixbuf.height - y0); - } - - if((fw < 1) || (fh < 1)) - { - return; - } - - for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y) - { - for(std::size_t x = -1 * std::min(0, x0); x < (std::size_t)fw; ++x) - { - assert(x >= 0); - assert(y >= 0); - assert(x < image.width()); - assert(y < image.height()); - auto& c = image.getPixel(x, y); - - assert(x0 + x >= 0); - assert(y0 + y >= 0); - assert(x0 + x < pixbuf.width); - assert(y0 + y < pixbuf.height); - - if(c == restriction_colour) - { - pixbuf.setPixel(x0 + x, y0 + y, c); - } - } - } -} - -void Painter::drawImageStretched(int x0, int y0, const Drawable& image, - int width, int height) -{ - float fw = image.width(); - float fh = image.height(); - - // Make sure we don't try to draw outside the pixbuf. - if(width > (int)(pixbuf.width - x0)) - { - width = pixbuf.width - x0; - } - - if(height > (int)(pixbuf.height - y0)) - { - height = pixbuf.height - y0; - } - - if((width < 1) || (height < 1)) - { - return; - } - - for(int y = -1 * std::min(0, y0); y < height; ++y) - { - for(int x = -1 * std::min(0, x0); x < width; ++x) - { - int lx = ((float)x / (float)width) * fw; - int ly = ((float)y / (float)height) * fh; - auto& c = image.getPixel(lx, ly); - pixbuf.addPixel(x0 + x, y0 + y, c); - } - } -} - -void Painter::drawBox(int x, int y, const Box& box, int width, int height) -{ - int dx = x; - int dy = y; - - // Top: - drawImage(dx, dy, *box.topLeft); - - dx += box.topLeft->width(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImageStretched(dx, dy, *box.top, - width - box.topRight->width() - box.topLeft->width(), - box.top->height()); - - dx = x + width - box.topRight->width(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImage(dx, dy, *box.topRight); - - // Center: - dy = y + box.topLeft->height(); - dx = x + box.left->width(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImageStretched(dx, dy, *box.center, - width - box.left->width() - box.right->width(), - height - box.topLeft->height() - box.bottomLeft->height()); - - // Mid: - dx = x; - dy = y + box.topLeft->height(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImageStretched(dx, dy, *box.left, box.left->width(), - height - box.topLeft->height() - box.bottomLeft->height()); - - dx = x + width - box.right->width(); - dy = y + box.topRight->height(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImageStretched(dx, dy, *box.right, - box.right->width(), - height - box.topRight->height() - box.bottomRight->height()); - - // Bottom: - dx = x; - dy = y + height - box.bottomLeft->height(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImage(dx, dy, *box.bottomLeft); - - dx += box.bottomLeft->width(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImageStretched(dx, dy, *box.bottom, - width - box.bottomRight->width() - box.bottomLeft->width(), - box.bottom->height()); - - dx = x + width - box.bottomRight->width(); - if((dx < 0) || (dy < 0)) - { - return; - } - - drawImage(dx, dy, *box.bottomRight); -} - -void Painter::drawBar(int x, int y, const Bar& bar, int width, int height) -{ - if(width < ((int)bar.left->width() + (int)bar.right->width() + 1)) - { - width = bar.left->width() + bar.right->width() + 1; - } - - drawImageStretched(x, y, *bar.left, bar.left->width(), height); - - drawImageStretched(x + bar.left->width(), y, *bar.center, - width - bar.left->width() - bar.right->width(), height); - - drawImageStretched(x + width - bar.left->width(), y, *bar.right, - bar.right->width(), height); -} - -} // GUI:: diff --git a/plugingui/painter.h b/plugingui/painter.h deleted file mode 100644 index 9bf7fbf..0000000 --- a/plugingui/painter.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * painter.h - * - * Wed Oct 12 19:48:45 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "colour.h" -#include "pixelbuffer.h" - -namespace GUI -{ - -class Font; -class Drawable; -class Image; -class Canvas; - -class Painter -{ -public: - Painter(Canvas& canvas); - ~Painter(); - - void setColour(const Colour& colour); - - void drawLine(int x1, int y1, int x2, int y2); - void drawText(int x, int y, const Font& font, const std::string& text, - bool nocolour = false, bool rotate = false); - void drawRectangle(int x1, int y1, int x2, int y2); - void drawFilledRectangle(int x1, int y1, int x2, int y2); - void drawPoint(int x, int y); - void drawCircle(int x, int y, double r); - void drawFilledCircle(int x, int y, int r); - void drawImage(int x, int y, const Drawable& image); - void drawRestrictedImage(int x0, int y0, const Colour& restriction_colour, - const Drawable& image); - void drawImageStretched(int x, int y, const Drawable& image, - int width, int height); - - template - void draw(Iterator begin, Iterator end, int x_offset, int y_offset, Colour const& colour); - - typedef struct { - Image* topLeft; - Image* top; - Image* topRight; - Image* left; - Image* right; - Image* bottomLeft; - Image* bottom; - Image* bottomRight; - Image* center; - } Box; - void drawBox(int x, int y, const Box& box, int width, int height); - - typedef struct { - Image* left; - Image* right; - Image* center; - } Bar; - void drawBar(int x, int y, const Bar& bar, int width, int height); - - void clear(); - -private: - PixelBufferAlpha& pixbuf; - Colour colour; -}; - -template -void Painter::draw(Iterator begin, Iterator end, int x_offset, int y_offset, Colour const& colour) -{ - for (auto it = begin; it != end; ++it) - { - pixbuf.addPixel(x_offset + it->x, y_offset + it->y, colour); - } -} - -} // GUI:: diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc deleted file mode 100644 index 3c666cd..0000000 --- a/plugingui/pixelbuffer.cc +++ /dev/null @@ -1,369 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * pixelbuffer.cc - * - * Thu Nov 10 09:00:38 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "pixelbuffer.h" - -#include - -#include -#include -#include - -namespace GUI -{ - -PixelBuffer::PixelBuffer(std::size_t width, std::size_t height) -{ - realloc(width, height); -} - -PixelBuffer::~PixelBuffer() -{ -} - -void PixelBuffer::realloc(std::size_t width, std::size_t height) -{ - buf_data.resize(width * height * 3); - buf = buf_data.data(); - this->width = width; - this->height = height; -} - -void PixelBuffer::blendLine(std::size_t x, std::size_t y, - const std::uint8_t* line, std::size_t len) -{ - std::uint8_t* target = buf + (x + y * width) * 3; - while(len) - { - if(line[3] == 0xff) - { - std::memcpy(target, line, 3); - } - else - { - unsigned int a = line[3]; - unsigned int b = 255 - a; - - target[0] = (std::uint8_t)((line[0] * a + target[0] * b) / 255); - target[1] = (std::uint8_t)((line[1] * a + target[1] * b) / 255); - target[2] = (std::uint8_t)((line[2] * a + target[2] * b) / 255); - } - target += 3; - line += 4; - --len; - } -} - -Rect PixelBuffer::updateBuffer(std::vector& pixel_buffers) -{ - bool has_dirty_rect{false}; - Rect dirty_rect; - - for(const auto& pixel_buffer : pixel_buffers) - { - if(pixel_buffer->dirty) - { - auto x1 = (std::size_t)std::max(pixel_buffer->x, 0); - auto x2 = (std::size_t)std::max((pixel_buffer->x + (int)pixel_buffer->width), 0); - auto y1 = (std::size_t)std::max(pixel_buffer->y, 0); - auto y2 = (std::size_t)std::max((pixel_buffer->y + (int)pixel_buffer->height), 0); - - pixel_buffer->dirty = false; - if(!has_dirty_rect) - { - // Insert this area: - dirty_rect = {x1, y1, x2, y2}; - has_dirty_rect = true; - } - else - { - // Expand existing area: - auto x1_0 = dirty_rect.x1; - auto y1_0 = dirty_rect.y1; - auto x2_0 = dirty_rect.x2; - auto y2_0 = dirty_rect.y2; - dirty_rect = { - (x1_0 < x1) ? x1_0 : x1, - (y1_0 < y1) ? y1_0 : y1, - (x2_0 > x2) ? x2_0 : x2, - (y2_0 > y2) ? y2_0 : y2 - }; - } - } - - if(pixel_buffer->has_last) - { - auto x1 = (std::size_t)pixel_buffer->last_x; - auto x2 = (std::size_t)(pixel_buffer->last_x + pixel_buffer->last_width); - auto y1 = (std::size_t)pixel_buffer->last_y; - auto y2 = (std::size_t)(pixel_buffer->last_y + pixel_buffer->last_height); - - pixel_buffer->has_last = false; - if(!has_dirty_rect) - { - // Insert this area: - dirty_rect = {x1, y1, x2, y2}; - has_dirty_rect = true; - } - else - { - // Expand existing area: - auto x1_0 = dirty_rect.x1; - auto y1_0 = dirty_rect.y1; - auto x2_0 = dirty_rect.x2; - auto y2_0 = dirty_rect.y2; - dirty_rect = { - (x1_0 < x1) ? x1_0 : x1, - (y1_0 < y1) ? y1_0 : y1, - (x2_0 > x2) ? x2_0 : x2, - (y2_0 > y2) ? y2_0 : y2 - }; - } - } - } - - if(!has_dirty_rect) - { - return {}; - } - - for(const auto& pixel_buffer : pixel_buffers) - { - if(!pixel_buffer->visible) - { - continue; - } - - int update_width = pixel_buffer->width; - int update_height = pixel_buffer->height; - - // Skip buffer if not inside window. - if(((int)width < pixel_buffer->x) || - ((int)height < pixel_buffer->y)) - { - continue; - } - - if(update_width > ((int)width - pixel_buffer->x)) - { - update_width = ((int)width - pixel_buffer->x); - } - - if(update_height > ((int)height - pixel_buffer->y)) - { - update_height = ((int)height - pixel_buffer->y); - } - - auto from_x = (int)dirty_rect.x1 - pixel_buffer->x; - from_x = std::max(0, from_x); - auto from_y = (int)dirty_rect.y1 - pixel_buffer->y; - from_y = std::max(0, from_y); - - auto to_x = (int)dirty_rect.x2 - pixel_buffer->x; - to_x = std::min(to_x, (int)update_width); - auto to_y = (int)dirty_rect.y2 - pixel_buffer->y; - to_y = std::min(to_y, (int)update_height); - - if(to_x < from_x) - { - continue; - } - - for(int y = from_y; y < to_y; y++) - { - blendLine(pixel_buffer->x + from_x, - pixel_buffer->y + y, - pixel_buffer->getLine(from_x, y), - to_x - from_x); - } - } - - dirty_rect.x2 = std::min(width, dirty_rect.x2); - dirty_rect.y2 = std::min(height, dirty_rect.y2); - - // Make sure we don't try to paint a rect backwards. - if(dirty_rect.x1 > dirty_rect.x2) - { - std::swap(dirty_rect.x1, dirty_rect.x2); - } - - if(dirty_rect.y1 > dirty_rect.y2) - { - std::swap(dirty_rect.y1, dirty_rect.y2); - } - - return dirty_rect; -} - -PixelBufferAlpha::PixelBufferAlpha(std::size_t width, std::size_t height) -{ - realloc(width, height); -} - -PixelBufferAlpha::~PixelBufferAlpha() -{ -} - -void PixelBufferAlpha::realloc(std::size_t width, std::size_t height) -{ - buf_data.resize(width * height * 4); - buf = buf_data.data(); - this->width = width; - this->height = height; - clear(); -} - -void PixelBufferAlpha::clear() -{ - std::memset(buf, 0, width * height * 4); -} - -void PixelBufferAlpha::setPixel(std::size_t x, std::size_t y, const Colour& c) -{ - std::uint8_t* pixel = buf + (x + y * width) * 4; - std::memcpy(pixel, c.data(), 4); -} - -void PixelBufferAlpha::writeLine(std::size_t x, std::size_t y, - const std::uint8_t* line, std::size_t len) -{ - if(x >= width || y >= height) - { - return; - } - - if(x + len > width) - { - len = width - x; - } - - auto offset = buf + (x + y * width) * 4; - - std::memcpy(offset, line, len * 4); -} - - -// SIMD: https://github.com/WojciechMula/toys/blob/master/blend_32bpp/blend_32bpp.c -// Alpha blending: http://en.wikipedia.org/wiki/Alpha_compositing - -void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, - const std::uint8_t* line, std::size_t len) -{ - if(x >= width || y >= height) - { - return; - } - - if(x + len > width) - { - len = width - x; - } - - int a, b; - std::uint8_t* target = buf + (x + y * width) * 4; - while(len) - { - if(line[3] == 0xff) - { - const std::uint8_t* end = line; - while(end[3] == 0xff && end < line + len * 4) - { - end += 4; - } - auto chunk_len = end - line; - std::memcpy(target, line, chunk_len); - line += chunk_len; - target += chunk_len; - len -= chunk_len / 4; - continue; - } - else if(line[3] == 0) - { - // Do nothing - } - else - { - a = line[3]; - b = target[3] * (255 - a) / 255; - - target[0] = (line[0] * a + target[0] * b) / (a + b); - target[1] = (line[1] * a + target[1] * b) / (a + b); - target[2] = (line[2] * a + target[2] * b) / (a + b); - target[3] = (int)target[3] + line[3] * (255 - target[3]) / 255; - } - - line += 4; - target += 4; - --len; - } -} - -void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) -{ - if(x >= width || y >= height) - { - return; // out of bounds - } - - const std::uint8_t* colour = c.data(); - - if(colour[3] == 0) - { - return; - } - - int a, b; - std::uint8_t* target = buf + (x + y * width) * 4; - - if(colour[3] == 0xff) - { - std::memcpy(target, colour, 4); - } - else - { - a = colour[3]; - b = target[3] * (255 - a) / 255; - - target[0] = (colour[0] * a + target[0] * b) / (a + b); - target[1] = (colour[1] * a + target[1] * b) / (a + b); - target[2] = (colour[2] * a + target[2] * b) / (a + b); - target[3] = (int)target[3] + colour[3] * (255 - target[3]) / 255; - } -} - -const Colour& PixelBufferAlpha::pixel(std::size_t x, std::size_t y) const -{ - static Colour c; - std::memcpy(c.data(), buf + (x + y * width) * 4, 4); - return c; -} - -const std::uint8_t* PixelBufferAlpha::getLine(std::size_t x, std::size_t y) const -{ - return buf + (x + y * width) * 4; -} - -} // GUI:: diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h deleted file mode 100644 index 5c11d14..0000000 --- a/plugingui/pixelbuffer.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * pixelbuffer.h - * - * Thu Nov 10 09:00:37 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "colour.h" - -#include -#include -#include - -#include "guievent.h" - -namespace GUI -{ - -class PixelBuffer -{ -public: - PixelBuffer(std::size_t width, std::size_t height); - ~PixelBuffer(); - - void realloc(std::size_t width, std::size_t height); - - void blendLine(std::size_t x, std::size_t y, - const std::uint8_t* line, std::size_t len); - - Rect updateBuffer(std::vector& pixel_buffers); - - std::vector buf_data; - std::uint8_t* buf{nullptr}; - std::size_t width{0}; - std::size_t height{0}; -}; - -class PixelBufferAlpha -{ -public: - PixelBufferAlpha() = default; - PixelBufferAlpha(std::size_t width, std::size_t height); - ~PixelBufferAlpha(); - - void realloc(std::size_t width, std::size_t height); - - void clear(); - - void setPixel(std::size_t x, std::size_t y, const Colour& c); - - void writeLine(std::size_t x, std::size_t y, - const std::uint8_t* line, std::size_t len); - void blendLine(std::size_t x, std::size_t y, - const std::uint8_t* line, std::size_t len); - - void addPixel(std::size_t x, std::size_t y, const Colour& c); - - const Colour& pixel(std::size_t x, std::size_t y) const; - - const std::uint8_t* getLine(std::size_t x, std::size_t y) const; - - std::vector buf_data; - std::uint8_t* buf{nullptr}; - std::size_t width{0}; - std::size_t height{0}; - int x{0}; - int y{0}; - bool dirty{true}; - bool visible{true}; - - // Add optional dirty rect that this pixelbuffer took up since it was last - // rendered. Make sure to update this list on resize and/or move. - std::size_t last_width{0}; - std::size_t last_height{0}; - int last_x{0}; - int last_y{0}; - bool has_last{false}; -}; - -} // GUI:: diff --git a/plugingui/powerbutton.cc b/plugingui/powerbutton.cc deleted file mode 100644 index 5bf2a2c..0000000 --- a/plugingui/powerbutton.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * powerbutton.cc - * - * Thu Mar 23 12:30:50 CET 2017 - * Copyright 2017 AndrĂ© Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "powerbutton.h" - -#include "painter.h" - -namespace GUI -{ - -PowerButton::PowerButton(Widget* parent) : Toggle(parent) -{ -} - -void PowerButton::setEnabled(bool enabled) -{ - this->enabled = enabled; - - redraw(); -} - -void PowerButton::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - // disabled - if(!enabled) - { - if(clicked) - { - p.drawImage(0, 0, disabled_clicked); - } - else - { - p.drawImage(0, 0, disabled); - } - return; - } - - // enabled and on - if(state) - { - if(clicked) - { - p.drawImage(0, 0, on_clicked); - } - else - { - p.drawImage(0, 0, on); - } - return; - } - - // enabled and off - if(clicked) - { - p.drawImage(0, 0, off_clicked); - } - else - { - p.drawImage(0, 0, off); - } -} - -} // GUI:: diff --git a/plugingui/powerbutton.h b/plugingui/powerbutton.h deleted file mode 100644 index 14dbeca..0000000 --- a/plugingui/powerbutton.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * powerbutton.h - * - * Thu Mar 23 12:30:50 CET 2017 - * Copyright 2017 AndrĂ© Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "texture.h" -#include "toggle.h" - -namespace GUI -{ - -class PowerButton : public Toggle -{ -public: - PowerButton(Widget* parent); - virtual ~PowerButton() = default; - - void setEnabled(bool enabled); - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - - bool enabled = true; - -private: - Texture on{getImageCache(), ":resources/bypass_button.png", 32, 0, 16, 16}; - Texture on_clicked{getImageCache(), ":resources/bypass_button.png", 48, 0, 16, 16}; - Texture off{getImageCache(), ":resources/bypass_button.png", 0, 0, 16, 16}; - Texture off_clicked{getImageCache(), ":resources/bypass_button.png", 16, 0, 16, 16}; - Texture disabled{getImageCache(), ":resources/bypass_button.png", 64, 0, 16, 16}; - Texture disabled_clicked{getImageCache(), ":resources/bypass_button.png", 80, 0, 16, 16}; -}; - -} // GUI:: diff --git a/plugingui/powerwidget.cc b/plugingui/powerwidget.cc index 0a565e6..301f396 100644 --- a/plugingui/powerwidget.cc +++ b/plugingui/powerwidget.cc @@ -26,11 +26,11 @@ */ #include "powerwidget.h" -#include "painter.h" +#include +#include #include #include -#include #include #include diff --git a/plugingui/powerwidget.h b/plugingui/powerwidget.h index c5c6665..8398f75 100644 --- a/plugingui/powerwidget.h +++ b/plugingui/powerwidget.h @@ -26,13 +26,14 @@ */ #pragma once -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include + #include struct Settings; diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc deleted file mode 100644 index dd3e130..0000000 --- a/plugingui/progressbar.cc +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * progressbar.cc - * - * Fri Mar 22 22:07:57 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "progressbar.h" - -namespace GUI -{ - -ProgressBar::ProgressBar(Widget *parent) - : Widget(parent) -{ -} - -ProgressBar::~ProgressBar() -{ -} - -void ProgressBar::setState(ProgressBarState state) -{ - if(this->state != state) - { - this->state = state; - redraw(); - } -} - -void ProgressBar::setTotal(std::size_t total) -{ - if(this->total != total) - { - this->total = total; - redraw(); - } -} - -void ProgressBar::setValue(std::size_t value) -{ - if(this->value != value) - { - this->value = value; - redraw(); - } -} - -void ProgressBar::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - float progress = 0.0f; - if(total != 0) - { - progress = (float)value / (float)total; - } - - int brd = 4; - int val = (width() - (2 * brd)) * progress; - - bar_bg.setSize(width(), height()); - p.drawImage(0, 0, bar_bg); - - switch(state) - { - case ProgressBarState::Red: - bar_red.setSize(val, height()); - p.drawImage(brd, 0, bar_red); - break; - case ProgressBarState::Green: - bar_green.setSize(val, height()); - p.drawImage(brd, 0, bar_green); - break; - case ProgressBarState::Blue: - bar_blue.setSize(val, height()); - p.drawImage(brd, 0, bar_blue); - break; - case ProgressBarState::Off: - return; - } - -} - -} // GUI:: diff --git a/plugingui/progressbar.h b/plugingui/progressbar.h deleted file mode 100644 index 76cc6fd..0000000 --- a/plugingui/progressbar.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * progressbar.h - * - * Fri Mar 22 22:07:57 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "widget.h" - -#include "guievent.h" -#include "painter.h" -#include "texturedbox.h" - -namespace GUI -{ - -enum class ProgressBarState -{ - Red, - Green, - Blue, - Off -}; - -class ProgressBar - : public Widget -{ -public: - ProgressBar(Widget* parent); - virtual ~ProgressBar(); - - void setTotal(std::size_t total); - void setValue(std::size_t value); - - void setState(ProgressBarState state); - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - -private: - ProgressBarState state{ProgressBarState::Blue}; - - TexturedBox bar_bg{getImageCache(), ":resources/progress.png", - 0, 0, // atlas offset (x, y) - 6, 1, 6, // dx1, dx2, dx3 - 11, 0, 0}; // dy1, dy2, dy3 - - TexturedBox bar_red{getImageCache(), ":resources/progress.png", - 13, 0, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 11, 0, 0}; // dy1, dy2, dy3 - - TexturedBox bar_green{getImageCache(), ":resources/progress.png", - 18, 0, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 11, 0, 0}; // dy1, dy2, dy3 - - TexturedBox bar_blue{getImageCache(), ":resources/progress.png", - 23, 0, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 11, 0, 0}; // dy1, dy2, dy3 - - std::size_t total{0}; - std::size_t value{0}; -}; - -} // GUI:: diff --git a/plugingui/rcgen.cc b/plugingui/rcgen.cc deleted file mode 100644 index f7b5590..0000000 --- a/plugingui/rcgen.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * rcgen.cc - * - * Sun Mar 17 20:27:17 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include -#include -#include -#include - -#include - -std::string usage(const std::string& name, bool brief = false) -{ - std::ostringstream output; - output << - "Usage: " << name << " [options]\n"; - if(!brief) - { - output << - "\n" - "Create resource file from list of input files.\n" - "\n"; - } - return output.str(); -} - -int main(int argc, char *argv[]) -{ - bool verbose{false}; - std::vector stripPrefixes; - std::string dirRoot; - std::string outfile; - - dg::Options opt; - - opt.add("strip-path", required_argument, 's', - "Strip supplied path prefix from resource names.", - [&]() - { - stripPrefixes.push_back(optarg); - return 0; - }); - - opt.add("dir-root", required_argument, 'd', - "Change to supplied root dir before reading files.", - [&]() - { - dirRoot = optarg; - return 0; - }); - - opt.add("output", required_argument, 'o', - "Write output to specificed file, defaults to stdout.", - [&]() - { - outfile = optarg; - return 0; - }); - - opt.add("verbose", no_argument, 'v', - "Print verbose output during processing.", - [&]() - { - verbose = true; - return 0; - }); - - opt.add("help", no_argument, 'h', - "Print this message and exit.", - [&]() - { - std::cout << usage(argv[0]); - std::cout << "Options:\n"; - opt.help(); - exit(0); - return 0; - }); - - if(opt.process(argc, argv) != 0) - { - return 1; - } - - FILE* out = stdout; - if(!outfile.empty()) - { - out = fopen(outfile.data(), "wb"); - if(!out) - { - fprintf(stderr, "Could not write to file '%s' - quitting\n", - outfile.data()); - return 1; - - } - } - - fprintf(out, "/* This file is autogenerated by rcgen. Do not modify! */\n"); - fprintf(out, "#include \"resource_data.h\"\n"); - fprintf(out, "\n"); - fprintf(out, "const rc_data_t rc_data[] =\n"); - fprintf(out, "{\n"); - - if(!dirRoot.empty()) - { - if(verbose) - { - fprintf(stderr, "Change to dir: %s\n", dirRoot.data()); - } - - if(chdir(dirRoot.data())) - { - return 1; - } - } - - for(const auto& arg : opt.arguments()) - { - std::string resourceName = arg; - for(const auto& stripPrefix : stripPrefixes) - { - if(stripPrefix == resourceName.substr(0, stripPrefix.length())) - { - resourceName = resourceName.substr(stripPrefix.length()); - break; - } - } - - fprintf(out, " {\n \":%s\", ", resourceName.data()); - - if(verbose) - { - fprintf(stderr, "Process: %s\n", arg.data()); - } - - std::string data; - FILE *fp = fopen(arg.data(), "rb"); - if(!fp) - { - fprintf(stderr, "Could not read file '%s' - quitting\n", arg.data()); - return 1; - } - - char buf[32]; - while(!feof(fp)) - { - std::size_t sz = fread(buf, 1, sizeof(buf), fp); - data.append(buf, sz); - } - fclose(fp); - - fprintf(out, "%d,\n \"", (int)data.length()); - for(std::size_t j = 0; j < data.length(); ++j) - { - if((j != 0) && (j % 16) == 0) - { - fprintf(out, "\"\n \""); - } - fprintf(out, "\\%o", (unsigned char)data[j]); - } - - fprintf(out, "\"\n },\n"); - } - - fprintf(out, " { \"\", 0, 0 }\n"); - fprintf(out, "};\n"); - - return 0; -} diff --git a/plugingui/resamplingframecontent.h b/plugingui/resamplingframecontent.h index 3efc62e..e66bec5 100644 --- a/plugingui/resamplingframecontent.h +++ b/plugingui/resamplingframecontent.h @@ -26,10 +26,10 @@ */ #pragma once -#include "widget.h" -#include "textedit.h" -#include "knob.h" -#include "label.h" +#include +#include +#include +#include class SettingsNotifier; struct Settings; diff --git a/plugingui/resource.cc b/plugingui/resource.cc deleted file mode 100644 index 44f5540..0000000 --- a/plugingui/resource.cc +++ /dev/null @@ -1,192 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * resource.cc - * - * Sun Mar 17 19:38:04 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "resource.h" - -#include -#include -#include - -#include - -#if DG_PLATFORM != DG_PLATFORM_WINDOWS -#include -#include -#include -#endif - -// rcgen generated file containing rc_data declaration. -#include "resource_data.h" - -namespace GUI -{ - -// TODO: Replace with std::filesystem::is_regular_file once we update the -// compiler to require C++17 -static bool pathIsFile(const std::string& path) -{ -#if DG_PLATFORM == DG_PLATFORM_WINDOWS - return (GetFileAttributesA(path.data()) & FILE_ATTRIBUTE_DIRECTORY) == 0; -#else - struct stat s; - if(stat(path.data(), &s) != 0) - { - return false; // error - } - - return (s.st_mode & S_IFREG) != 0; // s.st_mode & S_IFDIR => dir -#endif -} - -// Internal resources start with a colon. -static bool nameIsInternal(const std::string& name) -{ - return name.size() && (name[0] == ':'); -} - -Resource::Resource(const std::string& name) -{ - isValid = false; - - if(nameIsInternal(name)) - { - // Use internal resource: - - // Find internal resource in rc_data. - const rc_data_t* p = rc_data; - while(*p->name) // last entry in rc_data has the name := "" - { - if(name == p->name) - { - internalData = p->data; - internalSize = p->size; - break; - } - ++p; - } - - // We did not find the named resource. - if(internalData == nullptr) - { - ERR(rc, "Could not find '%s'\n", name.c_str()); - return; - } - - isInternal = true; - } - else - { - if(!pathIsFile(name)) - { - return; - } - - // Read from file: - std::FILE *fp = std::fopen(name.data(), "rb"); - if(!fp) - { - return; - } - - // Get the file size - if(std::fseek(fp, 0, SEEK_END) == -1) - { - std::fclose(fp); - return; - } - - long filesize = std::ftell(fp); - - // Apparently fseek doesn't fail if fp points to a directory that has been - // opened (which doesn't fail either!!) and ftell will then fail by either - // returning -1 or LONG_MAX - if(filesize == -1L || filesize == LONG_MAX) - { - std::fclose(fp); - return; - } - - // Reserve space in the string for the data. - externalData.reserve(filesize); - - // Rewind and read... - std::rewind(fp); - - char buffer[32]; - while(!std::feof(fp)) - { - size_t size = std::fread(buffer, 1, sizeof(buffer), fp); - externalData.append(buffer, size); - } - - std::fclose(fp); - - isInternal = false; - } - - isValid = true; -} - -const char *Resource::data() -{ - if(isValid == false) - { - return nullptr; - } - - if(isInternal) - { - return internalData; - } - else - { - return externalData.data(); - } -} - -size_t Resource::size() -{ - if(isValid == false) - { - return 0; - } - - if(isInternal) - { - return internalSize; - } - else - { - return externalData.length(); - } -} - -bool Resource::valid() -{ - return isValid; -} - -} // GUI:: diff --git a/plugingui/resource.h b/plugingui/resource.h deleted file mode 100644 index 5f7b3b4..0000000 --- a/plugingui/resource.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * resource.h - * - * Sun Mar 17 19:38:03 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -namespace GUI { - -class Resource { -public: - Resource(const std::string& name); - - const char* data(); - size_t size(); - - bool valid(); - -protected: - std::string externalData; - bool isValid{false}; - bool isInternal{false}; - const char *internalData{nullptr}; - size_t internalSize{0}; -}; - -} // GUI:: diff --git a/plugingui/resource_data.h b/plugingui/resource_data.h deleted file mode 100644 index 337caf6..0000000 --- a/plugingui/resource_data.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * resource_data.h - * - * Sun Mar 17 20:25:24 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -typedef struct { - const char *name; - unsigned int size; - const char *data; -} rc_data_t; - -extern const rc_data_t rc_data[]; diff --git a/plugingui/sampleselectionframecontent.cc b/plugingui/sampleselectionframecontent.cc index f0aa5e7..a647144 100644 --- a/plugingui/sampleselectionframecontent.cc +++ b/plugingui/sampleselectionframecontent.cc @@ -28,7 +28,7 @@ #include -#include "painter.h" +#include namespace GUI { diff --git a/plugingui/sampleselectionframecontent.h b/plugingui/sampleselectionframecontent.h index f3636da..d56f545 100644 --- a/plugingui/sampleselectionframecontent.h +++ b/plugingui/sampleselectionframecontent.h @@ -26,10 +26,11 @@ */ #pragma once -#include "knob.h" +#include +#include +#include + #include "labeledcontrol.h" -#include "layout.h" -#include "widget.h" #include diff --git a/plugingui/scrollbar.cc b/plugingui/scrollbar.cc deleted file mode 100644 index 9a17d1d..0000000 --- a/plugingui/scrollbar.cc +++ /dev/null @@ -1,214 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * scrollbar.cc - * - * Sun Apr 14 12:54:58 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "scrollbar.h" - -#include - -#include "painter.h" - -namespace GUI { - -ScrollBar::ScrollBar(Widget *parent) - : Widget(parent) -{ -} - -void ScrollBar::setRange(int r) -{ - rangeValue = r; - setValue(value()); - redraw(); -} - -int ScrollBar::range() -{ - return rangeValue; -} - -void ScrollBar::setMaximum(int m) -{ - maxValue = m; - if(maxValue < rangeValue) - { - rangeValue = maxValue; - } - setValue(value()); - redraw(); -} - -int ScrollBar::maximum() -{ - return maxValue; -} - -void ScrollBar::addValue(int delta) -{ - setValue(value() + delta); -} - -void ScrollBar::setValue(int value) -{ - if(value > (maxValue - rangeValue)) - { - value = maxValue - rangeValue; - } - - if(value < 0) - { - value = 0; - } - - if(currentValue == value) - { - return; - } - - currentValue = value; - - valueChangeNotifier(value); - - redraw(); -} - -int ScrollBar::value() -{ - return currentValue; -} - -//! Draw an up/down arrow at (x,y) with the bounding box size (w,h) -//! If h is negative the arrow will point down, if positive it will point up. -static void drawArrow(Painter &p, int x, int y, int w, int h) -{ - if(h < 0) - { - y -= h; - } - - p.drawLine(x, y, x + (w / 2), y + h); - p.drawLine(x + (w / 2), y + h, x + w, y); - - ++y; - p.drawLine(x, y, x + (w / 2), y + h); - p.drawLine(x + (w / 2), y + h, x + w, y); -} - -void ScrollBar::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - p.clear(); - - p.drawImageStretched(0, 0, bg_img, width(), height()); - - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); - if(!maxValue) - { - return; - } - - { - int h = height() - 2 * width() - 3; - int offset = width() + 2; - - int y_val1 = (currentValue * h) / maxValue; - int y_val2 = ((currentValue + rangeValue) * h) / maxValue - 1; - - p.drawFilledRectangle(2, y_val1 + offset, width() - 1, y_val2 + offset); - } - - p.drawLine(0, 0, 0, height()); - - drawArrow(p, width()/4, width()/4, width()/2, -1 * (width()/3)); - p.drawLine(0, width(), width(), width()); - - drawArrow(p, width()/4, height() - width() + width()/4, width()/2, width()/3); - p.drawLine(0, height() - width(), width(), height() - width()); -} - -void ScrollBar::scrollEvent(ScrollEvent* scrollEvent) -{ - setValue(value() + scrollEvent->delta); -} - -void ScrollBar::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) -{ - if(!dragging) - { - return; - } - - float delta = yOffset - mouseMoveEvent->y; - - int h = height() - 2 * width() - 3; - delta /= (float)h / (float)maxValue; - - int newval = valueOffset - delta; - if(newval != value()) - { - setValue(newval); - } -} - -void ScrollBar::buttonEvent(ButtonEvent* buttonEvent) -{ - // Ignore everything except left clicks. - if(buttonEvent->button != MouseButton::left) - { - return; - } - - if((buttonEvent->y < (int)width()) && buttonEvent->y > 0) - { - if(buttonEvent->direction == Direction::down) - { - addValue(-1); - } - - return; - } - - if((buttonEvent->y > ((int)height() - (int)width())) && - (buttonEvent->y < (int)height())) - { - if(buttonEvent->direction == Direction::down) - { - addValue(1); - } - - return; - } - - if(buttonEvent->direction == Direction::down) - { - yOffset = buttonEvent->y; - valueOffset = value(); - } - - dragging = (buttonEvent->direction == Direction::down); -} - -} // GUI:: diff --git a/plugingui/scrollbar.h b/plugingui/scrollbar.h deleted file mode 100644 index 5e60673..0000000 --- a/plugingui/scrollbar.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * scrollbar.h - * - * Sun Apr 14 12:54:58 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "widget.h" -#include "texture.h" -#include "notifier.h" - -namespace GUI { - -class ScrollBar : public Widget { - friend class ListBoxBasic; -public: - ScrollBar(Widget *parent); - - void setRange(int range); - int range(); - - void setMaximum(int max); - int maximum(); - - void addValue(int delta); - void setValue(int value); - int value(); - - Notifier valueChangeNotifier; // (int value) - -protected: - // From Widget: - bool catchMouse() override { return true; } - void scrollEvent(ScrollEvent* scrollEvent) override; - void repaintEvent(RepaintEvent* repaintEvent) override; - void buttonEvent(ButtonEvent* buttonEvent) override; - void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; - -private: - int maxValue{100}; - int currentValue{0}; - int rangeValue{10}; - - int yOffset{0}; - int valueOffset{0}; - bool dragging{false}; - - Texture bg_img{getImageCache(), ":resources/widget.png", 7, 7, 1, 63}; -}; - -} // GUI:: diff --git a/plugingui/slider.cc b/plugingui/slider.cc deleted file mode 100644 index 15a82b3..0000000 --- a/plugingui/slider.cc +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * slider.cc - * - * Sat Nov 26 18:10:22 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "slider.h" - -#include "painter.h" - -#include -#include - -namespace GUI -{ - -Slider::Slider(Widget* parent) : Widget(parent) -{ - state = State::up; - - current_value = 0.0; - maximum = 1.0; - minimum = 0.0; -} - -void Slider::setValue(float new_value) -{ - current_value = new_value; - if (current_value < 0.) - { - current_value = 0.; - } - else if (current_value > 1.0) { - current_value = 1.0; - } - - redraw(); - clickNotifier(); - valueChangedNotifier(current_value); -} - -float Slider::value() const -{ - return current_value; -} - -void Slider::setColour(Colour colour) -{ - switch (colour) { - case Colour::Green: - active_inner_bar = &inner_bar_green; - break; - case Colour::Red: - active_inner_bar = &inner_bar_red; - break; - case Colour::Blue: - active_inner_bar = &inner_bar_blue; - break; - case Colour::Yellow: - active_inner_bar = &inner_bar_yellow; - break; - case Colour::Purple: - active_inner_bar = &inner_bar_purple; - break; - case Colour::Grey: - active_inner_bar = &inner_bar_grey; - break; - } - - if (enabled) { inner_bar = active_inner_bar; } -} - -void Slider::setEnabled(bool enabled) -{ - this->enabled = enabled; - - if (enabled) { - inner_bar = active_inner_bar; - } - else { - active_inner_bar = inner_bar; - inner_bar = &inner_bar_light_grey; - } - - redraw(); -} - -void Slider::repaintEvent(RepaintEvent* repaintEvent) -{ - Painter p(*this); - - auto inner_offset = (current_value / maximum) * getControlWidth(); - auto button_x = button_offset + inner_offset - (button.width() / 2); - auto button_y = (height() - button.height()) / 2; - - // draw bar - bar.setSize(width(), height()); - p.drawImage(0, 0, bar); - - // draw inner bar - inner_bar->setSize(button_x - bar_boundary, height() - 2 * bar_boundary); - p.drawImage(bar_boundary, bar_boundary, *inner_bar); - - // draw button - p.drawImage(button_x, button_y, button); -} - -void Slider::buttonEvent(ButtonEvent* buttonEvent) -{ - // Ignore everything except left clicks. - if(!enabled || buttonEvent->button != MouseButton::left) - { - return; - } - - if(buttonEvent->direction == Direction::down) - { - state = State::down; - recomputeCurrentValue(buttonEvent->x); - - redraw(); - clickNotifier(); - valueChangedNotifier(current_value); - } - - if(buttonEvent->direction == Direction::up) - { - state = State::up; - recomputeCurrentValue(buttonEvent->x); - - redraw(); - clickNotifier(); - valueChangedNotifier(current_value); - } -} - -void Slider::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) -{ - if(state == State::down) - { - recomputeCurrentValue(mouseMoveEvent->x); - - redraw(); - clickNotifier(); - valueChangedNotifier(current_value); - } -} - -void Slider::scrollEvent(ScrollEvent* scrollEvent) -{ - if (!enabled) { return; } - - current_value -= scrollEvent->delta/(float)getControlWidth(); - if (current_value < 0.) - { - current_value = 0.; - } - else if (current_value > 1.0) { - current_value = 1.0; - } - - redraw(); - clickNotifier(); - valueChangedNotifier(current_value); -} - -std::size_t Slider::getControlWidth() const -{ - if(width() < 2 * button_offset) - { - return 0; - } - - return width() - 2 * button_offset; -} - -void Slider::recomputeCurrentValue(float x) -{ - if(x < button_offset) - { - current_value = 0; - } - else - { - current_value = (x - button_offset) / getControlWidth(); - } - - if (current_value < 0.) - { - current_value = 0.; - } - else if (current_value > 1.0) { - current_value = 1.0; - } -} - -} // GUI:: diff --git a/plugingui/slider.h b/plugingui/slider.h deleted file mode 100644 index 90905fd..0000000 --- a/plugingui/slider.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * slider.h - * - * Sat Nov 26 18:10:22 CET 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "texture.h" -#include "texturedbox.h" -#include "widget.h" - -namespace GUI -{ - -class Slider - : public Widget -{ -public: - Slider(Widget* parent); - virtual ~Slider() = default; - - // From Widget: - bool catchMouse() override - { - return true; - } - bool isFocusable() override - { - return true; - } - - void setValue(float new_value); - float value() const; - - enum class Colour { Green, Red, Blue, Yellow, Purple, Grey }; - // Changes the colour of the inner bar - void setColour(Colour colour); - void setEnabled(bool enabled); - - Notifier<> clickNotifier; - Notifier valueChangedNotifier; // (float value) - -protected: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - virtual void buttonEvent(ButtonEvent* buttonEvent) override; - virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; - virtual void scrollEvent(ScrollEvent* scrollEvent) override; - - bool enabled = true;; - -private: - enum class State - { - up, - down - }; - - float current_value; - float maximum; - float minimum; - - State state; - - TexturedBox bar{getImageCache(), ":resources/slider.png", - 0, 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 7, 1, 7 // dy1, dy2, dy3 - }; - Texture button{ - getImageCache(), ":resources/slider.png", 15, 0, // atlas offset (x, y) - 15, 15 // width, height - }; - - TexturedBox inner_bar_green{getImageCache(), ":resources/slider.png", - 30, 0, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_red{getImageCache(), ":resources/slider.png", - 30, 5, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_blue{getImageCache(), ":resources/slider.png", - 30, 10, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_yellow{getImageCache(), ":resources/slider.png", - 35, 0, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_purple{getImageCache(), ":resources/slider.png", - 35, 5, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_grey{getImageCache(), ":resources/slider.png", - 35, 10, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_turquoise{getImageCache(), ":resources/slider.png", - 40, 0, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_orange{getImageCache(), ":resources/slider.png", - 40, 5, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - TexturedBox inner_bar_light_grey{getImageCache(), ":resources/slider.png", - 40, 10, // atlas offset (x, y) - 2, 1, 2, // dx1, dx2, dx3 - 2, 1, 2 // dy1, dy2, dy3 - }; - - // This points to the inner_bar_* of the current color. - // It should never be a nullptr! - TexturedBox* inner_bar{&inner_bar_blue}; - TexturedBox* active_inner_bar = inner_bar; - - std::size_t bar_boundary{5}; - std::size_t button_offset{7}; - - std::size_t getControlWidth() const; - void recomputeCurrentValue(float x); -}; - -} // GUI:: diff --git a/plugingui/stackedwidget.cc b/plugingui/stackedwidget.cc deleted file mode 100644 index 05f8f3c..0000000 --- a/plugingui/stackedwidget.cc +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * stackedwidget.cc - * - * Mon Nov 21 19:36:49 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "stackedwidget.h" - -namespace GUI -{ - -StackedWidget::StackedWidget(Widget *parent) - : Widget(parent) -{ - CONNECT(this, sizeChangeNotifier, this, &StackedWidget::sizeChanged); -} - -StackedWidget::~StackedWidget() -{ -} - -void StackedWidget::addWidget(Widget *widget) -{ - widgets.push_back(widget); - widget->reparent(this); - - if(currentWidget == nullptr) - { - setCurrentWidget(widget); - } - else - { - widget->setVisible(false); - } -} - -void StackedWidget::removeWidget(Widget *widget) -{ - if(widget == currentWidget) - { - setCurrentWidget(nullptr); - } - - widgets.remove(widget); -} - -Widget *StackedWidget::getCurrentWidget() const -{ - return currentWidget; -} - -void StackedWidget::setCurrentWidget(Widget *widget) -{ - if(widget == currentWidget) - { - return; - } - - if(currentWidget) - { - currentWidget->setVisible(false); - } - - currentWidget = widget; - - if(currentWidget) - { - currentWidget->move(0, 0); - currentWidget->resize(width(), height()); - currentWidget->setVisible(true); - } - - currentChanged(currentWidget); -} - -Widget* StackedWidget::getWidgetAfter(Widget* widget) -{ - bool found_it{false}; - - for(auto w : widgets) - { - if(found_it) - { - return w; - } - - if(w == widget) - { - found_it = true; - } - } - - if(found_it) - { - // widget was the last in the list. - return nullptr; - } - - // The Widget pointed to by 'widget' was not in the list... - return nullptr; -} - -Widget* StackedWidget::getWidgetBefore(Widget* widget) -{ - Widget* last{nullptr}; - - for(auto w : widgets) - { - if(w == widget) - { - return last; - } - - last = w; - } - - // The Widget pointed to by 'widget' was not in the list... - return nullptr; -} - -void StackedWidget::sizeChanged(int width, int height) -{ - // Propagate size change to child: - if(currentWidget) - { - currentWidget->move(0, 0); - currentWidget->resize(width, height); - } -} - -} // GUI:: diff --git a/plugingui/stackedwidget.h b/plugingui/stackedwidget.h deleted file mode 100644 index 24213f7..0000000 --- a/plugingui/stackedwidget.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * stackedwidget.h - * - * Mon Nov 21 19:36:49 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "widget.h" -#include "notifier.h" - -namespace GUI -{ - -//! A StackedWidget is a widget containing a list of widgets but only showing -//! one of them at a time. -//! It is be used to implement a TabWidget but can also be used for other -//! purposes. -class StackedWidget - : public Widget -{ -public: - StackedWidget(Widget* parent); - ~StackedWidget(); - - //! Add a widget to the stack. - void addWidget(Widget* widget); - - //! Remove a widget from the stack. - void removeWidget(Widget* widget); - - //! Get currently visible widget. - Widget* getCurrentWidget() const; - - //! Show widget. Hide all the others. - //! If widget is not in the stack nothing happens. - void setCurrentWidget(Widget* widget); - - //! Returns a pointer to the Widget after the one referenced by 'widget' or - //! nullptr if 'widget' is the last in the list. - Widget* getWidgetAfter(Widget* widget); - - //! Returns a pointer to the Widget beforer the one referenced by 'widget' or - //! nullptr if 'widget' is the first in the list. - Widget* getWidgetBefore(Widget* widget); - - //! Reports whn a new widget is shown. - Notifier currentChanged; - -private: - //! Callback for Widget::sizeChangeNotifier - void sizeChanged(int width, int height); - -private: - Widget* currentWidget{nullptr}; - std::list widgets; -}; - -} // GUI:: diff --git a/plugingui/statusframecontent.h b/plugingui/statusframecontent.h index 998e87c..fdf6d05 100644 --- a/plugingui/statusframecontent.h +++ b/plugingui/statusframecontent.h @@ -27,8 +27,9 @@ #pragma once #include "settings.h" -#include "textedit.h" -#include "widget.h" + +#include +#include class SettingsNotifier; diff --git a/plugingui/tabbutton.cc b/plugingui/tabbutton.cc deleted file mode 100644 index 6a27f61..0000000 --- a/plugingui/tabbutton.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * tabbutton.cc - * - * Thu Nov 24 18:52:26 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "tabbutton.h" - -#include "painter.h" - -namespace GUI -{ - -static TabID getNextTabID() -{ - static TabID next{0}; - next++; - return next; -} - -TabButton::TabButton(Widget* parent, Widget* tab_widget) - : ButtonBase(parent) - , tab_widget(tab_widget) -{ - tab_id = getNextTabID(); - CONNECT(this, clickNotifier, this, &TabButton::clickHandler); -} - -TabButton::~TabButton() -{ -} - -Widget* TabButton::getTabWidget() -{ - return tab_widget; -} - -std::size_t TabButton::getMinimalWidth() const -{ - std::size_t padding = 15; - auto font_width = font.textWidth(text); - - return font_width + padding; -} - -std::size_t TabButton::getMinimalHeight() const -{ - std::size_t padding = 10; - auto font_height= font.textHeight(text); - - return font_height + padding; -} - -void TabButton::setActive(bool active) -{ - this->active = active; - - if (active) { - draw_state = State::Down; - } - else { - draw_state = State::Up; - } - - redraw(); -} - -TabID TabButton::getID() const -{ - return tab_id; -} - -void TabButton::repaintEvent(RepaintEvent* e) -{ - Painter p(*this); - - int padTop = 3; - int padLeft = 0; - int padTextTop = 3; - - int w = width(); - int h = height(); - if(w == 0 || h == 0) - { - return; - } - - if (draw_state == State::Up && !active) { - tab_passive.setSize(w - padLeft, h - padTop); - p.drawImage(padLeft, padTop, tab_passive); - } - else { - tab_active.setSize(w - padLeft, h - padTop); - p.drawImage(padLeft, padTop, tab_active); - } - - auto x = padLeft + (width() - font.textWidth(text)) / 2; - auto y = padTop + padTextTop + font.textHeight(text); - p.drawText(x, y, font, text, true); -} - -void TabButton::scrollEvent(ScrollEvent* scroll_event) -{ - scrollNotifier(scroll_event->delta); -} - -void TabButton::clickHandler() -{ - switchTabNotifier(tab_widget); -} - -} // GUI:: diff --git a/plugingui/tabbutton.h b/plugingui/tabbutton.h deleted file mode 100644 index 1e9371a..0000000 --- a/plugingui/tabbutton.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * tabbutton.h - * - * Thu Nov 24 18:52:26 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include "button_base.h" -#include "font.h" -#include "texturedbox.h" - -namespace GUI -{ - -class ScrollEvent; - -using TabID = int; - -class TabButton - : public ButtonBase -{ -public: - TabButton(Widget* parent, Widget* tab_widget); - virtual ~TabButton(); - - Widget* getTabWidget(); - std::size_t getMinimalWidth() const; - std::size_t getMinimalHeight() const; - void setActive(bool active); - - TabID getID() const; - - Notifier switchTabNotifier; - Notifier scrollNotifier; // float delta - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* e) override; - virtual void scrollEvent(ScrollEvent* scroll_event) override; - -private: - TabID tab_id; - - void clickHandler(); - - Widget* tab_widget; - bool active{false}; - - TexturedBox tab_active{getImageCache(), ":resources/tab.png", - 0, 0, // atlas offset (x, y) - 5, 1, 5, // dx1, dx2, dx3 - 5, 13, 1}; // dy1, dy2, dy3 - - TexturedBox tab_passive{getImageCache(), ":resources/tab.png", - 11, 0, // atlas offset (x, y) - 5, 1, 5, // dx1, dx2, dx3 - 5, 13, 1}; // dy1, dy2, dy3 - - Font font{":resources/fontemboss.png"}; -}; - -} // GUI:: diff --git a/plugingui/tabwidget.cc b/plugingui/tabwidget.cc deleted file mode 100644 index 635f1bd..0000000 --- a/plugingui/tabwidget.cc +++ /dev/null @@ -1,214 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * tabwidget.cc - * - * Thu Nov 24 17:46:22 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "tabwidget.h" - -#include "painter.h" - -namespace GUI -{ - -TabWidget::TabWidget(Widget *parent) - : Widget(parent) - , stack(this) -{ - CONNECT(this, sizeChangeNotifier, this, &TabWidget::sizeChanged); - CONNECT(&stack, currentChanged, this, &TabWidget::setActiveButtons); -} - -TabID TabWidget::addTab(const std::string& title, Widget* widget) -{ - buttons.emplace_back(this, widget); - auto& button = buttons.back(); - button.setText(title); - stack.addWidget(widget); - CONNECT(&button, switchTabNotifier, this, &TabWidget::switchTab); - CONNECT(&button, scrollNotifier, this, &TabWidget::rotateTab); - sizeChanged(width(), height()); - return button.getID(); -} - -void TabWidget::setTabWidth(std::size_t width) -{ - tab_width = width; - relayout(); -} - -std::size_t TabWidget::getTabWidth() const -{ - return tab_width; -} - -void TabWidget::setVisible(TabID tab_id, bool visible) -{ - for (auto& button : buttons) - { - if(button.getID() == tab_id) - { - button.setVisible(visible); - relayout(); - return; - } - } -} - -std::size_t TabWidget::getBarHeight() const -{ - return topbar.height(); -} - -void TabWidget::rotateTab(float delta) -{ - Widget* widget{nullptr}; - Widget* current = stack.getCurrentWidget(); - if(delta > 0.0f) - { - while((widget = stack.getWidgetAfter(current)) != nullptr) - { - auto button = getButtonFromWidget(widget); - if(!button || !button->visible()) - { - current = widget; - continue; - } - break; - } - } - else - { - while((widget = stack.getWidgetBefore(current)) != nullptr) - { - auto button = getButtonFromWidget(widget); - if(!button || !button->visible()) - { - current = widget; - continue; - } - break; - } - } - - if(widget) - { - switchTab(widget); - } -} - -void TabWidget::switchTab(Widget* tab_widget) -{ - stack.setCurrentWidget(tab_widget); -} - -void TabWidget::setActiveButtons(Widget* current_widget) -{ - for (auto& button : buttons) { - if (button.getTabWidget() == current_widget) { - button.setActive(true); - } - else - { - button.setActive(false); - } - } -} - -void TabWidget::sizeChanged(int width, int height) -{ - std::size_t pos = 0; - - int button_width = tab_width; - int bar_height = 25; - int button_border_width = 10; - - int button_padding_left = 25; - int button_padding_inner = 3; - int logo_padding_right = button_padding_left / 2; - - Painter p(*this); - - if(buttons.size() > 0) - { - for(auto& button : buttons) - { - if(!button.visible()) - { - continue; - } - int min_width = button.getMinimalWidth(); - button_width = std::max(button_width, min_width + button_border_width); - } - - button_width = std::min(button_width, width / (int)buttons.size()); - } - - // draw the upper bar - topbar.setSize(width, bar_height); - p.drawImage(0, 0, topbar); - auto x_logo = width - toplogo.width() - logo_padding_right; - auto y_logo = (bar_height - toplogo.height()) / 2; - p.drawImage(x_logo, y_logo, toplogo); - - // place the buttons - pos = button_padding_left; - for(auto& button : buttons) - { - if(!button.visible()) - { - continue; - } - button.resize(button_width, bar_height); - button.move(pos, 0); - pos += button_width + button_padding_inner; - } - - stack.move(0, bar_height); - stack.resize(width, std::max((int)height - bar_height, 0)); -} - -void TabWidget::relayout() -{ - sizeChanged(TabWidget::width(), TabWidget::height()); // Force re-layout -} - -const TabButton* TabWidget::getButtonFromWidget(const Widget* tab_widget) -{ - if(tab_widget == nullptr) - { - return nullptr; - } - - for(auto& button : buttons) - { - if(button.getTabWidget() == tab_widget) - { - return &button; - } - } - - return nullptr; -} - -} // GUI:: diff --git a/plugingui/tabwidget.h b/plugingui/tabwidget.h deleted file mode 100644 index 129826a..0000000 --- a/plugingui/tabwidget.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * tabwidget.h - * - * Thu Nov 24 17:46:22 CET 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "widget.h" -#include "tabbutton.h" -#include "stackedwidget.h" -#include "texture.h" - -namespace GUI -{ - -class TabWidget - : public Widget -{ -public: - TabWidget(Widget *parent); - - //! Add new tab to the tab widget. - //! \param title The title to display on the tab button. - //! \param widget The widget to show in the tab. - //! \returns The TabID of the newly added tab. - TabID addTab(const std::string& title, Widget* widget); - - std::size_t getBarHeight() const; - - void setTabWidth(std::size_t width); - std::size_t getTabWidth() const; - - void setVisible(TabID tab_id, bool visible); - -private: - //! Callback for Widget::sizeChangeNotifier - void sizeChanged(int width, int height); - -private: - void relayout(); - //! Switch to the next tab if delta is > 0 or previous tab if delta is <= 0. - void rotateTab(float delta); - void switchTab(Widget* tabWidget); - void setActiveButtons(Widget* current_widget); - - const TabButton* getButtonFromWidget(const Widget* tab_widget); - - std::list buttons; - StackedWidget stack; - - TexturedBox topbar{getImageCache(), ":resources/topbar.png", - 0, 0, // atlas offset (x, y) - 1, 1, 1, // dx1, dx2, dx3 - 17, 1, 1}; // dy1, dy2, dy3 - - Texture toplogo{getImageCache(), ":resources/toplogo.png", - 0, 0, // atlas offset (x, y) - 95, 17}; // width, height - - std::size_t tab_width{64}; -}; - -} // GUI:: diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc index 3f73039..4b94083 100644 --- a/plugingui/testmain.cc +++ b/plugingui/testmain.cc @@ -31,10 +31,10 @@ #include #include -#include "mainwindow.h" -#include "window.h" -#include "resource.h" -#include "uitranslation.h" +#include +#include +#include + #include "mainwindow.h" int main() diff --git a/plugingui/textedit.cc b/plugingui/textedit.cc deleted file mode 100644 index 9688b82..0000000 --- a/plugingui/textedit.cc +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * lineedit.cc - * - * Tue Oct 21 11:25:26 CEST 2014 - * Copyright 2014 Jonas Suhr Christensen - * jsc@umbraculum.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "textedit.h" - -#include "painter.h" - -namespace GUI -{ - -TextEdit::TextEdit(Widget* parent) : Widget(parent), scroll(this) -{ - setReadOnly(true); - - scroll.move(width() - 2*x_border - 3, y_border - 1); - scroll.resize(16, 100); - CONNECT(&scroll, valueChangeNotifier, this, &TextEdit::scrolled); -} - -TextEdit::~TextEdit() -{ -} - -void TextEdit::resize(std::size_t width, std::size_t height) -{ - Widget::resize(width, height); - - needs_preprocessing = true; - scroll.move(width - 2*x_border - 3, y_border - 1); - scroll.resize(scroll.width(), std::max((int)height - 2*(y_border - 1), 0)); -} - -void TextEdit::setReadOnly(bool readonly) -{ - this->readonly = readonly; -} - -bool TextEdit::readOnly() -{ - return readonly; -} - -void TextEdit::setText(const std::string& text) -{ - this->text = text; - - needs_preprocessing = true; - redraw(); - textChangedNotifier(); -} - -std::string TextEdit::getText() -{ - return text; -} - -void TextEdit::preprocessText() -{ - std::vector lines; - - preprocessed_text.clear(); - std::string text = this->text; - - // Handle tab characters - for(std::size_t i = 0; i < text.length(); ++i) - { - char ch = text.at(i); - if(ch == '\t') - { - text.erase(i, 1); - text.insert(i, 4, ' '); - } - } - - // Handle "\r" - for(std::size_t i = 0; i < text.length(); ++i) - { - char ch = text.at(i); - if(ch == '\r') - { - text.erase(i, 1); - } - } - - // Handle new line characters - std::size_t pos = 0; - do - { - pos = text.find("\n"); - lines.push_back(text.substr(0, pos)); - text = text.substr(pos + 1); - } while(pos != std::string::npos); - - // Wrap long lines - auto const max_width = width() - 2*x_border - 10 - scroll.width(); - for(auto const& line: lines) - { - std::string valid; - std::string current; - for(auto c: line) - { - current += c; - if(c == ' ') - { - valid.append(current.substr(valid.size())); - } - - if(font.textWidth(current) >= max_width) - { - if(valid.empty()) - { - current.pop_back(); - preprocessed_text.push_back(current); - current = c; - } - else - { - current = current.substr(valid.size()); - valid.pop_back(); - preprocessed_text.push_back(valid); - valid.clear(); - } - } - } - preprocessed_text.push_back(current); - } -} - -void TextEdit::repaintEvent(RepaintEvent* repaintEvent) -{ - if(needs_preprocessing) - { - preprocessText(); - } - - Painter p(*this); - - // update values of scroll bar - scroll.setRange(height() / font.textHeight()); - scroll.setMaximum(preprocessed_text.size()); - - if((width() == 0) || (height() == 0)) - { - return; - } - - box.setSize(width(), height()); - p.drawImage(0, 0, box); - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); - - int ypos = font.textHeight() + y_border; - - auto scroll_value = scroll.value(); - for(std::size_t i = 0; i < preprocessed_text.size() - scroll_value; ++i) - { - if(i * font.textHeight() >= (height() - y_border - font.textHeight())) - { - break; - } - - auto const& line = preprocessed_text[scroll_value + i]; - p.drawText(x_border, ypos, font, line); - ypos += font.textHeight(); - } -} - -void TextEdit::scrollEvent(ScrollEvent* scrollEvent) -{ - scroll.setValue(scroll.value() + scrollEvent->delta); -} - -void TextEdit::scrolled(int value) -{ - (void)value; - redraw(); -} - -} // GUI:: diff --git a/plugingui/textedit.h b/plugingui/textedit.h deleted file mode 100644 index 17a04ff..0000000 --- a/plugingui/textedit.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * textedit.h - * - * Tue Oct 21 11:23:58 CEST 2014 - * Copyright 2014 Jonas Suhr Christensen - * jsc@umbraculum.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include "font.h" -#include "notifier.h" -#include "scrollbar.h" -#include "texturedbox.h" -#include "widget.h" - -namespace GUI -{ - -class TextEdit - : public Widget -{ -public: - TextEdit(Widget* parent); - virtual ~TextEdit(); - - // From Widget - bool isFocusable() override - { - return true; - } - void resize(std::size_t width, std::size_t height) override; - - std::string getText(); - void setText(const std::string& text); - - void setReadOnly(bool readonly); - bool readOnly(); - - void preprocessText(); - - Notifier<> textChangedNotifier; - -protected: - // From Widget - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - void scrollEvent(ScrollEvent* scrollEvent) override; - -private: - void scrolled(int value); - - TexturedBox box{getImageCache(), ":resources/widget.png", 0, - 0, // atlas offset (x, y) - 7, 1, 7, // dx1, dx2, dx3 - 7, 63, 7}; // dy1, dy2, dy3 - - static constexpr int x_border{10}; - static constexpr int y_border{8}; - - ScrollBar scroll; - Font font; - - std::string text; - - bool readonly{true}; - bool needs_preprocessing{false}; - - std::vector preprocessed_text; -}; - -} // GUI:: diff --git a/plugingui/texture.cc b/plugingui/texture.cc deleted file mode 100644 index 8cd7040..0000000 --- a/plugingui/texture.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * texture.cc - * - * Sat Jun 4 21:18:11 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "texture.h" - -namespace GUI -{ - -Texture::Texture(ImageCache& image_cache, const std::string& filename, - std::size_t x, std::size_t y, - std::size_t width, std::size_t height) - : ScopedImageBorrower(image_cache, filename) - , _x(x) - , _y(y) - , _width(width>image.width()?image.width():width) - , _height(height>image.height()?image.height():height) -{ -} - -size_t Texture::width() const -{ - return _width; -} - -size_t Texture::height() const -{ - return _height; -} - -const Colour& Texture::getPixel(size_t x, size_t y) const -{ - if(x > _width || y > _height) - { - return outOfRange; - } - return image.getPixel(x + _x, y + _y); -} - -const std::uint8_t* Texture::line(std::size_t y, std::size_t x_offset) const -{ - return image.line(y + _y) + _x * 4 + x_offset * 4; -} - -bool Texture::hasAlpha() const -{ - return true; -} - -} // GUI:: diff --git a/plugingui/texture.h b/plugingui/texture.h deleted file mode 100644 index c751ed4..0000000 --- a/plugingui/texture.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * texture.h - * - * Sat Jun 4 21:18:11 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include "imagecache.h" -#include "image.h" - -namespace GUI -{ - -class Texture - : public ScopedImageBorrower - , public Drawable -{ -public: - Texture(ImageCache& image_cache, const std::string& filename, - std::size_t x = 0, std::size_t y = 0, - std::size_t width = std::numeric_limits::max(), - std::size_t height = std::numeric_limits::max()); - - size_t width() const override; - size_t height() const override; - - const Colour& getPixel(size_t x, size_t y) const override; - const std::uint8_t* line(std::size_t y, - std::size_t x_offset = 0) const override; - bool hasAlpha() const override; - -private: - std::size_t _x; - std::size_t _y; - std::size_t _width; - std::size_t _height; - Colour outOfRange{0.0f, 0.0f, 0.0f, 0.0f}; -}; - -} // GUI:: diff --git a/plugingui/texturedbox.cc b/plugingui/texturedbox.cc deleted file mode 100644 index e48353a..0000000 --- a/plugingui/texturedbox.cc +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * texturedbox.cc - * - * Sun Jun 5 12:22:15 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "texturedbox.h" - -#include - -namespace GUI -{ - -TexturedBox::TexturedBox(ImageCache& image_cache, const std::string& filename, - std::size_t x0, std::size_t y0, - std::size_t dx1, std::size_t dx2, std::size_t dx3, - std::size_t dy1, std::size_t dy2, std::size_t dy3) - : seg_a(image_cache, filename, x0 , y0 , dx1, dy1) - , seg_b(image_cache, filename, x0 + dx1 , y0 , dx2, dy1) - , seg_c(image_cache, filename, x0 + dx1 + dx2, y0 , dx3, dy1) - , seg_d(image_cache, filename, x0 , y0 + dy1 , dx1, dy2) - , seg_e(image_cache, filename, x0 + dx1 , y0 + dy1 , dx2, dy2) - , seg_f(image_cache, filename, x0 + dx1 + dx2, y0 + dy1 , dx3, dy2) - , seg_g(image_cache, filename, x0 , y0 + dy1 + dy2, dx1, dy3) - , seg_h(image_cache, filename, x0 + dx1 , y0 + dy1 + dy2, dx2, dy3) - , seg_i(image_cache, filename, x0 + dx1 + dx2, y0 + dy1 + dy2, dx3, dy3) - , dx1(dx1) - , dx2(dx2) - , dx3(dx3) - , dy1(dy1) - , dy2(dy2) - , dy3(dy3) - , _width(dx1 + dx2 + dx3) - , _height(dy1 + dy2 + dy3) -{ -} - -std::size_t TexturedBox::width() const -{ - return _width; -} - -std::size_t TexturedBox::height() const -{ - return _height; -} - -void TexturedBox::setSize(std::size_t width, std::size_t height) -{ - _width = width; - _height = height; -} - -const Colour& TexturedBox::getPixel(std::size_t x, std::size_t y) const -{ - assert(x < _width); - assert(y < _height); - - if(y < dy1) // row 1 - { - if(x < dx1) // col 1 - { - return seg_a.getPixel(x, y); - } - else if(x < (_width - dx3)) // col 2 - { - float scale = (float)(x - dx1) / (float)(_width - dx1 - dx3); - assert(seg_b.width() == dx2); - return seg_b.getPixel(scale * dx2, y); - } - else // col 3 - { - return seg_c.getPixel(x - (_width - dx3), y); - } - } - else if(y < (_height - dy3)) // row 2 - { - if(x < dx1) // col 1 - { - // TODO: Apply vertical scale - float scale = (float)(y - dy1) / (float)(_height - dy1 - dy3); - return seg_d.getPixel(x, scale * dy2); - } - else if(x < (_width - dx3)) // col 2 - { - float scale_x = (float)(x - dx1) / (float)(_width - dx1 - dx3); - float scale_y = (float)(y - dy1) / (float)(_height - dy1 - dy3); - return seg_e.getPixel(scale_x * dx2, scale_y * dy2); - } - else // col 3 - { - float scale = (float)(y - dy1) / (float)(_height - dy1 - dy3); - return seg_f.getPixel(x - (_width - dx3), scale * dy2); - } - } - else // row 3 - { - if(x < dx1) // col 1 - { - return seg_g.getPixel(x, y - (_height - dy3)); - } - else if(x < (_width - dx3)) // col 2 - { - float scale = (float)(x - dx1) / (float)(_width - dx1 - dx3); - return seg_h.getPixel(scale * dx2, y - (_height - dy3)); - } - else // col 3 - { - return seg_i.getPixel(x - (_width - dx3), y - (_height - dy3)); - } - } - - return outOfRange; -} - -const std::uint8_t* TexturedBox::line(std::size_t y, std::size_t x_offset) const -{ - // TODO: Gather line into temporary buffer? - return nullptr; -} - -bool TexturedBox::hasAlpha() const -{ - return true; -} - -} // GUI:: diff --git a/plugingui/texturedbox.h b/plugingui/texturedbox.h deleted file mode 100644 index 7aa3967..0000000 --- a/plugingui/texturedbox.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * texturedbox.h - * - * Sun Jun 5 12:22:14 CEST 2016 - * Copyright 2016 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "drawable.h" -#include "imagecache.h" -#include "texture.h" - -namespace GUI -{ - -class TexturedBox - : public Drawable -{ -public: - //! Draw a box from 9 image segments nested inside the same image. - //! An image says more than a thousand words: - //! .----------------------------------------. - //! | (x0, y0) | - //! | \ dx1 dx2 dx3 | - //! | .-----+-----------+-----. \ | - //! | dy1 | A | <--B--> | C | | | - //! | +-----+-----------+-----+ | | - //! | | /|\ | /|\ | /|\ | | h | - //! | | | | | | | | | e | - //! | dy2 | D | <--E--> | F | > i | - //! | | | | | | | | | g | - //! | | \|/ | \|/ | \|/ | | h | - //! | +-----+-----------+-----+ | t | - //! | dy3 | G | <--H--> | I | | | - //! | `-----+-----------+-----` / | - //! | | - //! | \___________ ___________/ | - //! | V | - //! | width | - //! `----------------------------------------` - //! - //! \param image_cache A reference to the image cache object. - //! \param filename The filename of the texture image to use. - //! \param (x0, y0) is coordinate of the upper left corner of the A segment. - //! \param (width, height) is the total rendered size of the Box. - //! \param dx1 is the width of the A, C and F segments. - //! \param dx2 is the width of the B, E and H segments. - //! \param dx3 is the width of the C, F and I segments. - //! \param dy1 is the height of the A, B and C segments. - //! \param dy2 is the height of the D, E and F segments. - //! \param dy3 is the height of the G, G and I segments. - //! - //! Segments A, C, G and I are drawn with no stretch. - //! Segments B and H are stretched horizontally to fill the - //! gaps between A, C and G, I so that resulting width is 'width' - //! Segments D and F are stretched vertically to fill the - //! gaps between A, G and C, I so that resulting height is 'height' - //! Segment E will be stretched both horizontally and vertically - //! to fill the inner space between B, H and D, F. - TexturedBox(ImageCache& image_cache, const std::string& filename, - std::size_t x0, std::size_t y0, - std::size_t dx1, std::size_t dx2, std::size_t dx3, - std::size_t dy1, std::size_t dy2, std::size_t dy3); - - // From Drawable: - std::size_t width() const override; - std::size_t height() const override; - - void setSize(std::size_t width, std::size_t height); - - const Colour& getPixel(std::size_t x, std::size_t y) const override; - const std::uint8_t* line(std::size_t y, - std::size_t x_offset = 0) const override; - bool hasAlpha() const override; - -private: - Texture seg_a; - Texture seg_b; - Texture seg_c; - Texture seg_d; - Texture seg_e; - Texture seg_f; - Texture seg_g; - Texture seg_h; - Texture seg_i; - - std::size_t dx1; - std::size_t dx2; - std::size_t dx3; - std::size_t dy1; - std::size_t dy2; - std::size_t dy3; - std::size_t _width{100}; - std::size_t _height{100}; - - Colour outOfRange{0.0f, 0.0f, 0.0f, 0.0f}; -}; - -} // GUI:: diff --git a/plugingui/timingframecontent.cc b/plugingui/timingframecontent.cc index ceaf5be..ffcd07e 100644 --- a/plugingui/timingframecontent.cc +++ b/plugingui/timingframecontent.cc @@ -29,7 +29,7 @@ #include #include -#include "painter.h" +#include namespace GUI { diff --git a/plugingui/timingframecontent.h b/plugingui/timingframecontent.h index 3dde8c1..adecc01 100644 --- a/plugingui/timingframecontent.h +++ b/plugingui/timingframecontent.h @@ -26,11 +26,12 @@ */ #pragma once -#include "knob.h" -#include "label.h" +#include +#include +#include +#include + #include "labeledcontrol.h" -#include "layout.h" -#include "widget.h" #include diff --git a/plugingui/toggle.cc b/plugingui/toggle.cc deleted file mode 100644 index 39587de..0000000 --- a/plugingui/toggle.cc +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * toggle.cc - * - * Wed Mar 22 22:58:57 CET 2017 - * Copyright 2017 AndrĂ© Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "toggle.h" - -namespace GUI -{ - -Toggle::Toggle(Widget* parent) : Widget(parent) -{ -} - -void Toggle::buttonEvent(ButtonEvent* buttonEvent) -{ - // Ignore everything except left clicks. - if(buttonEvent->button != MouseButton::left) - { - return; - } - - if((buttonEvent->direction == Direction::up) || buttonEvent->doubleClick) - { - buttonDown = false; - clicked = false; - if(inCheckbox) - { - internalSetChecked(!state); - } - } - else - { - buttonDown = true; - clicked = true; - } - - redraw(); -} - -void Toggle::setText(std::string text) -{ - _text = text; - redraw(); -} - -bool Toggle::checked() -{ - return state; -} - -void Toggle::setChecked(bool c) -{ - internalSetChecked(c); -} - -void Toggle::mouseLeaveEvent() -{ - inCheckbox = false; - if(buttonDown) - { - clicked = false; - redraw(); - } -} - -void Toggle::mouseEnterEvent() -{ - inCheckbox = true; - if(buttonDown) - { - clicked = true; - redraw(); - } -} - -void Toggle::internalSetChecked(bool checked) -{ - if(state == checked) - { - return; - } - - state = checked; - stateChangedNotifier(state); - redraw(); -} - -} // GUI:: diff --git a/plugingui/toggle.h b/plugingui/toggle.h deleted file mode 100644 index 3466459..0000000 --- a/plugingui/toggle.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * toggle.h - * - * Wed Mar 22 22:58:57 CET 2017 - * Copyright 2017 AndrĂ© Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "widget.h" - -#include - -namespace GUI -{ - -class Toggle : public Widget -{ -public: - Toggle(Widget* parent); - virtual ~Toggle() = default; - - void setText(std::string text); - - // From Widget: - bool isFocusable() override { return true; } - bool catchMouse() override { return true; } - - bool checked(); - void setChecked(bool checked); - - Notifier stateChangedNotifier; - -protected: - // From Widget: - virtual void buttonEvent(ButtonEvent* buttonEvent) override; - virtual void mouseLeaveEvent() override; - virtual void mouseEnterEvent() override; - - bool state{false}; - bool clicked{false}; - bool buttonDown{false}; - bool inCheckbox{false}; - - std::string _text; - -private: - void internalSetChecked(bool checked); -}; - -} // GUI:: diff --git a/plugingui/tooltip.cc b/plugingui/tooltip.cc deleted file mode 100644 index e251ed5..0000000 --- a/plugingui/tooltip.cc +++ /dev/null @@ -1,200 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * tooltip.cc - * - * Wed May 8 17:31:42 CEST 2019 - * Copyright 2019 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "tooltip.h" - -#include "painter.h" -#include "font.h" -#include "window.h" -#include - -namespace GUI -{ - -Tooltip::Tooltip(Widget *parent) - : Widget(parent->window()) - , activating_widget(parent) -{ - resize(32, 32); -} - -Tooltip::~Tooltip() -{ -} - -void Tooltip::setText(const std::string& text) -{ - this->text = text; - needs_preprocessing = true; - redraw(); -} - -void Tooltip::resize(std::size_t width, std::size_t height) -{ - Widget::resize(width, height); -} - -void Tooltip::repaintEvent(RepaintEvent* repaintEvent) -{ - if(needs_preprocessing) - { - preprocessText(); - } - - Painter p(*this); - - if((width() == 0) || (height() == 0)) - { - return; - } - - box.setSize(width(), height()); - p.drawImage(0, 0, box); - p.setColour(Colour(183.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 1.0f)); - - int ypos = font.textHeight() + y_border; - - for(std::size_t i = 0; i < preprocessed_text.size(); ++i) - { - if(i * font.textHeight() >= (height() - y_border - font.textHeight())) - { - break; - } - - auto const& line = preprocessed_text[i]; - p.drawText(x_border, ypos, font, line); - ypos += font.textHeight(); - } -} - -void Tooltip::preprocessText() -{ - std::vector lines; - - preprocessed_text.clear(); - std::string text = this->text; - - // Handle tab characters - for(std::size_t i = 0; i < text.length(); ++i) - { - char ch = text.at(i); - if(ch == '\t') - { - text.erase(i, 1); - text.insert(i, 4, ' '); - } - } - - // Handle "\r" - for(std::size_t i = 0; i < text.length(); ++i) - { - char ch = text.at(i); - if(ch == '\r') - { - text.erase(i, 1); - } - } - - // Handle new line characters - std::size_t pos = 0; - do - { - pos = text.find("\n"); - lines.push_back(text.substr(0, pos)); - text = text.substr(pos + 1); - } while(pos != std::string::npos); - - max_text_width = 0; - total_text_height = 0; - for(auto const& line: lines) - { - std::string valid; - std::string current; - for(auto c: line) - { - current += c; - if(c == ' ') - { - valid.append(current.substr(valid.size())); - } - } - preprocessed_text.push_back(current); - - max_text_width = std::max(max_text_width, font.textWidth(line)); - total_text_height += font.textHeight(line); - } -} - -void Tooltip::mouseLeaveEvent() -{ - hide(); -} - -void Tooltip::show() -{ - if(needs_preprocessing) - { - preprocessText(); - } - - resize(max_text_width + 2*x_border, total_text_height + 2*y_border); - - int x = activating_widget->translateToWindowX(); - int y = activating_widget->translateToWindowY(); - - if(x + width() > window()->width()) - { - x -= width(); - x += activating_widget->width(); - } - - if(y + height() > window()->height()) - { - y -= height(); - y += activating_widget->height(); - } - - // Make sure the tip is displayed inside the window - x = std::max(x, 0); - y = std::max(y, 0); - - move(x, y); - Widget::show(); - - // TODO: This should be handled differently - // Hack to notify the window that the mouse is now inside the tooltip. - window()->setMouseFocus(this); -} - -void Tooltip::buttonEvent(ButtonEvent* buttonEvent) -{ - if(buttonEvent->direction == Direction::down) - { - hide(); - } -} - -} // GUI:: diff --git a/plugingui/tooltip.h b/plugingui/tooltip.h deleted file mode 100644 index 9d1619d..0000000 --- a/plugingui/tooltip.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * tooltip.h - * - * Wed May 8 17:31:42 CEST 2019 - * Copyright 2019 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -#include - -#include "widget.h" -#include "painter.h" -#include "texturedbox.h" -#include "font.h" - -namespace GUI -{ - -class Tooltip - : public Widget -{ -public: - Tooltip(Widget *parent); - virtual ~Tooltip(); - - void setText(const std::string& text); - - // From Widget: - virtual void repaintEvent(RepaintEvent* repaint_event) override; - virtual void resize(std::size_t height, std::size_t width) override; - virtual void mouseLeaveEvent() override; - virtual void show() override; - virtual void buttonEvent(ButtonEvent* buttonEvent) override; - -private: - void preprocessText(); - - TexturedBox box{getImageCache(), ":resources/thinlistbox.png", - 0, 0, // atlas offset (x, y) - 1, 1, 1, // dx1, dx2, dx3 - 1, 1, 1}; // dy1, dy2, dy3 - Font font; - - static constexpr int x_border{10}; - static constexpr int y_border{8}; - - bool needs_preprocessing{false}; - std::string text; - std::vector preprocessed_text; - std::size_t max_text_width{0}; - std::size_t total_text_height{0}; - Widget* activating_widget; -}; - -} // GUI:: diff --git a/plugingui/uitranslation.cc b/plugingui/uitranslation.cc deleted file mode 100644 index 0546be8..0000000 --- a/plugingui/uitranslation.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * uitranslation.cc - * - * Thu May 7 18:04:40 CEST 2020 - * Copyright 2020 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "uitranslation.h" - -#ifdef WITH_NLS - -#include "resource.h" - -UITranslation::UITranslation() -{ - auto lang = Translation::getISO639LanguageName(); - printf("LANG: %s\n", lang.data()); - std::string res = ":locale/"; - res += lang + ".mo"; - - GUI::Resource mo(res); - if(!mo.valid()) - { - printf("Locale not in resources - use default\n"); - // Locale not in resources - use default - return; - } - printf("Using mo: %s\n", res.data()); - load(mo.data(), mo.size()); -} - -#endif // WITH_NLS diff --git a/plugingui/uitranslation.h b/plugingui/uitranslation.h deleted file mode 100644 index 5341255..0000000 --- a/plugingui/uitranslation.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * uitranslation.h - * - * Thu May 7 18:04:40 CEST 2020 - * Copyright 2020 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include - -#include - -#ifdef WITH_NLS -class UITranslation - : public Translation -{ -public: - UITranslation(); - ~UITranslation() = default; -}; -#endif diff --git a/plugingui/utf8.cc b/plugingui/utf8.cc deleted file mode 100644 index 747e726..0000000 --- a/plugingui/utf8.cc +++ /dev/null @@ -1,361 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * utf8.cc - * - * Tue Feb 27 19:18:23 CET 2007 - * Copyright 2006 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "utf8.h" - -UTF8::UTF8() -{ - // Encode Map - map_encode["\x80"] = "\xc2\x80"; - map_encode["\x81"] = "\xc2\x81"; - map_encode["\x82"] = "\xc2\x82"; - map_encode["\x83"] = "\xc2\x83"; - map_encode["\x84"] = "\xc2\x84"; - map_encode["\x85"] = "\xc2\x85"; - map_encode["\x86"] = "\xc2\x86"; - map_encode["\x87"] = "\xc2\x87"; - map_encode["\x88"] = "\xc2\x88"; - map_encode["\x89"] = "\xc2\x89"; - map_encode["\x8a"] = "\xc2\x8a"; - map_encode["\x8b"] = "\xc2\x8b"; - map_encode["\x8c"] = "\xc2\x8c"; - map_encode["\x8d"] = "\xc2\x8d"; - map_encode["\x8e"] = "\xc2\x8e"; - map_encode["\x8f"] = "\xc2\x8f"; - map_encode["\x90"] = "\xc2\x90"; - map_encode["\x91"] = "\xc2\x91"; - map_encode["\x92"] = "\xc2\x92"; - map_encode["\x93"] = "\xc2\x93"; - map_encode["\x94"] = "\xc2\x94"; - map_encode["\x95"] = "\xc2\x95"; - map_encode["\x96"] = "\xc2\x96"; - map_encode["\x97"] = "\xc2\x97"; - map_encode["\x98"] = "\xc2\x98"; - map_encode["\x99"] = "\xc2\x99"; - map_encode["\x9a"] = "\xc2\x9a"; - map_encode["\x9b"] = "\xc2\x9b"; - map_encode["\x9c"] = "\xc2\x9c"; - map_encode["\x9d"] = "\xc2\x9d"; - map_encode["\x9e"] = "\xc2\x9e"; - map_encode["\x9f"] = "\xc2\x9f"; - map_encode["\xa0"] = "\xc2\xa0"; - map_encode["\xa1"] = "\xc2\xa1"; - map_encode["\xa2"] = "\xc2\xa2"; - map_encode["\xa3"] = "\xc2\xa3"; - map_encode["\xa4"] = "\xc2\xa4"; - map_encode["\xa5"] = "\xc2\xa5"; - map_encode["\xa6"] = "\xc2\xa6"; - map_encode["\xa7"] = "\xc2\xa7"; - map_encode["\xa8"] = "\xc2\xa8"; - map_encode["\xa9"] = "\xc2\xa9"; - map_encode["\xaa"] = "\xc2\xaa"; - map_encode["\xab"] = "\xc2\xab"; - map_encode["\xac"] = "\xc2\xac"; - map_encode["\xad"] = "\xc2\xad"; - map_encode["\xae"] = "\xc2\xae"; - map_encode["\xaf"] = "\xc2\xaf"; - map_encode["\xb0"] = "\xc2\xb0"; - map_encode["\xb1"] = "\xc2\xb1"; - map_encode["\xb2"] = "\xc2\xb2"; - map_encode["\xb3"] = "\xc2\xb3"; - map_encode["\xb4"] = "\xc2\xb4"; - map_encode["\xb5"] = "\xc2\xb5"; - map_encode["\xb6"] = "\xc2\xb6"; - map_encode["\xb7"] = "\xc2\xb7"; - map_encode["\xb8"] = "\xc2\xb8"; - map_encode["\xb9"] = "\xc2\xb9"; - map_encode["\xba"] = "\xc2\xba"; - map_encode["\xbb"] = "\xc2\xbb"; - map_encode["\xbc"] = "\xc2\xbc"; - map_encode["\xbd"] = "\xc2\xbd"; - map_encode["\xbe"] = "\xc2\xbe"; - map_encode["\xbf"] = "\xc2\xbf"; - map_encode["\xc0"] = "\xc3\x80"; - map_encode["\xc1"] = "\xc3\x81"; - map_encode["\xc2"] = "\xc3\x82"; - map_encode["\xc3"] = "\xc3\x83"; - map_encode["\xc4"] = "\xc3\x84"; - map_encode["\xc5"] = "\xc3\x85"; - map_encode["\xc6"] = "\xc3\x86"; - map_encode["\xc7"] = "\xc3\x87"; - map_encode["\xc8"] = "\xc3\x88"; - map_encode["\xc9"] = "\xc3\x89"; - map_encode["\xca"] = "\xc3\x8a"; - map_encode["\xcb"] = "\xc3\x8b"; - map_encode["\xcc"] = "\xc3\x8c"; - map_encode["\xcd"] = "\xc3\x8d"; - map_encode["\xce"] = "\xc3\x8e"; - map_encode["\xcf"] = "\xc3\x8f"; - map_encode["\xd0"] = "\xc3\x90"; - map_encode["\xd1"] = "\xc3\x91"; - map_encode["\xd2"] = "\xc3\x92"; - map_encode["\xd3"] = "\xc3\x93"; - map_encode["\xd4"] = "\xc3\x94"; - map_encode["\xd5"] = "\xc3\x95"; - map_encode["\xd6"] = "\xc3\x96"; - map_encode["\xd7"] = "\xc3\x97"; - map_encode["\xd8"] = "\xc3\x98"; - map_encode["\xd9"] = "\xc3\x99"; - map_encode["\xda"] = "\xc3\x9a"; - map_encode["\xdb"] = "\xc3\x9b"; - map_encode["\xdc"] = "\xc3\x9c"; - map_encode["\xdd"] = "\xc3\x9d"; - map_encode["\xde"] = "\xc3\x9e"; - map_encode["\xdf"] = "\xc3\x9f"; - map_encode["\xe0"] = "\xc3\xa0"; - map_encode["\xe1"] = "\xc3\xa1"; - map_encode["\xe2"] = "\xc3\xa2"; - map_encode["\xe3"] = "\xc3\xa3"; - map_encode["\xe4"] = "\xc3\xa4"; - map_encode["\xe5"] = "\xc3\xa5"; - map_encode["\xe6"] = "\xc3\xa6"; - map_encode["\xe7"] = "\xc3\xa7"; - map_encode["\xe8"] = "\xc3\xa8"; - map_encode["\xe9"] = "\xc3\xa9"; - map_encode["\xea"] = "\xc3\xaa"; - map_encode["\xeb"] = "\xc3\xab"; - map_encode["\xec"] = "\xc3\xac"; - map_encode["\xed"] = "\xc3\xad"; - map_encode["\xee"] = "\xc3\xae"; - map_encode["\xef"] = "\xc3\xaf"; - map_encode["\xf0"] = "\xc3\xb0"; - map_encode["\xf1"] = "\xc3\xb1"; - map_encode["\xf2"] = "\xc3\xb2"; - map_encode["\xf3"] = "\xc3\xb3"; - map_encode["\xf4"] = "\xc3\xb4"; - map_encode["\xf5"] = "\xc3\xb5"; - map_encode["\xf6"] = "\xc3\xb6"; - map_encode["\xf7"] = "\xc3\xb7"; - map_encode["\xf8"] = "\xc3\xb8"; - map_encode["\xf9"] = "\xc3\xb9"; - map_encode["\xfa"] = "\xc3\xba"; - map_encode["\xfb"] = "\xc3\xbb"; - map_encode["\xfc"] = "\xc3\xbc"; - map_encode["\xfd"] = "\xc3\xbd"; - map_encode["\xfe"] = "\xc3\xbe"; - map_encode["\xff"] = "\xc3\xbf"; - - // Decode Map - map_decode["\xc2\x80"] = "\x80"; - map_decode["\xc2\x81"] = "\x81"; - map_decode["\xc2\x82"] = "\x82"; - map_decode["\xc2\x83"] = "\x83"; - map_decode["\xc2\x84"] = "\x84"; - map_decode["\xc2\x85"] = "\x85"; - map_decode["\xc2\x86"] = "\x86"; - map_decode["\xc2\x87"] = "\x87"; - map_decode["\xc2\x88"] = "\x88"; - map_decode["\xc2\x89"] = "\x89"; - map_decode["\xc2\x8a"] = "\x8a"; - map_decode["\xc2\x8b"] = "\x8b"; - map_decode["\xc2\x8c"] = "\x8c"; - map_decode["\xc2\x8d"] = "\x8d"; - map_decode["\xc2\x8e"] = "\x8e"; - map_decode["\xc2\x8f"] = "\x8f"; - map_decode["\xc2\x90"] = "\x90"; - map_decode["\xc2\x91"] = "\x91"; - map_decode["\xc2\x92"] = "\x92"; - map_decode["\xc2\x93"] = "\x93"; - map_decode["\xc2\x94"] = "\x94"; - map_decode["\xc2\x95"] = "\x95"; - map_decode["\xc2\x96"] = "\x96"; - map_decode["\xc2\x97"] = "\x97"; - map_decode["\xc2\x98"] = "\x98"; - map_decode["\xc2\x99"] = "\x99"; - map_decode["\xc2\x9a"] = "\x9a"; - map_decode["\xc2\x9b"] = "\x9b"; - map_decode["\xc2\x9c"] = "\x9c"; - map_decode["\xc2\x9d"] = "\x9d"; - map_decode["\xc2\x9e"] = "\x9e"; - map_decode["\xc2\x9f"] = "\x9f"; - map_decode["\xc2\xa0"] = "\xa0"; - map_decode["\xc2\xa1"] = "\xa1"; - map_decode["\xc2\xa2"] = "\xa2"; - map_decode["\xc2\xa3"] = "\xa3"; - map_decode["\xc2\xa4"] = "\xa4"; - map_decode["\xc2\xa5"] = "\xa5"; - map_decode["\xc2\xa6"] = "\xa6"; - map_decode["\xc2\xa7"] = "\xa7"; - map_decode["\xc2\xa8"] = "\xa8"; - map_decode["\xc2\xa9"] = "\xa9"; - map_decode["\xc2\xaa"] = "\xaa"; - map_decode["\xc2\xab"] = "\xab"; - map_decode["\xc2\xac"] = "\xac"; - map_decode["\xc2\xad"] = "\xad"; - map_decode["\xc2\xae"] = "\xae"; - map_decode["\xc2\xaf"] = "\xaf"; - map_decode["\xc2\xb0"] = "\xb0"; - map_decode["\xc2\xb1"] = "\xb1"; - map_decode["\xc2\xb2"] = "\xb2"; - map_decode["\xc2\xb3"] = "\xb3"; - map_decode["\xc2\xb4"] = "\xb4"; - map_decode["\xc2\xb5"] = "\xb5"; - map_decode["\xc2\xb6"] = "\xb6"; - map_decode["\xc2\xb7"] = "\xb7"; - map_decode["\xc2\xb8"] = "\xb8"; - map_decode["\xc2\xb9"] = "\xb9"; - map_decode["\xc2\xba"] = "\xba"; - map_decode["\xc2\xbb"] = "\xbb"; - map_decode["\xc2\xbc"] = "\xbc"; - map_decode["\xc2\xbd"] = "\xbd"; - map_decode["\xc2\xbe"] = "\xbe"; - map_decode["\xc2\xbf"] = "\xbf"; - map_decode["\xc3\x80"] = "\xc0"; - map_decode["\xc3\x81"] = "\xc1"; - map_decode["\xc3\x82"] = "\xc2"; - map_decode["\xc3\x83"] = "\xc3"; - map_decode["\xc3\x84"] = "\xc4"; - map_decode["\xc3\x85"] = "\xc5"; - map_decode["\xc3\x86"] = "\xc6"; - map_decode["\xc3\x87"] = "\xc7"; - map_decode["\xc3\x88"] = "\xc8"; - map_decode["\xc3\x89"] = "\xc9"; - map_decode["\xc3\x8a"] = "\xca"; - map_decode["\xc3\x8b"] = "\xcb"; - map_decode["\xc3\x8c"] = "\xcc"; - map_decode["\xc3\x8d"] = "\xcd"; - map_decode["\xc3\x8e"] = "\xce"; - map_decode["\xc3\x8f"] = "\xcf"; - map_decode["\xc3\x90"] = "\xd0"; - map_decode["\xc3\x91"] = "\xd1"; - map_decode["\xc3\x92"] = "\xd2"; - map_decode["\xc3\x93"] = "\xd3"; - map_decode["\xc3\x94"] = "\xd4"; - map_decode["\xc3\x95"] = "\xd5"; - map_decode["\xc3\x96"] = "\xd6"; - map_decode["\xc3\x97"] = "\xd7"; - map_decode["\xc3\x98"] = "\xd8"; - map_decode["\xc3\x99"] = "\xd9"; - map_decode["\xc3\x9a"] = "\xda"; - map_decode["\xc3\x9b"] = "\xdb"; - map_decode["\xc3\x9c"] = "\xdc"; - map_decode["\xc3\x9d"] = "\xdd"; - map_decode["\xc3\x9e"] = "\xde"; - map_decode["\xc3\x9f"] = "\xdf"; - map_decode["\xc3\xa0"] = "\xe0"; - map_decode["\xc3\xa1"] = "\xe1"; - map_decode["\xc3\xa2"] = "\xe2"; - map_decode["\xc3\xa3"] = "\xe3"; - map_decode["\xc3\xa4"] = "\xe4"; - map_decode["\xc3\xa5"] = "\xe5"; - map_decode["\xc3\xa6"] = "\xe6"; - map_decode["\xc3\xa7"] = "\xe7"; - map_decode["\xc3\xa8"] = "\xe8"; - map_decode["\xc3\xa9"] = "\xe9"; - map_decode["\xc3\xaa"] = "\xea"; - map_decode["\xc3\xab"] = "\xeb"; - map_decode["\xc3\xac"] = "\xec"; - map_decode["\xc3\xad"] = "\xed"; - map_decode["\xc3\xae"] = "\xee"; - map_decode["\xc3\xaf"] = "\xef"; - map_decode["\xc3\xb0"] = "\xf0"; - map_decode["\xc3\xb1"] = "\xf1"; - map_decode["\xc3\xb2"] = "\xf2"; - map_decode["\xc3\xb3"] = "\xf3"; - map_decode["\xc3\xb4"] = "\xf4"; - map_decode["\xc3\xb5"] = "\xf5"; - map_decode["\xc3\xb6"] = "\xf6"; - map_decode["\xc3\xb7"] = "\xf7"; - map_decode["\xc3\xb8"] = "\xf8"; - map_decode["\xc3\xb9"] = "\xf9"; - map_decode["\xc3\xba"] = "\xfa"; - map_decode["\xc3\xbb"] = "\xfb"; - map_decode["\xc3\xbc"] = "\xfc"; - map_decode["\xc3\xbd"] = "\xfd"; - map_decode["\xc3\xbe"] = "\xfe"; - map_decode["\xc3\xbf"] = "\xff"; - // FIXME: This is just a hack to make Goran Mekic's name work. - map_decode["\xc4\x87"] = "c"; -} - -std::string UTF8::fromLatin1(std::string const& s) -{ - std::string ret; - - for(int i = 0; i < (int)s.length(); i++) - { - std::string c; - - if((unsigned char)s[i] <= 0x7F) - { - c = s.substr(i, 1); - } - else - { - c = map_encode[s.substr(i, 1)]; - } - - // If c == "", the character wasn't found in the map. - // Ignore this case for now and just push an empty string in this case. - - ret.append(c); - } - - return ret; -} - -std::string UTF8::toLatin1(std::string const& s) -{ - std::string ret; - - int width = 1; - for(int i = 0; i < (int)s.length(); i += width) - { - if(/*(unsigned char)s[i]>=0x00&&*/ (unsigned char)s[i] <= 0x7F) - { - width = 1; // 00-7F -> 1 byte - } - if((unsigned char)s[i] >= 0xC2 && (unsigned char)s[i] <= 0xDF) - { - width = 2; // C2-DF -> 2 bytes - } - if((unsigned char)s[i] >= 0xE0 && (unsigned char)s[i] <= 0xEF) - { - width = 3; // E0-EF -> 3 bytes - } - if((unsigned char)s[i] >= 0xF0 && (unsigned char)s[i] <= 0xF4) - { - width = 4; // F0-F4 -> 4 bytes - } - - std::string c; - if(width == 1) - { - c = s.substr(i, 1); - } - else - { - c = map_decode[s.substr(i, width)]; - } - - // If c == "", the character wasn't found in the map. - // Ignore this case for now and just push an empty string in this case. - - ret.append(c); - } - - return ret; -} diff --git a/plugingui/utf8.h b/plugingui/utf8.h deleted file mode 100644 index 04c26b1..0000000 --- a/plugingui/utf8.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * utf8.h - * - * Tue Feb 27 19:18:23 CET 2007 - * Copyright 2006 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include - -// Class to convert utf8 to latin1 and the other way around. -class UTF8 -{ -public: - UTF8(); - - // Encode a string from latin1 to UTF-8. - std::string fromLatin1(std::string const& s); - - // Decode a string from UTF-8 to latin1. - std::string toLatin1(std::string const& s); - -private: - std::unordered_map map_encode; - std::unordered_map map_decode; -}; diff --git a/plugingui/verticalline.cc b/plugingui/verticalline.cc deleted file mode 100644 index 6a3a98a..0000000 --- a/plugingui/verticalline.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * verticalline.cc - * - * Sat Apr 6 12:59:44 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "verticalline.h" - -#include "painter.h" - -namespace GUI { - -VerticalLine::VerticalLine(Widget *parent) - : Widget(parent) - , vline(":resources/vertline.png") -{ -} - -void VerticalLine::repaintEvent(RepaintEvent* repaintEvent) -{ - if(height() < 2) - { - return; - } - - Painter p(*this); - p.drawImageStretched(0, (height() - vline.height()) / 2, - vline, width(), vline.height()); -} - -} // GUI:: diff --git a/plugingui/verticalline.h b/plugingui/verticalline.h deleted file mode 100644 index 3403244..0000000 --- a/plugingui/verticalline.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * verticalline.h - * - * Sat Apr 6 12:59:43 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "widget.h" -#include "image.h" - -namespace GUI { - -class VerticalLine : public Widget { -public: - VerticalLine(Widget* parent); - virtual ~VerticalLine() = default; - -protected: - // From Widget: - virtual void repaintEvent(RepaintEvent* repaintEvent) override; - -private: - Image vline; -}; - -} // GUI:: diff --git a/plugingui/visualizerframecontent.cc b/plugingui/visualizerframecontent.cc index 7e5b298..d6ea2c2 100644 --- a/plugingui/visualizerframecontent.cc +++ b/plugingui/visualizerframecontent.cc @@ -29,7 +29,7 @@ #include #include -#include "painter.h" +#include namespace GUI { diff --git a/plugingui/visualizerframecontent.h b/plugingui/visualizerframecontent.h index edf8f35..3012762 100644 --- a/plugingui/visualizerframecontent.h +++ b/plugingui/visualizerframecontent.h @@ -25,8 +25,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #pragma once -#include "layout.h" -#include "widget.h" + +#include +#include + #include "humaniservisualiser.h" #include diff --git a/plugingui/voicelimitframecontent.h b/plugingui/voicelimitframecontent.h index 8b08014..0fbc306 100644 --- a/plugingui/voicelimitframecontent.h +++ b/plugingui/voicelimitframecontent.h @@ -28,10 +28,11 @@ #include -#include "label.h" -#include "knob.h" +#include +#include +#include + #include "labeledcontrol.h" -#include "widget.h" struct Settings; class SettingsNotifier; diff --git a/plugingui/widget.cc b/plugingui/widget.cc deleted file mode 100644 index da6b1e2..0000000 --- a/plugingui/widget.cc +++ /dev/null @@ -1,297 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * widget.cc - * - * Sun Oct 9 13:01:44 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "widget.h" - -#include - -#include "painter.h" -#include "window.h" - -namespace GUI -{ - -Widget::Widget(Widget* parent) - : parent(parent) -{ - if(parent) - { - parent->addChild(this); - _window = parent->window(); - } - - pixbuf.x = translateToWindowX(); - pixbuf.y = translateToWindowY(); -} - -Widget::~Widget() -{ - if(parent) - { - parent->removeChild(this); - } -} - -void Widget::show() -{ - setVisible(true); -} - -void Widget::hide() -{ - setVisible(false); -} - -void Widget::setVisible(bool visible) -{ - _visible = visible; - pixbuf.visible = visible; - redraw(); -} - -bool Widget::visible() const -{ - return _visible; -} - -void Widget::redraw() -{ - dirty = true; - window()->needsRedraw(); -} - -void Widget::addChild(Widget* widget) -{ - children.push_back(widget); -} - -void Widget::removeChild(Widget* widget) -{ - for(auto i = children.begin(); i != children.end(); ++i) - { - if(*i == widget) - { - children.erase(i); - return; - } - } -} - -void Widget::reparent(Widget* parent) -{ - if(parent == this->parent) - { - return; // Already at the right parent. - } - - if(this->parent) - { - this->parent->removeChild(this); - } - - if(parent) - { - parent->addChild(this); - } - - this->parent = parent; -} - -void Widget::resize(std::size_t width, std::size_t height) -{ - assert(width < 32000 && height < 32000); // Catch negative values as size_t - if((width < 1) || (height < 1) || - ((width == _width) && (height == _height))) - { - return; - } - - _width = width; - _height = height; - - // Store old size/position in pixelbuffer for rendering invalidation. - if(!pixbuf.has_last) - { - pixbuf.last_width = pixbuf.width; - pixbuf.last_height = pixbuf.height; - pixbuf.last_x = pixbuf.x; - pixbuf.last_y = pixbuf.y; - pixbuf.has_last = true; - } - - pixbuf.realloc(width, height); - pixbuf.x = translateToWindowX(); - pixbuf.y = translateToWindowY(); - redraw(); - sizeChangeNotifier(width, height); -} - -void Widget::move(int x, int y) -{ - if((_x == x) && - (_y == y)) - { - return; - } - - _x = x; - _y = y; - - // Store old size/position in pixelbuffer for rendering invalidation. - if(!pixbuf.has_last) - { - pixbuf.last_width = pixbuf.width; - pixbuf.last_height = pixbuf.height; - pixbuf.last_x = pixbuf.x; - pixbuf.last_y = pixbuf.y; - pixbuf.has_last = true; - } - - //pixbuf.x = translateToWindowX(); - //pixbuf.y = translateToWindowY(); - - positionChangeNotifier(x, y); -} - -int Widget::x() const -{ - return _x; -} - -int Widget::y() const -{ - return _y; -} - -std::size_t Widget::width() const -{ - return _width; -} - -std::size_t Widget::height() const -{ - return _height; -} - -Point Widget::position() const -{ - return { _x, _y }; -} - -PixelBufferAlpha& Widget::getPixelBuffer() -{ - return pixbuf; -} - -ImageCache& Widget::getImageCache() -{ - assert(parent); - return parent->getImageCache(); -} - -Widget* Widget::find(int x, int y) -{ - for(auto i = children.rbegin(); i != children.rend(); ++i) - { - Widget* widget = *i; - if(widget->visible()) - { - if((x >= widget->x()) && (x < (widget->x() + (int)widget->width())) && - (y >= widget->y()) && (y < (widget->y() + (int)widget->height()))) - { - return widget->find(x - widget->x(), y - widget->y()); - } - } - } - - return this; -} - -Window* Widget::window() -{ - return _window; -} - -std::vector Widget::getPixelBuffers() -{ - std::vector pixelBuffers; - - pixbuf.x = translateToWindowX(); - pixbuf.y = translateToWindowY(); - - if(dirty) - { - repaintEvent(nullptr); - pixbuf.dirty = true; - dirty = false; - } - - if(pixbuf.dirty || visible()) - { - pixelBuffers.push_back(&pixbuf); - } - - if(visible()) - { - for(auto child : children) - { - auto childPixelBuffers = child->getPixelBuffers(); - pixelBuffers.insert(pixelBuffers.end(), - childPixelBuffers.begin(), childPixelBuffers.end()); - } - } - - return pixelBuffers; -} - -bool Widget::hasKeyboardFocus() -{ - return window()->keyboardFocus() == this; -} - -std::size_t Widget::translateToWindowX() -{ - size_t window_x = x(); - if(parent) - { - window_x += parent->translateToWindowX(); - } - - return window_x; -} - -std::size_t Widget::translateToWindowY() -{ - size_t window_y = y(); - if(parent) - { - window_y += parent->translateToWindowY(); - } - - return window_y; -} - -} // GUI:: diff --git a/plugingui/widget.h b/plugingui/widget.h deleted file mode 100644 index b9436b7..0000000 --- a/plugingui/widget.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * widget.h - * - * Sun Oct 9 13:01:44 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "guievent.h" -#include "pixelbuffer.h" -#include "notifier.h" -#include "layout.h" -#include "canvas.h" - -#include - -namespace GUI -{ - -struct Point -{ - int x; - int y; -}; - -struct Size -{ - std::size_t width; - std::size_t height; -}; - -class ImageCache; -class Window; - -class Widget - : public Listener - , public LayoutItem - , public Canvas -{ - friend class Painter; -public: - Widget(Widget* parent); - virtual ~Widget(); - - virtual void show(); - virtual void hide(); - void setVisible(bool visible); - virtual bool visible() const; - - //! Mark widget dirty and shedule redraw on next window redraw. - void redraw(); - - // From LayoutItem - virtual void resize(std::size_t width, std::size_t height) override; - virtual void move(int x, int y) override; - virtual int x() const override; - virtual int y() const override; - virtual std::size_t width() const override; - virtual std::size_t height() const override; - - Point position() const; - - // From Canvas - PixelBufferAlpha& getPixelBuffer() override; - - virtual bool isFocusable() { return false; } - virtual bool catchMouse() { return false; } - - void addChild(Widget* widget); - void removeChild(Widget* widget); - void reparent(Widget* parent); - - virtual void repaintEvent(RepaintEvent* repaintEvent) {} - virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) {} - virtual void buttonEvent(ButtonEvent* buttonEvent) {} - virtual void scrollEvent(ScrollEvent* scrollEvent) {} - virtual void keyEvent(KeyEvent* keyEvent) {} - virtual void mouseLeaveEvent() {} - virtual void mouseEnterEvent() {} - - virtual ImageCache& getImageCache(); - - Widget* find(int x, int y); - - virtual Window* window(); - - std::vector getPixelBuffers(); - - bool hasKeyboardFocus(); - - Notifier sizeChangeNotifier; // (width, height) - Notifier positionChangeNotifier; // (x, y) - - //! Translate x-coordinate from parent-space to window-space. - virtual std::size_t translateToWindowX(); - - //! Translate y-coordinate from parent-space to window-space. - virtual std::size_t translateToWindowY(); - -protected: - friend class EventHandler; - PixelBufferAlpha pixbuf{0,0}; - - std::vector children; - - Widget* parent = nullptr; - Window* _window = nullptr; - - int _x{0}; - int _y{0}; - std::size_t _width{0}; - std::size_t _height{0}; - - bool _visible{true}; - - bool dirty{true}; -}; - -} // GUI:: diff --git a/plugingui/window.cc b/plugingui/window.cc deleted file mode 100644 index 5e0ad31..0000000 --- a/plugingui/window.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * window.cc - * - * Sun Oct 9 13:11:53 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "window.h" - -#include - -#include "painter.h" - -#ifndef UI_PUGL -#ifdef UI_X11 -#include "nativewindow_x11.h" -#endif // UI_X11 -#ifdef UI_WIN32 -#include "nativewindow_win32.h" -#endif // UI_WIN32 -#ifdef UI_COCOA -#include "nativewindow_cocoa.h" -#endif // UI_COCOA -#else -#include "nativewindow_pugl.h" -#endif // !UI_PUGL - -namespace GUI -{ - -Window::Window(void* native_window) - : Widget(nullptr) - , wpixbuf(1, 1) -{ - // Make sure we have a valid size when initialising the NativeWindow - _width = wpixbuf.width; - _height = wpixbuf.height; - -#ifndef UI_PUGL -#ifdef UI_X11 - native = new NativeWindowX11(native_window, *this); -#endif // UI_X11 -#ifdef UI_WIN32 - native = new NativeWindowWin32(native_window, *this); -#endif // UI_WIN32 -#ifdef UI_COCOA - native = new NativeWindowCocoa(native_window, *this); -#endif // UI_COCOA -#else - // Use pugl - native = new NativeWindowPugl(native_window, *this); -#endif // !UI_PUGL - - eventhandler = new EventHandler(*native, *this); - - setVisible(true); // The root widget is always visible. -} - -Window::~Window() -{ - delete native; - delete eventhandler; -} - -void Window::setFixedSize(int w, int h) -{ - native->setFixedSize(w, h); -} - -void Window::setAlwaysOnTop(bool always_on_top) -{ - native->setAlwaysOnTop(always_on_top); -} - -void Window::setCaption(const std::string& caption) -{ - native->setCaption(caption); -} - -//! This overload the resize method on Widget and simply requests a window resize -//! on the windowmanager/OS. The resized() method is called by the event handler -//! once the window has been resized. -void Window::resize(std::size_t width, std::size_t height) -{ - native->resize(width, height); -} - -//! This overload the move method on Widget and simply requests a window move -//! on the windowmanager/OS. The moved() method is called by the event handler -//! once the window has been moved. -void Window::move(int x, int y) -{ - native->move(x, y); -} - -void Window::show() -{ - Widget::show(); - redraw(); - native->show(); -} - -void Window::hide() -{ - native->hide(); - Widget::hide(); -} - -Window* Window::window() -{ - return this; -} - -Size Window::getNativeSize() -{ - auto sz = native->getSize(); - return {sz.first, sz.second}; -} - -ImageCache& Window::getImageCache() -{ - return image_cache; -} - -EventHandler* Window::eventHandler() -{ - return eventhandler; -} - -Widget* Window::keyboardFocus() -{ - return _keyboardFocus; -} - -void Window::setKeyboardFocus(Widget* widget) -{ - auto oldFocusWidget = _keyboardFocus; - _keyboardFocus = widget; - - if(oldFocusWidget) - { - oldFocusWidget->redraw(); - } - - if(_keyboardFocus) - { - _keyboardFocus->redraw(); - } -} - -Widget* Window::buttonDownFocus() -{ - return _buttonDownFocus; -} - -void Window::setButtonDownFocus(Widget* widget) -{ - _buttonDownFocus = widget; - native->grabMouse(widget != nullptr); -} - -Widget* Window::mouseFocus() -{ - return _mouseFocus; -} - -void Window::setMouseFocus(Widget* widget) -{ - _mouseFocus = widget; - -} - -void Window::needsRedraw() -{ - needs_redraw = true; -} - -void* Window::getNativeWindowHandle() const -{ - return native->getNativeWindowHandle(); -} - -Point Window::translateToScreen(const Point& point) -{ - return native->translateToScreen(point); -} - -std::size_t Window::translateToWindowX() -{ - return 0; -} - -std::size_t Window::translateToWindowY() -{ - return 0; -} - -//! Called by event handler when an windowmanager/OS window resize event has -//! been received. Do not call this directly. -void Window::resized(std::size_t width, std::size_t height) -{ - auto size = native->getSize(); - if((wpixbuf.width != size.first) || - (wpixbuf.height != size.second)) - { - wpixbuf.realloc(size.first, size.second); - Widget::resize(size.first, size.second); - } - - updateBuffer(); -} - -//! Called by event handler when an windowmanager/OS window move event has -//! been received. Do not call this directly. -void Window::moved(int x, int y) -{ - // Make sure widget coordinates are updated. - Widget::move(x, y); -} - -bool Window::updateBuffer() -{ - if(!native) - { - return false; - } - - if(!needs_redraw) - { - // Nothing changed, don't update anything. - return false; - } - - auto pixel_buffers = getPixelBuffers(); - - auto dirty_rect = wpixbuf.updateBuffer(pixel_buffers); - - if(!dirty_rect.empty()) - { - native->redraw(dirty_rect); - } - needs_redraw = false; - - return true; -} - -} // GUI:: diff --git a/plugingui/window.h b/plugingui/window.h deleted file mode 100644 index 6031500..0000000 --- a/plugingui/window.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * window.h - * - * Sun Oct 9 13:11:52 CEST 2011 - * Copyright 2011 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo 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. - * - * DrumGizmo 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 DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include "widget.h" - -#include "pixelbuffer.h" -#include "nativewindow.h" -#include "image.h" -#include "eventhandler.h" -#include "imagecache.h" - -namespace GUI -{ - -class Window - : public Widget -{ -public: - Window(void* native_window = nullptr); - ~Window(); - - void setFixedSize(int width, int height); - void setAlwaysOnTop(bool always_on_top); - void setCaption(const std::string& caption); - - // From Widget: - void resize(std::size_t width, std::size_t height) override; - void move(int x, int y) override; - void show() override; - void hide() override; - Window* window() override; - Size getNativeSize(); - ImageCache& getImageCache() override; - - EventHandler* eventHandler(); - - Widget* keyboardFocus(); - void setKeyboardFocus(Widget* widget); - - Widget* buttonDownFocus(); - void setButtonDownFocus(Widget* widget); - - Widget* mouseFocus(); - void setMouseFocus(Widget* widget); - - //! Tag the window buffer dirty to be rendered. - void needsRedraw(); - - // \returns the native window handle, it HWND on Win32 or Window id on X11 - void* getNativeWindowHandle() const; - - //! Translate a local window coordinate to a global screen coordinate. - Point translateToScreen(const Point& point); - -protected: - // For the EventHandler - friend class EventHandler; - - // From Widget: - std::size_t translateToWindowX() override; - std::size_t translateToWindowY() override; - void resized(std::size_t width, std::size_t height); - void moved(int x, int y); - - //! Returns true if window pixel buffer changed and needs to be copied to - //! native window. - bool updateBuffer(); - - // For the Painter - friend class Widget; - - // For the NativeWindow implementations: - friend class NativeWindowX11; - friend class NativeWindowWin32; - friend class NativeWindowPugl; - friend class NativeWindowCocoa; - PixelBuffer wpixbuf; - - size_t refcount{0}; - - Widget* _keyboardFocus{nullptr}; - Widget* _buttonDownFocus{nullptr}; - Widget* _mouseFocus{nullptr}; - - NativeWindow* native{nullptr}; - EventHandler* eventhandler{nullptr}; - - size_t maxRefcount{0}; - - bool needs_redraw{false}; - ImageCache image_cache; -}; - -} // GUI:: diff --git a/test/Makefile.am b/test/Makefile.am index c2c151d..add962a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -25,26 +25,31 @@ TESTS += lv2 endif check_PROGRAMS = $(TESTS) -resource_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"resource\" $(SNDFILE_CFLAGS) \ +resource_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"resource\" \ + $(SNDFILE_CFLAGS) \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/hugin resource_LDFLAGS = $(SNDFILE_LIBS) nodist_resource_SOURCES = \ $(top_builddir)/plugingui/resource_data.cc resource_SOURCES = \ - $(top_srcdir)/plugingui/resource.cc \ + $(top_srcdir)/dggui/resource.cc \ $(top_srcdir)/hugin/hugin.c \ $(top_srcdir)/src/random.cc \ uunit/uunit.cc \ drumkit_creator.cc \ resource_test.cc -audiocache_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocache\" \ +audiocache_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocache\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) + -I$(top_srcdir)/hugin -DDISABLE_HUGIN \ + $(PTHREAD_CFLAGS) \ + $(SNDFILE_CFLAGS) audiocache_LDFLAGS = $(PTHREAD_LIBS) $(SNDFILE_LIBS) audiocache_SOURCES = \ $(top_srcdir)/src/audiocache.cc \ @@ -59,10 +64,13 @@ audiocache_SOURCES = \ drumkit_creator.cc \ audiocachetest.cc -audiocachefile_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocachefile\" \ +audiocachefile_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocachefile\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) + -I$(top_srcdir)/hugin -DDISABLE_HUGIN \ + $(PTHREAD_CFLAGS) \ + $(SNDFILE_CFLAGS) audiocachefile_LDFLAGS = $(PTHREAD_LIBS) $(SNDFILE_LIBS) audiocachefile_SOURCES = \ $(top_srcdir)/src/audiocachefile.cc \ @@ -74,20 +82,25 @@ audiocachefile_SOURCES = \ drumkit_creator.cc \ audiocachefiletest.cc -audiocacheidmanager_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocacheidmanager\" \ +audiocacheidmanager_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocacheidmanager\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/hugin -DDISABLE_HUGIN $(SNDFILE_CFLAGS) + -I$(top_srcdir)/hugin -DDISABLE_HUGIN \ + $(SNDFILE_CFLAGS) audiocacheidmanager_LDFLAGS = $(SNDFILE_LIBS) audiocacheidmanager_SOURCES = \ $(top_srcdir)/src/audiocacheidmanager.cc \ uunit/uunit.cc \ audiocacheidmanagertest.cc -audiocacheeventhandler_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocacheeventhandler\" \ +audiocacheeventhandler_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"audiocacheeventhandler\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) + -I$(top_srcdir)/hugin -DDISABLE_HUGIN \ + $(PTHREAD_CFLAGS) \ + $(SNDFILE_CFLAGS) audiocacheeventhandler_LDFLAGS = $(PTHREAD_LIBS) $(SNDFILE_LIBS) audiocacheeventhandler_SOURCES = \ $(top_srcdir)/src/audiocacheeventhandler.cc \ @@ -98,10 +111,12 @@ audiocacheeventhandler_SOURCES = \ uunit/uunit.cc \ audiocacheeventhandlertest.cc -enginetest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"enginetest\" \ +enginetest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"enginetest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/hugin $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) + -I$(top_srcdir)/hugin $(PTHREAD_CFLAGS) \ + $(SNDFILE_CFLAGS) enginetest_LDFLAGS = $(PTHREAD_LIBS) $(SNDFILE_LIBS) \ $(top_builddir)/src/libdg.la enginetest_SOURCES = \ @@ -110,20 +125,26 @@ enginetest_SOURCES = \ drumkit_creator.cc \ enginetest.cc -paintertest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"paintertest\" \ +paintertest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"paintertest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/plugingui \ - -I$(top_srcdir)/hugin $(PTHREAD_CFLAGS) -paintertest_LDFLAGS = $(top_builddir)/plugingui/libdggui.la + -I$(top_srcdir)/src \ + -I$(top_srcdir)/ \ + -I$(top_srcdir)/hugin \ + $(PTHREAD_CFLAGS) +paintertest_LDFLAGS = \ + $(top_builddir)/dggui/libdggui.la paintertest_SOURCES = \ $(top_srcdir)/hugin/hugin.c \ uunit/uunit.cc \ - paintertest.cc + paintertest.cc \ + $(top_builddir)/plugingui/resource_data.cc -lv2_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"lv2\" \ +lv2_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"lv2\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - `pkg-config --cflags serd-0` `pkg-config --cflags lilv-0` \ + `pkg-config --cflags serd-0` `pkg-config --cflags lilv-0` \ -DLV2_PATH=\"@LV2DIR@\" $(SNDFILE_CFLAGS) lv2_LDFLAGS = `pkg-config --libs serd-0` \ `pkg-config --libs lilv-0` -lcrypto \ @@ -135,9 +156,11 @@ lv2_SOURCES = \ lv2_test_host.cc \ lv2.cc -configfile_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"configfile\" \ +configfile_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"configfile\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/hugin -I$(top_srcdir)/src + -I$(top_srcdir)/hugin \ + -I$(top_srcdir)/src configfile_LDFLAGS = configfile_SOURCES = \ $(top_srcdir)/src/configfile.cc \ @@ -146,7 +169,8 @@ configfile_SOURCES = \ uunit/uunit.cc \ configtest.cc -randomtest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"randomtest\" \ +randomtest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"randomtest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin -DDISABLE_HUGIN @@ -157,30 +181,42 @@ randomtest_SOURCES = \ uunit/uunit.cc \ randomtest.cc -atomictest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"atomictest\" \ +atomictest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"atomictest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/hugin + -I$(top_srcdir)/src \ + -I$(top_srcdir)/hugin atomictest_LDFLAGS = atomictest_SOURCES = atomictest.cc uunit/uunit.cc -syncedsettingstest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"syncedsettingstest\" \ +syncedsettingstest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"syncedsettingstest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/hugin + -I$(top_srcdir)/src \ + -I$(top_srcdir)/hugin syncedsettingstest_LDFLAGS = syncedsettingstest_SOURCES = syncedsettings.cc uunit/uunit.cc -imagecachetest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"imagecachetest\" \ +imagecachetest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"imagecachetest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/plugingui -I$(top_srcdir)/hugin -imagecachetest_LDFLAGS = $(top_builddir)/plugingui/libdggui.la + -I$(top_srcdir)/src \ + -I$(top_srcdir)/ \ + -I$(top_srcdir)/hugin +imagecachetest_LDFLAGS = \ + $(top_builddir)/dggui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la imagecachetest_SOURCES = \ $(top_srcdir)/hugin/hugin.c \ imagecachetest.cc \ uunit/uunit.cc -semaphoretest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"semaphoretest\" \ +semaphoretest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"semaphoretest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/hugin $(PTHREAD_CFLAGS) + -I$(top_srcdir)/src \ + -I$(top_srcdir)/hugin \ + $(PTHREAD_CFLAGS) semaphoretest_LDFLAGS = $(PTHREAD_LIBS) semaphoretest_SOURCES = \ $(top_srcdir)/hugin/hugin.c \ @@ -188,10 +224,12 @@ semaphoretest_SOURCES = \ semaphoretest.cc \ uunit/uunit.cc -drumkitcreatortest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"drumkitcreatortest\" \ +drumkitcreatortest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"drumkitcreatortest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src \ - -I$(top_srcdir)/hugin -DDISABLE_HUGIN $(SNDFILE_CFLAGS) + -I$(top_srcdir)/hugin -DDISABLE_HUGIN \ + $(SNDFILE_CFLAGS) drumkitcreatortest_CFLAGS = -DDISABLE_HUGIN drumkitcreatortest_LDFLAGS = $(SNDFILE_LIBS) drumkitcreatortest_SOURCES = \ @@ -200,7 +238,8 @@ drumkitcreatortest_SOURCES = \ drumkit_creator.cc \ drumkitcreatortest.cc -bytesizeparsertest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"bytesizeparsertest\" \ +bytesizeparsertest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"bytesizeparsertest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src bytesizeparsertest_LDFLAGS = @@ -209,7 +248,8 @@ bytesizeparsertest_SOURCES = \ bytesizeparsertest.cc \ uunit/uunit.cc -notifiertest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"notifiertest\" \ +notifiertest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"notifiertest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src notifiertest_LDFLAGS = @@ -217,9 +257,11 @@ notifiertest_SOURCES = \ notifiertest.cc \ uunit/uunit.cc -dgxmlparsertest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"dgxmlparsertest\" \ +dgxmlparsertest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"dgxmlparsertest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/hugin \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/hugin \ -I$(top_srcdir)/pugixml/src dgxmlparsertest_LDFLAGS = dgxmlparsertest_SOURCES = \ @@ -230,7 +272,8 @@ dgxmlparsertest_SOURCES = \ scopedfile.cc \ uunit/uunit.cc -domloadertest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"domloadertest\" \ +domloadertest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"domloadertest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src domloadertest_LDFLAGS = \ @@ -241,9 +284,11 @@ domloadertest_SOURCES = \ scopedfile.cc \ uunit/uunit.cc -configparsertest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"configparsertest\" \ +configparsertest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"configparsertest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/hugin \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/hugin \ -I$(top_srcdir)/pugixml/src configparsertest_LDFLAGS = configparsertest_SOURCES = \ @@ -253,9 +298,11 @@ configparsertest_SOURCES = \ configparsertest.cc \ uunit/uunit.cc -midimapparsertest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"midimapparsertest\" \ +midimapparsertest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"midimapparsertest\" \ $(DEBUG_FLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/hugin \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/hugin \ -I$(top_srcdir)/pugixml/src midimapparsertest_LDFLAGS = midimapparsertest_SOURCES = \ @@ -266,7 +313,8 @@ midimapparsertest_SOURCES = \ midimapparsertest.cc \ uunit/uunit.cc -eventsdstest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"eventsdstest\" \ +eventsdstest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"eventsdstest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src eventsdstest_LDFLAGS = @@ -275,7 +323,8 @@ eventsdstest_SOURCES = \ eventsdstest.cc \ uunit/uunit.cc -powermaptest_CXXFLAGS = -I$(top_srcdir)/test/uunit -DOUTPUT=\"powermaptest\" \ +powermaptest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"powermaptest\" \ $(DEBUG_FLAGS) \ -I$(top_srcdir)/src powermaptest_LDFLAGS = @@ -291,12 +340,12 @@ rcgen_verbose = $(rcgen_verbose_@AM_V@) rcgen_verbose_ = $(rcgen_verbose_@AM_DEFAULT_V@) rcgen_verbose_0 = @echo " RCGEN "$@; -translationtest_resource_data.cc: $(top_builddir)/plugingui/rcgen $(RES) - $(rcgen_verbose)$(top_builddir)/plugingui/rcgen$(EXEEXT) -s $(top_srcdir)/test/ -o $@ $(RES) +translationtest_resource_data.cc: $(top_builddir)/dggui/rcgen $(RES) + $(rcgen_verbose)$(top_builddir)/dggui/rcgen$(EXEEXT) -s $(top_srcdir)/test/ -o $@ $(RES) -translationtest_CXXFLAGS = -I$(top_srcdir)/test/uunit \ - -DOUTPUT=\"translationtest\" \ - -I$(top_srcdir)/plugingui \ +translationtest_CXXFLAGS = \ + -I$(top_srcdir)/test/uunit -DOUTPUT=\"translationtest\" \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin \ -DMO_SRC=\"$(top_srcdir)/test/locale/da.mo\" \ @@ -306,9 +355,9 @@ nodist_translationtest_SOURCES = \ $(top_builddir)/test/translationtest_resource_data.cc translationtest_SOURCES = \ $(top_srcdir)/hugin/hugin.c \ - $(top_srcdir)/plugingui/resource.cc \ + $(top_srcdir)/dggui/resource.cc \ $(top_srcdir)/src/translation.cc \ - $(top_srcdir)/plugingui/uitranslation.cc \ + $(top_srcdir)/dggui/uitranslation.cc \ translationtest.cc \ uunit/uunit.cc diff --git a/test/imagecachetest.cc b/test/imagecachetest.cc index 5471afb..6fa08d4 100644 --- a/test/imagecachetest.cc +++ b/test/imagecachetest.cc @@ -26,10 +26,8 @@ */ #include -#include - -#include -#include +#include +#include class TestableImageCache : public GUI::ImageCache diff --git a/test/paintertest.cc b/test/paintertest.cc index fb17a91..611693c 100644 --- a/test/paintertest.cc +++ b/test/paintertest.cc @@ -26,10 +26,10 @@ */ #include -#include "../plugingui/canvas.h" -#include "../plugingui/painter.h" -#include "../plugingui/image.h" -#include "../plugingui/font.h" +#include +#include +#include +#include class TestColour { diff --git a/test/resource_test.cc b/test/resource_test.cc index 1433dca..929544c 100644 --- a/test/resource_test.cc +++ b/test/resource_test.cc @@ -26,7 +26,7 @@ */ #include -#include "../plugingui/resource.h" +#include "../dggui/resource.h" #include "drumkit_creator.h" diff --git a/test/translationtest.cc b/test/translationtest.cc index d99c623..7525881 100644 --- a/test/translationtest.cc +++ b/test/translationtest.cc @@ -29,7 +29,7 @@ #include #include -#include +#include #include class TranslationTest diff --git a/test/uitests/Makefile.am b/test/uitests/Makefile.am index 8b1877e..a27a44b 100644 --- a/test/uitests/Makefile.am +++ b/test/uitests/Makefile.am @@ -2,11 +2,12 @@ noinst_PROGRAMS = resizetest tabwidgettest framewidgettest \ filebrowsertest benchmarktest powerwidgettest resizetest_LDADD = \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/dggui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la resizetest_CXXFLAGS = \ - -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin resizetest_SOURCES = \ @@ -14,11 +15,12 @@ resizetest_SOURCES = \ $(top_srcdir)/hugin/hugin.c tabwidgettest_LDADD = \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/dggui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la tabwidgettest_CXXFLAGS = \ - -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin tabwidgettest_SOURCES = \ @@ -26,11 +28,13 @@ tabwidgettest_SOURCES = \ $(top_srcdir)/hugin/hugin.c filebrowsertest_LDADD = \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/dggui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la filebrowsertest_CXXFLAGS = \ -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin filebrowsertest_SOURCES = \ @@ -38,11 +42,12 @@ filebrowsertest_SOURCES = \ $(top_srcdir)/hugin/hugin.c framewidgettest_LDADD = \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/dggui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la framewidgettest_CXXFLAGS = \ - -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin framewidgettest_SOURCES = \ @@ -59,15 +64,15 @@ rcgen_verbose = $(rcgen_verbose_@AM_V@) rcgen_verbose_ = $(rcgen_verbose_@AM_DEFAULT_V@) rcgen_verbose_0 = @echo " RCGEN "$@; -benchmarktest_resource_data.cc: $(top_builddir)/plugingui/rcgen $(RES) - $(rcgen_verbose)$(top_builddir)/plugingui/rcgen$(EXEEXT) -d $(top_srcdir)/test/uitests -o $@ $(RES) +benchmarktest_resource_data.cc: $(top_builddir)/dggui/rcgen $(RES) + $(rcgen_verbose)$(top_builddir)/dggui/rcgen$(EXEEXT) -d $(top_srcdir)/test/uitests -o $@ $(RES) benchmarktest_LDADD = \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/dggui/libdggui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la benchmarktest_CXXFLAGS = \ - -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin nodist_benchmarktest_SOURCES = \ @@ -81,11 +86,13 @@ CLEANFILES = benchmarktest_resource_data.cc powerwidgettest_LDADD = \ - $(top_builddir)/plugingui/libdggui.la \ + $(top_builddir)/dggui/libdggui.la \ + $(top_builddir)/plugingui/libplugingui.la \ $(top_builddir)/src/libdg.la \ $(top_builddir)/src/libnls.la powerwidgettest_CXXFLAGS = \ -I$(top_srcdir)/plugingui \ + -I$(top_srcdir)/ \ -I$(top_srcdir)/src \ -I$(top_srcdir)/hugin powerwidgettest_SOURCES = \ diff --git a/test/uitests/benchmarktest.cc b/test/uitests/benchmarktest.cc index aaf3946..5566942 100644 --- a/test/uitests/benchmarktest.cc +++ b/test/uitests/benchmarktest.cc @@ -29,9 +29,9 @@ #include #include -#include -#include -#include +#include +#include +#include class TimedCanvas : public GUI::Canvas diff --git a/test/uitests/filebrowsertest.cc b/test/uitests/filebrowsertest.cc index 5f78921..7c309d9 100644 --- a/test/uitests/filebrowsertest.cc +++ b/test/uitests/filebrowsertest.cc @@ -29,9 +29,10 @@ #include #include -#include -#include -#include + +#include +#include +#include #include class TestWindow diff --git a/test/uitests/framewidgettest.cc b/test/uitests/framewidgettest.cc index a2a24db..4f0e0fd 100644 --- a/test/uitests/framewidgettest.cc +++ b/test/uitests/framewidgettest.cc @@ -28,14 +28,15 @@ #include #include -#include -#include -#include #include -#include -#include -#include -#include + +#include +#include +#include +#include +#include +#include +#include // TODO: fix segfault on close diff --git a/test/uitests/powerwidgettest.cc b/test/uitests/powerwidgettest.cc index 9ab0458..41aff67 100644 --- a/test/uitests/powerwidgettest.cc +++ b/test/uitests/powerwidgettest.cc @@ -28,15 +28,18 @@ #include #include -#include -#include -#include #include -#include -#include -#include -#include + +#include +#include +#include +#include +#include +#include +#include + #include + #include class TestWindow diff --git a/test/uitests/resizetest.cc b/test/uitests/resizetest.cc index 8facc61..28439d1 100644 --- a/test/uitests/resizetest.cc +++ b/test/uitests/resizetest.cc @@ -29,9 +29,10 @@ #include #include -#include -#include -#include + +#include +#include +#include class TestWindow : public GUI::Window diff --git a/test/uitests/tabwidgettest.cc b/test/uitests/tabwidgettest.cc index 722dc02..36a69cc 100644 --- a/test/uitests/tabwidgettest.cc +++ b/test/uitests/tabwidgettest.cc @@ -29,12 +29,13 @@ #include #include -#include -#include -#include -#include -#include -#include + +#include +#include +#include +#include +#include +#include class Widget1 : public GUI::Widget -- cgit v1.2.3