summaryrefslogtreecommitdiff
path: root/plugingui
diff options
context:
space:
mode:
Diffstat (limited to 'plugingui')
-rw-r--r--plugingui/Makefile.am8
-rw-r--r--plugingui/Makefile.am.plugingui29
-rw-r--r--plugingui/Makefile.mingw32125
-rw-r--r--plugingui/button.cc211
-rw-r--r--plugingui/button.h59
-rw-r--r--plugingui/checkbox.cc169
-rw-r--r--plugingui/checkbox.h52
-rw-r--r--plugingui/colour.cc39
-rw-r--r--plugingui/colour.h27
-rw-r--r--plugingui/combobox.cc312
-rw-r--r--plugingui/combobox.h44
-rw-r--r--plugingui/dgwindow.cc344
-rw-r--r--plugingui/dgwindow.h90
-rw-r--r--plugingui/directory.cc669
-rw-r--r--plugingui/directory.h102
-rw-r--r--plugingui/eventhandler.cc371
-rw-r--r--plugingui/eventhandler.h39
-rw-r--r--plugingui/filebrowser.cc346
-rw-r--r--plugingui/filebrowser.h52
-rw-r--r--plugingui/font.cc160
-rw-r--r--plugingui/font.h39
-rw-r--r--plugingui/guievent.h134
-rw-r--r--plugingui/image.cc118
-rw-r--r--plugingui/image.h27
-rw-r--r--plugingui/knob.cc268
-rw-r--r--plugingui/knob.h64
-rw-r--r--plugingui/label.cc58
-rw-r--r--plugingui/label.h35
-rw-r--r--plugingui/layout.cc219
-rw-r--r--plugingui/layout.h135
-rw-r--r--plugingui/led.cc117
-rw-r--r--plugingui/led.h30
-rw-r--r--plugingui/lineedit.cc416
-rw-r--r--plugingui/lineedit.h62
-rw-r--r--plugingui/listbox.cc116
-rw-r--r--plugingui/listbox.h41
-rw-r--r--plugingui/listboxbasic.cc526
-rw-r--r--plugingui/listboxbasic.h86
-rw-r--r--plugingui/listboxthin.cc112
-rw-r--r--plugingui/listboxthin.h40
-rw-r--r--plugingui/nativewindow.h65
-rw-r--r--plugingui/nativewindow_pugl.cc278
-rw-r--r--plugingui/nativewindow_pugl.h59
-rw-r--r--plugingui/nativewindow_win32.cc547
-rw-r--r--plugingui/nativewindow_win32.h49
-rw-r--r--plugingui/nativewindow_x11.cc672
-rw-r--r--plugingui/nativewindow_x11.h54
-rw-r--r--plugingui/notifier.h163
-rw-r--r--plugingui/painter.cc811
-rw-r--r--plugingui/painter.h87
-rw-r--r--plugingui/pixelbuffer.cc199
-rw-r--r--plugingui/pixelbuffer.h94
-rw-r--r--plugingui/pluginconfig.cc33
-rw-r--r--plugingui/pluginconfig.h21
-rw-r--r--plugingui/plugingui.cc625
-rw-r--r--plugingui/plugingui.h80
-rw-r--r--plugingui/progressbar.cc136
-rw-r--r--plugingui/progressbar.h49
-rw-r--r--plugingui/resource.cc173
-rw-r--r--plugingui/resource.h27
-rw-r--r--plugingui/resource_data.h5
-rw-r--r--plugingui/scrollbar.cc224
-rw-r--r--plugingui/scrollbar.h59
-rw-r--r--plugingui/slider.cc216
-rw-r--r--plugingui/slider.h47
-rw-r--r--plugingui/testmain.cc75
-rw-r--r--plugingui/textedit.cc214
-rw-r--r--plugingui/textedit.h79
-rw-r--r--plugingui/verticalline.cc22
-rw-r--r--plugingui/verticalline.h16
-rw-r--r--plugingui/widget.cc243
-rw-r--r--plugingui/widget.h92
-rw-r--r--plugingui/window.cc282
-rw-r--r--plugingui/window.h95
74 files changed, 6726 insertions, 5056 deletions
diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am
index 00b0881..bc90f09 100644
--- a/plugingui/Makefile.am
+++ b/plugingui/Makefile.am
@@ -1,10 +1,8 @@
noinst_PROGRAMS = plugingui rcgen
include Makefile.am.plugingui
-#include $(top_srcdir)/src/Makefile.am.drumgizmo
-plugingui_LDADD = $(SNDFILE_LIBS) $(PTHREAD_LIBS) $(EXPAT_LIBS) \
- -ldl $(PLUGIN_GUI_LIBS)
+plugingui_LDADD = $(PLUGIN_GUI_LIBS)
plugingui_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS) \
-I$(top_srcdir)/include $(PLUGIN_GUI_CFLAGS) -I$(top_srcdir)/src \
@@ -13,6 +11,7 @@ plugingui_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS) \
plugingui_CFLAGS = $(plugingui_CXXFLAGS)
plugingui_SOURCES = \
+ testmain.cc \
$(PLUGIN_GUI_SOURCES) \
$(top_srcdir)/src/configfile.cc \
$(top_srcdir)/src/thread.cc \
@@ -57,5 +56,4 @@ EXTRA_DIST = \
verticalline.h \
widget.h \
window.h \
- lodepng/lodepng.h
-
+ lodepng/lodepng.h \ No newline at end of file
diff --git a/plugingui/Makefile.am.plugingui b/plugingui/Makefile.am.plugingui
index b1698e4..f4c0a55 100644
--- a/plugingui/Makefile.am.plugingui
+++ b/plugingui/Makefile.am.plugingui
@@ -1,12 +1,7 @@
-
-puglsources =
-
PLUGIN_GUI_SOURCES = \
$(top_srcdir)/hugin/hugin.c \
$(top_srcdir)/hugin/hugin_syslog.c \
- $(puglsources) \
- $(top_srcdir)/plugingui/nativewindow_x11.cc \
- $(top_srcdir)/plugingui/nativewindow_win32.cc \
+ $(top_srcdir)/plugingui/dgwindow.cc \
$(top_srcdir)/plugingui/plugingui.cc \
$(top_srcdir)/plugingui/label.cc \
$(top_srcdir)/plugingui/eventhandler.cc \
@@ -22,6 +17,8 @@ PLUGIN_GUI_SOURCES = \
$(top_srcdir)/plugingui/checkbox.cc \
$(top_srcdir)/plugingui/slider.cc \
$(top_srcdir)/plugingui/scrollbar.cc \
+ $(top_srcdir)/plugingui/textedit.cc \
+ $(top_srcdir)/plugingui/layout.cc \
$(top_srcdir)/plugingui/listbox.cc \
$(top_srcdir)/plugingui/listboxthin.cc \
$(top_srcdir)/plugingui/listboxbasic.cc \
@@ -37,13 +34,27 @@ PLUGIN_GUI_SOURCES = \
$(top_srcdir)/plugingui/resource_data.cc \
$(top_srcdir)/plugingui/lodepng/lodepng.cpp
-PLUGIN_GUI_LIBS = $(GUI_LIBS) $(PTHREAD_LIBS) $(ZLIB_LIBS)
+PLUGIN_GUI_LIBS = $(GUI_LIBS) $(PTHREAD_LIBS)
-PLUGIN_GUI_CFLAGS = $(GUI_CFLAGS) $(ZLIB_CFLAGS) -I$(top_srcdir)/hugin \
+PLUGIN_GUI_CFLAGS = $(GUI_CFLAGS) -I$(top_srcdir)/hugin \
-DWITH_HUG_SYSLOG -DWITH_HUG_MUTEX $(PTHREAD_CFLAGS) \
- -I$(top_srcdir)/pugl/pugl \
-DLODEPNG_NO_COMPILE_ENCODER \
-DLODEPNG_NO_COMPILE_DISK \
-DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS \
-DLODEPNG_NO_COMPILE_ERROR_TEXT \
-DLODEPNG_NO_COMPILE_CPP
+
+if ENABLE_X11
+PLUGIN_GUI_SOURCES += $(top_srcdir)/plugingui/nativewindow_x11.cc
+endif
+
+if ENABLE_WIN32
+PLUGIN_GUI_SOURCES += $(top_srcdir)/plugingui/nativewindow_win32.cc
+endif
+
+if ENABLE_PUGL
+PLUGIN_GUI_SOURCES += \
+ $(top_srcdir)/plugingui/nativewindow_pugl.cc \
+ $(top_srcdir)/pugl/pugl/pugl_x11.c
+PLUGIN_GUI_CFLAGS += -I$(top_srcdir)/pugl/pugl
+endif
diff --git a/plugingui/Makefile.mingw32 b/plugingui/Makefile.mingw32
index b16535b..3f52e8a 100644
--- a/plugingui/Makefile.mingw32
+++ b/plugingui/Makefile.mingw32
@@ -1,67 +1,62 @@
-top_srcdir=..
-include Makefile.am.plugingui
-
-CFLAGS=-DSTANDALONE -DWIN32 -DUSE_THREAD ${PLUGIN_GUI_CFLAGS} \
- -I$(top_srcdir)/src -I/local/include
-LDFLAGS=-mconsole -lgdi32 -lsetupapi -lws2_32 -L/local/lib -lz -pthread
-
-C_SOURCES = \
- $(top_srcdir)/hugin/hugin.c \
- $(top_srcdir)/hugin/hugin_syslog.c
-
-CXX_SOURCES = \
- $(top_srcdir)/plugingui/nativewindow_x11.cc \
- $(top_srcdir)/plugingui/nativewindow_win32.cc \
- $(top_srcdir)/plugingui/plugingui.cc \
- $(top_srcdir)/plugingui/pluginconfig.cc \
- $(top_srcdir)/plugingui/label.cc \
- $(top_srcdir)/plugingui/eventhandler.cc \
- $(top_srcdir)/plugingui/font.cc \
- $(top_srcdir)/plugingui/window.cc \
- $(top_srcdir)/plugingui/widget.cc \
- $(top_srcdir)/plugingui/colour.cc \
- $(top_srcdir)/plugingui/painter.cc \
- $(top_srcdir)/plugingui/button.cc \
- $(top_srcdir)/plugingui/pixelbuffer.cc \
- $(top_srcdir)/plugingui/lineedit.cc \
- $(top_srcdir)/plugingui/led.cc \
- $(top_srcdir)/plugingui/checkbox.cc \
- $(top_srcdir)/plugingui/slider.cc \
- $(top_srcdir)/plugingui/listbox.cc \
- $(top_srcdir)/plugingui/verticalline.cc \
- $(top_srcdir)/plugingui/listboxthin.cc \
- $(top_srcdir)/plugingui/listboxbasic.cc \
- $(top_srcdir)/plugingui/filebrowser.cc \
- $(top_srcdir)/plugingui/directory.cc \
- $(top_srcdir)/plugingui/knob.cc \
- $(top_srcdir)/plugingui/combobox.cc \
- $(top_srcdir)/plugingui/image.cc \
- $(top_srcdir)/plugingui/scrollbar.cc \
- $(top_srcdir)/plugingui/progressbar.cc \
- $(top_srcdir)/plugingui/resource.cc \
- $(top_srcdir)/plugingui/resource_data.cc \
- $(top_srcdir)/plugingui/lodepng/lodepng.cpp \
- $(top_srcdir)/src/thread.cc \
- $(top_srcdir)/src/semaphore.cc \
- $(top_srcdir)/src/mutex.cc \
- $(top_srcdir)/src/messagehandler.cc \
- $(top_srcdir)/src/messagereceiver.cc
-
-OBJECTS=$(CXX_SOURCES:.cc=.o) $(C_SOURCES:.c=.o)
-#OBJECTS=$(PLUGIN_GUI_SOURCES:.cc=.o)
-
-#$(PLUGIN_GUI_SOURCES:.c=.o)
-
-all: $(CXX_SOURCES) $(C_SOURCES) plugingui.exe
-
-plugingui.exe: $(OBJECTS)
- g++ -static -static-libgcc $(OBJECTS) $(LDFLAGS) $(CFLAGS) -o $@
-
-%.o: %.cc
- g++ -g -static -static-libgcc -O2 -c $(CFLAGS) $< -o $@
-
-%.o: %.c
- gcc -g -static -static-libgcc -O2 -c $(CFLAGS) $< -o $@
+DG_SRC = \
+ ../src/configfile.cc \
+ ../src/thread.cc \
+ ../src/semaphore.cc \
+ ../src/mutex.cc \
+ ../src/messagehandler.cc \
+ ../src/messagereceiver.cc
+
+DG_CFLAGS = -I.. -I../include -I../src -DSSE -msse -msse2 -DDISABLE_HUGIN
+
+GUI_SRC = \
+ testmain.cc \
+ dgwindow.cc \
+ nativewindow_win32.cc \
+ plugingui.cc \
+ pluginconfig.cc \
+ label.cc \
+ eventhandler.cc \
+ font.cc \
+ window.cc \
+ widget.cc \
+ colour.cc \
+ painter.cc \
+ button.cc \
+ pixelbuffer.cc \
+ lineedit.cc \
+ led.cc \
+ layout.cc \
+ checkbox.cc \
+ slider.cc \
+ scrollbar.cc \
+ textedit.cc \
+ listbox.cc \
+ listboxthin.cc \
+ listboxbasic.cc \
+ knob.cc \
+ filebrowser.cc \
+ directory.cc \
+ image.cc \
+ combobox.cc \
+ progressbar.cc \
+ verticalline.cc \
+ resource.cc \
+ resource_data.cc \
+ lodepng/lodepng.cpp
+
+GUI_CFLAGS=-DUSE_THREAD -DWIN32 -DSTANDALONE
+GUI_LIBS=-lgdi32 -lsetupapi -lws2_32
+
+DBG_SRC = \
+ ../hugin/hugin.c \
+ ../hugin/hugin_syslog.c
+
+DBG_CFLAGS=-I../hugin -DWITH_HUG_SYSLOG -DWITH_HUG_MUTEX -DDISABLE_HUGIN
+
+all:
+ gcc $(DBG_CFLAGS) ../hugin/hugin.c -c
+ gcc $(DBG_CFLAGS) ../hugin/hugin_syslog.c -c
+ g++ -std=c++11 -static -static-libgcc -O2 -g -Wall $(DBG_CFLAGS) $(DG_CFLAGS) $(DG_LIBS) hugin.o hugin_syslog.o $(DG_SRC) ${GUI_SRC} ${GUI_CFLAGS} $(GUI_LIBS) -o plugingui.exe
clean:
- rm -rf $(OBJECTS) plugingui.exe
+ del -f drumgizmo_vst.dll libdrumgizmo_vst.a
diff --git a/plugingui/button.cc b/plugingui/button.cc
index c316ef3..a3dd435 100644
--- a/plugingui/button.cc
+++ b/plugingui/button.cc
@@ -31,127 +31,134 @@
#include <stdio.h>
#include <hugin.hpp>
-GUI::Button::Button(Widget *parent)
- : GUI::Widget(parent)
-{
- box_up.topLeft = new Image(":pushbutton_tl.png");
- box_up.top = new Image(":pushbutton_t.png");
- box_up.topRight = new Image(":pushbutton_tr.png");
- box_up.left = new Image(":pushbutton_l.png");
- box_up.right = new Image(":pushbutton_r.png");
- box_up.bottomLeft = new Image(":pushbutton_bl.png");
- box_up.bottom = new Image(":pushbutton_b.png");
- box_up.bottomRight = new Image(":pushbutton_br.png");
- box_up.center = new Image(":pushbutton_c.png");
-
- box_down.topLeft = new Image(":pushbuttondown_tl.png");
- box_down.top = new Image(":pushbuttondown_t.png");
- box_down.topRight = new Image(":pushbuttondown_tr.png");
- box_down.left = new Image(":pushbuttondown_l.png");
- box_down.right = new Image(":pushbuttondown_r.png");
- box_down.bottomLeft = new Image(":pushbuttondown_bl.png");
- box_down.bottom = new Image(":pushbuttondown_b.png");
- box_down.bottomRight = new Image(":pushbuttondown_br.png");
- box_down.center = new Image(":pushbuttondown_c.png");
-
- draw_state = up;
- button_state = up;
-
- handler = NULL;
- ptr = NULL;
-}
+namespace GUI {
-void GUI::Button::registerClickHandler(void (*handler)(void *), void *ptr)
+Button::Button(Widget *parent)
+ : Widget(parent)
+ , draw_state(up)
+ , button_state(up)
{
- this->handler = handler;
- this->ptr = ptr;
+ box_up.topLeft = new Image(":pushbutton_tl.png");
+ box_up.top = new Image(":pushbutton_t.png");
+ box_up.topRight = new Image(":pushbutton_tr.png");
+ box_up.left = new Image(":pushbutton_l.png");
+ box_up.right = new Image(":pushbutton_r.png");
+ box_up.bottomLeft = new Image(":pushbutton_bl.png");
+ box_up.bottom = new Image(":pushbutton_b.png");
+ box_up.bottomRight = new Image(":pushbutton_br.png");
+ box_up.center = new Image(":pushbutton_c.png");
+
+ box_down.topLeft = new Image(":pushbuttondown_tl.png");
+ box_down.top = new Image(":pushbuttondown_t.png");
+ box_down.topRight = new Image(":pushbuttondown_tr.png");
+ box_down.left = new Image(":pushbuttondown_l.png");
+ box_down.right = new Image(":pushbuttondown_r.png");
+ box_down.bottomLeft = new Image(":pushbuttondown_bl.png");
+ box_down.bottom = new Image(":pushbuttondown_b.png");
+ box_down.bottomRight = new Image(":pushbuttondown_br.png");
+ box_down.center = new Image(":pushbuttondown_c.png");
}
-void GUI::Button::buttonEvent(ButtonEvent *e)
+Button::~Button()
{
- if(e->direction == 1) {
- draw_state = down;
- button_state = down;
- in_button = true;
- repaintEvent(NULL);
- }
- if(e->direction == -1) {
- draw_state = up;
- button_state = up;
- repaintEvent(NULL);
- if(in_button) {
- clicked();
- if(handler) handler(ptr);
- }
- }
+ delete(box_up.topLeft);
+ delete(box_up.top);
+ delete(box_up.topRight);
+ delete(box_up.left);
+ delete(box_up.right);
+ delete(box_up.bottomLeft);
+ delete(box_up.bottom);
+ delete(box_up.bottomRight);
+ delete(box_up.center);
+ delete(box_down.topLeft);
+ delete(box_down.top);
+ delete(box_down.topRight);
+ delete(box_down.left);
+ delete(box_down.right);
+ delete(box_down.bottomLeft);
+ delete(box_down.bottom);
+ delete(box_down.bottomRight);
+ delete(box_down.center);
}
-void GUI::Button::repaintEvent(GUI::RepaintEvent *e)
+void Button::buttonEvent(ButtonEvent* buttonEvent)
{
- Painter p(this);
-
- p.clear();
-
- int w = width();
- int h = height();
- if(w == 0 || h == 0) return;
-
- switch(draw_state) {
- case up:
- p.drawBox(0, 0, &box_up, w, h);
- break;
- case down:
- p.drawBox(0, 0, &box_down, w, h);
- break;
- }
-
- Font font(":fontemboss.png");
- p.setColour(Colour(0.1));
- p.drawText(width()/2-(text.length()*3)+(draw_state==up?0:1),
- height()/2+5+1+(draw_state==up?0:1), font, text, true);
+ if(buttonEvent->direction == Direction::down)
+ {
+ draw_state = down;
+ button_state = down;
+ in_button = true;
+ repaintEvent(nullptr);
+ }
+
+ if(buttonEvent->direction == Direction::up)
+ {
+ draw_state = up;
+ button_state = up;
+ repaintEvent(nullptr);
+ if(in_button)
+ {
+ clicked();
+ clickNotifier();
+ }
+ }
}
-void GUI::Button::setText(std::string text)
+void Button::repaintEvent(RepaintEvent* repaintEvent)
{
- this->text = text;
- repaintEvent(NULL);
+ Painter p(*this);
+
+ p.clear();
+
+ int padTop = 3;
+ int padLeft = 0;
+
+ int w = width();
+ int h = height();
+ if(w == 0 || h == 0)
+ {
+ return;
+ }
+
+ switch(draw_state) {
+ case up:
+ p.drawBox(padLeft, padTop, box_up, w - padLeft, h - padTop);
+ break;
+ case down:
+ p.drawBox(padLeft, padTop, box_down, w - padLeft, h - padTop);
+ break;
+ }
+
+ p.setColour(Colour(0.1));
+ p.drawText(width()/2-(text.length()*3)+(draw_state==up?0:1) + (padLeft / 2),
+ height()/2+5+1+(draw_state==up?0:1) + (padTop / 2), font, text,
+ true);
}
-void GUI::Button::mouseLeaveEvent()
+void Button::setText(const std::string& text)
{
- in_button = false;
- if(button_state == down) {
- draw_state = up;
- repaintEvent(NULL);
- }
+ this->text = text;
+ repaintEvent(nullptr);
}
-void GUI::Button::mouseEnterEvent()
+void Button::mouseLeaveEvent()
{
- in_button = true;
- if(button_state == down) {
- draw_state = down;
- repaintEvent(NULL);
- }
+ in_button = false;
+ if(button_state == down)
+ {
+ draw_state = up;
+ repaintEvent(nullptr);
+ }
}
-void GUI::Button::mouseMoveEvent(MouseMoveEvent *e)
+void Button::mouseEnterEvent()
{
+ in_button = true;
+ if(button_state == down)
+ {
+ draw_state = down;
+ repaintEvent(nullptr);
+ }
}
-#ifdef TEST_BUTTON
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_BUTTON*/
+} //GUI::
diff --git a/plugingui/button.h b/plugingui/button.h
index 682dfa2..f42dc99 100644
--- a/plugingui/button.h
+++ b/plugingui/button.h
@@ -24,57 +24,56 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_BUTTON_H__
-#define __DRUMGIZMO_BUTTON_H__
+#pragma once
#include <string>
#include "widget.h"
#include "painter.h"
+#include "notifier.h"
+#include "font.h"
namespace GUI {
class Button : public Widget {
public:
- Button(Widget *parent);
+ Button(Widget *parent);
+ ~Button();
- bool isFocusable() { return true; }
- bool catchMouse() { return true; }
+ // From Widget:
+ bool isFocusable() override { return true; }
+ bool catchMouse() override { return true; }
- void setText(std::string text);
+ void setText(const std::string& text);
- void registerClickHandler(void (*handler)(void *), void *ptr);
+ Notifier<> clickNotifier;
- //protected:
- virtual void clicked() {}
+protected:
+ virtual void clicked() {}
- virtual void repaintEvent(RepaintEvent *e);
- virtual void buttonEvent(ButtonEvent *e);
-
- virtual void mouseLeaveEvent();
- virtual void mouseEnterEvent();
- virtual void mouseMoveEvent(MouseMoveEvent *e);
+ // From Widget:
+ virtual void repaintEvent(RepaintEvent* e) override;
+ virtual void buttonEvent(ButtonEvent* e) override;
+ virtual void mouseLeaveEvent() override;
+ virtual void mouseEnterEvent() override;
private:
- bool in_button;
-
- Painter::Box box_up;
- Painter::Box box_down;
+ bool in_button{false};
- typedef enum {
- up,
- down
- } state_t;
+ Painter::Box box_up;
+ Painter::Box box_down;
- std::string text;
+ typedef enum {
+ up,
+ down
+ } state_t;
- state_t draw_state;
- state_t button_state;
+ std::string text;
- void (*handler)(void *);
- void *ptr;
-};
+ Font font{":fontemboss.png"};
+ state_t draw_state{up};
+ state_t button_state{up};
};
-#endif/*__DRUMGIZMO_BUTTON_H__*/
+} // GUI::
diff --git a/plugingui/checkbox.cc b/plugingui/checkbox.cc
index faf3741..60ed7a6 100644
--- a/plugingui/checkbox.cc
+++ b/plugingui/checkbox.cc
@@ -30,101 +30,126 @@
#include <stdio.h>
-GUI::CheckBox::CheckBox(Widget *parent)
- : GUI::Widget(parent),
- bg_on(":switch_back_on.png"), bg_off(":switch_back_off.png"),
- knob(":switch_front.png")
+namespace GUI {
+
+CheckBox::CheckBox(Widget* parent)
+ : Widget(parent)
+ , bg_on(":switch_back_on.png")
+ , bg_off(":switch_back_off.png")
+ , knob(":switch_front.png")
+ , state(false)
+ , middle(false)
{
- middle = false;
- state = false;
- handler = NULL;
}
-void GUI::CheckBox::buttonEvent(ButtonEvent *e)
+void CheckBox::buttonEvent(ButtonEvent* buttonEvent)
{
- if(e->direction == -1 || e->doubleclick) {
- state = !state;
- middle = false;
- if(handler) handler(ptr);
- } else {
- middle = true;
- }
-
- repaintEvent(NULL);
+ if((buttonEvent->direction == Direction::up) || buttonEvent->doubleClick)
+ {
+ buttonDown = false;
+ middle = false;
+ if(inCheckbox)
+ {
+ internalSetChecked(!state);
+ }
+ }
+ else
+ {
+ buttonDown = true;
+ middle = true;
+ }
+
+ repaintEvent(nullptr);
}
-void GUI::CheckBox::setText(std::string text)
+void CheckBox::setText(std::string text)
{
- _text = text;
- repaintEvent(NULL);
+ _text = text;
+ repaintEvent(nullptr);
}
-void GUI::CheckBox::registerClickHandler(void (*handler)(void *), void *ptr)
+void CheckBox::keyEvent(KeyEvent* keyEvent)
{
- this->handler = handler;
- this->ptr = ptr;
+ if(keyEvent->keycode == Key::character && keyEvent->text == " ")
+ {
+ if(keyEvent->direction == Direction::up)
+ {
+ middle = false;
+ internalSetChecked(!state);
+ }
+ else
+ {
+ middle = true;
+ }
+
+ repaintEvent(nullptr);
+ }
}
-void GUI::CheckBox::keyEvent(KeyEvent *e)
+void CheckBox::repaintEvent(RepaintEvent* repaintEvent)
{
- if(e->keycode == GUI::KeyEvent::KEY_CHARACTER && e->text == " ") {
- if(e->direction == -1) {
- state = !state;
- middle = false;
- } else {
- middle = true;
- }
-
- repaintEvent(NULL);
- }
+ Painter p(*this);
+
+ p.clear();
+
+ p.drawImage(0, (knob.height() - bg_on.height()) / 2, state ? bg_on : bg_off);
+
+ if(middle)
+ {
+ 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);
+ }
}
-void GUI::CheckBox::repaintEvent(GUI::RepaintEvent *e)
+bool CheckBox::checked()
{
- Painter p(this);
-
- p.clear();
-
- if(state) {
- p.drawImage(0, (knob.height() - bg_on.height()) / 2, &bg_on);
- if(middle) p.drawImage((bg_on.width() - knob.width()) / 2 + 1, 0, &knob);
- else p.drawImage(bg_on.width() - 40 + 2, 0, &knob);
- } else {
- p.drawImage(0, (knob.height() - bg_off.height()) / 2, &bg_off);
- if(middle) p.drawImage((bg_on.width() - knob.width()) / 2 + 1, 0, &knob);
- else p.drawImage(0, 0, &knob);
- }
- /*
- p.setColour(Colour(1));
- Font font;
- p.drawText(box + 8, height() / 2 + 5, font, _text);
- */
+ return state;
}
-bool GUI::CheckBox::checked()
+void CheckBox::setChecked(bool c)
{
- return state;
+ internalSetChecked(c);
}
-void GUI::CheckBox::setChecked(bool c)
+void CheckBox::mouseLeaveEvent()
{
- state = c;
- repaintEvent(NULL);
+ inCheckbox = false;
+ if(buttonDown)
+ {
+ middle = false;
+ repaintEvent(nullptr);
+ }
}
-#ifdef TEST_CHECKBOX
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
+void CheckBox::mouseEnterEvent()
+{
+ inCheckbox = true;
+ if(buttonDown)
+ {
+ middle = true;
+ repaintEvent(nullptr);
+ }
+}
-TEST_END;
+void CheckBox::internalSetChecked(bool checked)
+{
+ if(checked == state)
+ {
+ return;
+ }
+
+ state = checked;
+ stateChangedNotifier(state);
+ repaintEvent(nullptr);
+}
-#endif/*TEST_CHECKBOX*/
+} // GUI::
diff --git a/plugingui/checkbox.h b/plugingui/checkbox.h
index 1d6f9d6..927bf6d 100644
--- a/plugingui/checkbox.h
+++ b/plugingui/checkbox.h
@@ -24,48 +24,50 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_CHECKBOX_H__
-#define __DRUMGIZMO_CHECKBOX_H__
+#pragma once
#include "widget.h"
#include "image.h"
+#include "notifier.h"
namespace GUI {
class CheckBox : public Widget {
public:
- CheckBox(Widget *parent);
+ CheckBox(Widget *parent);
- void setText(std::string text);
+ void setText(std::string text);
- bool isFocusable() { return true; }
+ // From Widget:
+ bool isFocusable() override { return true; }
+ bool catchMouse() override { return true; }
- bool checked();
- void setChecked(bool checked);
+ bool checked();
+ void setChecked(bool checked);
- void registerClickHandler(void (*handler)(void *), void *ptr);
+ Notifier<bool> stateChangedNotifier;
- //protected:
- virtual void clicked() {}
-
- virtual void repaintEvent(RepaintEvent *e);
- virtual void buttonEvent(ButtonEvent *e);
- virtual void keyEvent(KeyEvent *e);
+protected:
+ // From Widget:
+ virtual void repaintEvent(RepaintEvent* repaintEvent) override;
+ virtual void buttonEvent(ButtonEvent* buttonEvent) override;
+ virtual void keyEvent(KeyEvent* keyEvent) override;
+ virtual void mouseLeaveEvent() override;
+ virtual void mouseEnterEvent() override;
private:
- Image bg_on;
- Image bg_off;
- Image knob;
-
- bool state;
- bool middle;
+ void internalSetChecked(bool checked);
- void (*handler)(void *);
- void *ptr;
+ Image bg_on;
+ Image bg_off;
+ Image knob;
- std::string _text;
-};
+ bool state;
+ bool middle;
+ bool buttonDown = false;
+ bool inCheckbox = false;
+ std::string _text;
};
-#endif/*__DRUMGIZMO_CHECKBOX_H__*/
+} // GUI::
diff --git a/plugingui/colour.cc b/plugingui/colour.cc
index 943011b..fb3d789 100644
--- a/plugingui/colour.cc
+++ b/plugingui/colour.cc
@@ -26,38 +26,25 @@
*/
#include "colour.h"
-GUI::Colour::Colour()
+namespace GUI {
+
+Colour::Colour()
{
- red = blue = green = alpha = 1.0;
+ red = blue = green = alpha = 1.0;
}
-GUI::Colour::Colour(float grey, float a)
+Colour::Colour(float grey, float a)
{
- red = green = blue = grey;
- alpha = a;
+ red = green = blue = grey;
+ alpha = a;
}
-GUI::Colour::Colour(float r, float g, float b, float a)
+Colour::Colour(float r, float g, float b, float a)
{
- red = r;
- green = g;
- blue = b;
- alpha = a;
+ red = r;
+ green = g;
+ blue = b;
+ alpha = a;
}
-#ifdef TEST_COLOUR
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_COLOUR*/
+} // GUI::
diff --git a/plugingui/colour.h b/plugingui/colour.h
index 92ec99e..9f539e9 100644
--- a/plugingui/colour.h
+++ b/plugingui/colour.h
@@ -24,28 +24,25 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_COLOUR_H__
-#define __DRUMGIZMO_COLOUR_H__
+#pragma once
namespace GUI {
class Colour {
public:
- Colour();
+ Colour();
- Colour(float grey, float alpha = 1.0);
+ Colour(float grey, float alpha = 1.0);
- Colour(float red,
- float green,
- float blue,
- float alpha = 1.0);
+ Colour(float red,
+ float green,
+ float blue,
+ float alpha = 1.0);
- float red;
- float green;
- float blue;
- float alpha;
+ float red;
+ float green;
+ float blue;
+ float alpha;
};
-};
-
-#endif/*__DRUMGIZMO_COLOUR_H__*/
+} // GUI::
diff --git a/plugingui/combobox.cc b/plugingui/combobox.cc
index 4637282..1323dab 100644
--- a/plugingui/combobox.cc
+++ b/plugingui/combobox.cc
@@ -33,199 +33,215 @@
#define BORDER 10
-void listboxSelectHandler(void *ptr)
-{
- GUI::ComboBox *c = (GUI::ComboBox*)ptr;
- GUI::ButtonEvent e;
- e.direction = 1;
- c->buttonEvent(&e);
-}
+namespace GUI {
-GUI::ComboBox::ComboBox(GUI::Widget *parent)
- : GUI::Widget(parent)
+void ComboBox::listboxSelectHandler()
{
- handler = NULL;
- ptr = NULL;
-
- box.topLeft = new Image(":widget_tl.png");
- box.top = new Image(":widget_t.png");
- box.topRight = new Image(":widget_tr.png");
- box.left = new Image(":widget_l.png");
- box.right = new Image(":widget_r.png");
- box.bottomLeft = new Image(":widget_bl.png");
- box.bottom = new Image(":widget_b.png");
- box.bottomRight = new Image(":widget_br.png");
- box.center = new Image(":widget_c.png");
-
- listbox = new GUI::ListBoxThin(parent);
- listbox->registerSelectHandler(listboxSelectHandler, this);
- listbox->registerClickHandler(listboxSelectHandler, this);
- listbox->hide();
+ ButtonEvent buttonEvent;
+ buttonEvent.direction = Direction::down;
+ this->buttonEvent(&buttonEvent);
}
-GUI::ComboBox::~ComboBox()
+ComboBox::ComboBox(Widget* parent)
+ : Widget(parent)
+ , listbox(parent)
{
+ box.topLeft = new Image(":widget_tl.png");
+ box.top = new Image(":widget_t.png");
+ box.topRight = new Image(":widget_tr.png");
+ box.left = new Image(":widget_l.png");
+ box.right = new Image(":widget_r.png");
+ box.bottomLeft = new Image(":widget_bl.png");
+ box.bottom = new Image(":widget_b.png");
+ box.bottomRight = new Image(":widget_br.png");
+ box.center = new Image(":widget_c.png");
+
+ CONNECT(&listbox, selectionNotifier, this, &ComboBox::listboxSelectHandler);
+ CONNECT(&listbox, clickNotifier, this, &ComboBox::listboxSelectHandler);
+
+ listbox.hide();
}
-void GUI::ComboBox::addItem(std::string name, std::string value)
+ComboBox::~ComboBox()
{
- listbox->addItem(name, value);
+ delete box.topLeft;
+ delete box.top;
+ delete box.topRight;
+ delete box.left;
+ delete box.right;
+ delete box.bottomLeft;
+ delete box.bottom;
+ delete box.bottomRight;
+ delete box.center;
}
-void GUI::ComboBox::clear()
+void ComboBox::addItem(std::string name, std::string value)
{
- listbox->clear();
- repaintEvent(NULL);
+ listbox.addItem(name, value);
}
-bool GUI::ComboBox::selectItem(int index)
+void ComboBox::clear()
{
- listbox->selectItem(index);
- repaintEvent(NULL);
- return true;
+ listbox.clear();
+ repaintEvent(nullptr);
}
-std::string GUI::ComboBox::selectedName()
+bool ComboBox::selectItem(int index)
{
- return listbox->selectedName();
+ listbox.selectItem(index);
+ repaintEvent(nullptr);
+ return true;
}
-std::string GUI::ComboBox::selectedValue()
+std::string ComboBox::selectedName()
{
- return listbox->selectedValue();
+ return listbox.selectedName();
}
-void GUI::ComboBox::registerValueChangedHandler(void (*handler)(void *),
- void *ptr)
+std::string ComboBox::selectedValue()
{
- this->handler = handler;
- this->ptr = ptr;
+ return listbox.selectedValue();
}
-static void drawArrow(GUI::Painter &p, int x, int y, int w, int h)
+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);
+ 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);
+ y++;
+ p.drawLine(x, y, x+(w/2), y+h);
+ p.drawLine(x+(w/2), y+h, x+w, y);
}
-void GUI::ComboBox::repaintEvent(GUI::RepaintEvent *e)
+void ComboBox::repaintEvent(RepaintEvent* repaintEvent)
{
- Painter p(this);
+ Painter p(*this);
+
+ p.clear();
- p.clear();
+ std::string _text = selectedName();
- std::string _text = selectedName();
+ int w = width();
+ int h = height();
+ if(w == 0 || h == 0)
+ {
+ return;
+ }
- int w = width();
- int h = height();
- if(w == 0 || h == 0) return;
- p.drawBox(0, 0, &box, w, h);
+ p.drawBox(0, 0, box, w, h);
- p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
- p.drawText(BORDER - 4 + 3, height()/2+5 + 1 + 1, font, _text);
+ p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
+ 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);
+ // p.setColour(Colour(1, 1, 1));
+ // p.drawText(BORDER - 4, (height()+font.textHeight()) / 2 + 1, font, _text);
- //int n = height() / 2;
+ //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);
- }
+ // 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 GUI::ComboBox::scrollEvent(ScrollEvent *e)
+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);
- repaintEvent(NULL);
- */
+ /*
+ scroll_offset += e->delta;
+ if(scroll_offset < 0)
+ {
+ scroll_offset = 0;
+ }
+ if(scroll_offset > (items.size() - 1))
+ {
+ scroll_offset = (items.size() - 1);
+ }
+ repaintEvent(nullptr);
+ */
}
-void GUI::ComboBox::keyEvent(GUI::KeyEvent *e)
+void ComboBox::keyEvent(KeyEvent* keyEvent)
{
- if(e->direction != -1) return;
-
- /*
- switch(e->keycode) {
- case GUI::KeyEvent::KEY_UP:
- {
- selected--;
- if(selected < 0) selected = 0;
- if(selected < scroll_offset) {
- scroll_offset = selected;
- if(scroll_offset < 0) scroll_offset = 0;
- }
- }
- break;
- case GUI::KeyEvent::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 GUI::KeyEvent::KEY_HOME:
- selected = 0;
- break;
- case GUI::KeyEvent::KEY_END:
- selected = items.size() - 1;
- break;
- default:
- break;
- }
-
- repaintEvent(NULL);
- */
+ 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;
+ }
+
+ repaintEvent(nullptr);
+ */
}
-void GUI::ComboBox::buttonEvent(ButtonEvent *e)
+void ComboBox::buttonEvent(ButtonEvent* buttonEvent)
{
- if(e->direction != 1) return;
-
- if(!listbox->visible()) {
- listbox->resize(width() - 10, 100);
- listbox->move(x() + 5, y() + height() - 7);
- } else {
- if(handler) handler(ptr);
- }
-
- listbox->setVisible(!listbox->visible());
+ 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());
}
-#ifdef TEST_COMBOBOX
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_COMBOBOX*/
+} // GUI::
diff --git a/plugingui/combobox.h b/plugingui/combobox.h
index bc4ae38..1e4fb8d 100644
--- a/plugingui/combobox.h
+++ b/plugingui/combobox.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_COMBOBOX_H__
-#define __DRUMGIZMO_COMBOBOX_H__
+#pragma once
#include <string.h>
#include <vector>
@@ -39,35 +38,32 @@ namespace GUI {
class ComboBox : public Widget {
public:
- ComboBox(Widget *parent);
- ~ComboBox();
+ ComboBox(Widget* parent);
+ ~ComboBox();
- bool isFocusable() { return true; }
+ void addItem(std::string name, std::string value);
- void addItem(std::string name, std::string value);
+ void clear();
+ bool selectItem(int index);
+ std::string selectedName();
+ std::string selectedValue();
- 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;
- void registerValueChangedHandler(void (*handler)(void *), void *ptr);
-
- virtual void repaintEvent(RepaintEvent *e);
- virtual void buttonEvent(ButtonEvent *e);
- virtual void scrollEvent(ScrollEvent *e);
- virtual void keyEvent(KeyEvent *e);
+ Notifier<std::string, std::string> valueChangedNotifier;
private:
- Painter::Box box;
-
- GUI::Font font;
- GUI::ListBoxThin *listbox;
+ Painter::Box box;
- void (*handler)(void *);
- void *ptr;
-};
+ void listboxSelectHandler();
+ Font font;
+ ListBoxThin listbox;
};
-#endif/*__DRUMGIZMO_COMBOBOX_H__*/
+} // GUI::
diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc
new file mode 100644
index 0000000..9eae38c
--- /dev/null
+++ b/plugingui/dgwindow.cc
@@ -0,0 +1,344 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * dgwindow.cc
+ *
+ * Mon Nov 23 20:30:45 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 "dgwindow.h"
+
+#include "knob.h"
+#include "verticalline.h"
+#include "../version.h"
+
+#include "messagehandler.h"
+#include "pluginconfig.h"
+
+namespace GUI {
+
+class LabeledControl : public Widget
+{
+public:
+ LabeledControl(Widget* parent, const std::string& name)
+ : Widget(parent)
+ {
+ layout.setResizeChildren(false);
+ layout.setHAlignment(HAlignment::center);
+
+ caption.setText(name);
+ caption.resize(100, 20);
+ caption.setAlignment(TextAlignment::center);
+ layout.addItem(&caption);
+ }
+
+ void setControl(Widget* control)
+ {
+ layout.addItem(control);
+ }
+
+ VBoxLayout layout{this};
+
+ Label caption{this};
+};
+
+class File : public Widget
+{
+public:
+ File(Widget* parent)
+ : Widget(parent)
+ {
+ layout.setResizeChildren(false);
+ layout.setVAlignment(VAlignment::center);
+
+ lineedit.resize(243, 29);
+ layout.addItem(&lineedit);
+
+ browseButton.setText("Browse...");
+ browseButton.resize(85, 41);
+ layout.addItem(&browseButton);
+ }
+
+ HBoxLayout layout{this};
+
+ LineEdit lineedit{this};
+ Button browseButton{this};
+};
+
+class HumanizeControls : public Widget
+{
+public:
+ HumanizeControls(Widget* parent)
+ : Widget(parent)
+ {
+ layout.setResizeChildren(false);
+ layout.setVAlignment(VAlignment::center);
+
+ velocity.resize(80, 80);
+ velocityCheck.resize(59, 38);
+ velocity.setControl(&velocityCheck);
+ layout.addItem(&velocity);
+
+ attack.resize(80, 80);
+ attackKnob.resize(60, 60);
+ attack.setControl(&attackKnob);
+ layout.addItem(&attack);
+
+ falloff.resize(80, 80);
+ falloffKnob.resize(60, 60);
+ falloff.setControl(&falloffKnob);
+ layout.addItem(&falloff);
+ }
+
+ HBoxLayout layout{this};
+
+ LabeledControl velocity{this, "Humanizer"};
+ LabeledControl attack{this, "Attack"};
+ LabeledControl falloff{this, "Release"};
+
+ CheckBox velocityCheck{&velocity};
+ Knob attackKnob{&attack};
+ Knob falloffKnob{&falloff};
+};
+
+DGWindow::DGWindow(MessageHandler& messageHandler, Config& config)
+ : messageHandler(messageHandler)
+ , config(config)
+{
+
+ int vlineSpacing = 16;
+
+ setFixedSize(370, 330);
+ setCaption("DrumGizmo v" VERSION);
+
+ layout.setResizeChildren(false);
+ layout.setHAlignment(HAlignment::center);
+// layout.setSpacing(0);
+
+ auto headerCaption = new Label(this);
+ headerCaption->setText("DrumGizmo");
+ headerCaption->setAlignment(TextAlignment::center);
+ headerCaption->resize(width() - 40, 32);
+ layout.addItem(headerCaption);
+
+ auto headerLine = new VerticalLine(this);
+ headerLine->resize(width() - 40, vlineSpacing);
+ layout.addItem(headerLine);
+
+ auto drumkitCaption = new Label(this);
+ drumkitCaption->setText("Drumkit file:");
+ drumkitCaption->resize(width() - 40, 15);
+ layout.addItem(drumkitCaption);
+
+ auto drumkitFile = new File(this);
+ drumkitFile->resize(width() - 40, 37);
+ lineedit = &drumkitFile->lineedit;
+ CONNECT(&drumkitFile->browseButton, clickNotifier,
+ this, &DGWindow::kitBrowseClick);
+ layout.addItem(drumkitFile);
+
+ drumkitFileProgress = new ProgressBar(this);
+ drumkitFileProgress->resize(width() - 40, 11);
+ layout.addItem(drumkitFileProgress);
+
+ VerticalLine *l = new VerticalLine(this);
+ l->resize(width() - 40, vlineSpacing);
+ layout.addItem(l);
+
+ auto midimapCaption = new Label(this);
+ midimapCaption->setText("Midimap file:");
+ midimapCaption->resize(width() - 40, 15);
+ layout.addItem(midimapCaption);
+
+ auto midimapFile = new File(this);
+ midimapFile->resize(width() - 40, 37);
+ lineedit2 = &midimapFile->lineedit;
+ CONNECT(&midimapFile->browseButton, clickNotifier,
+ this, &DGWindow::midimapBrowseClick);
+ layout.addItem(midimapFile);
+
+ midimapFileProgress = new ProgressBar(this);
+ midimapFileProgress->resize(width() - 40, 11);
+ layout.addItem(midimapFileProgress);
+
+ VerticalLine *l2 = new VerticalLine(this);
+ l2->resize(width() - 40, vlineSpacing);
+ layout.addItem(l2);
+
+ HumanizeControls* humanizeControls = new HumanizeControls(this);
+ humanizeControls->resize(80 * 3, 80);
+ layout.addItem(humanizeControls);
+ CONNECT(&humanizeControls->velocityCheck, stateChangedNotifier,
+ this, &DGWindow::velocityCheckClick);
+
+ CONNECT(&humanizeControls->attackKnob, valueChangedNotifier,
+ this, &DGWindow::attackValueChanged);
+
+ CONNECT(&humanizeControls->falloffKnob, valueChangedNotifier,
+ this, &DGWindow::falloffValueChanged);
+
+ // Store pointers for PluginGUI access:
+ velocityCheck = &humanizeControls->velocityCheck;
+ attackKnob = &humanizeControls->attackKnob;
+ falloffKnob = &humanizeControls->falloffKnob;
+
+ VerticalLine *l3 = new VerticalLine(this);
+ l3->resize(width() - 40, vlineSpacing);
+ layout.addItem(l3);
+
+ Label *lbl_version = new Label(this);
+ lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. GPLv3 .::.");
+ lbl_version->resize(width(), 20);
+ lbl_version->setAlignment(TextAlignment::center);
+ layout.addItem(lbl_version);
+
+ // Create file browser
+ fileBrowser = new FileBrowser(this);
+ fileBrowser->move(0, 0);
+ fileBrowser->resize(this->width() - 1, this->height() - 1);
+ fileBrowser->hide();
+}
+
+void DGWindow::repaintEvent(RepaintEvent* repaintEvent)
+{
+ if(!visible())
+ {
+ return;
+ }
+
+ Painter p(*this);
+ p.drawImageStretched(0,0, back, width(), height());
+ p.drawImage(width() - logo.width(), height() - logo.height(), logo);
+}
+
+void DGWindow::attackValueChanged(float value)
+{
+ ChangeSettingMessage *msg =
+ new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight,
+ value);
+
+ messageHandler.sendMessage(MSGRCV_ENGINE, msg);
+
+#ifdef STANDALONE
+ int i = value * 4;
+ switch(i) {
+ case 0: drumkitFileProgress->setState(ProgressBarState::Off); break;
+ case 1: drumkitFileProgress->setState(ProgressBarState::Blue); break;
+ case 2: drumkitFileProgress->setState(ProgressBarState::Green); break;
+ case 3: drumkitFileProgress->setState(ProgressBarState::Red); break;
+ default: break;
+ }
+#endif
+}
+
+void DGWindow::falloffValueChanged(float value)
+{
+ ChangeSettingMessage *msg =
+ new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff,
+ value);
+ messageHandler.sendMessage(MSGRCV_ENGINE, msg);
+
+#ifdef STANDALONE
+ drumkitFileProgress->setProgress(value);
+#endif
+}
+
+void DGWindow::velocityCheckClick(bool checked)
+{
+ ChangeSettingMessage *msg =
+ new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier,
+ checked);
+ messageHandler.sendMessage(MSGRCV_ENGINE, msg);
+}
+
+void DGWindow::kitBrowseClick()
+{
+ std::string path = lineedit->text();
+ if(path == "")
+ {
+ path = config.lastkit;
+ }
+
+ if(path == "")
+ {
+ path = lineedit2->text();
+ }
+
+ fileBrowser->setPath(path);
+ CONNECT(fileBrowser, fileSelectNotifier, this, &DGWindow::selectKitFile);
+ fileBrowser->show();
+}
+
+void DGWindow::midimapBrowseClick()
+{
+ std::string path = lineedit2->text();
+ if(path == "")
+ {
+ path = config.lastmidimap;
+ }
+
+ if(path == "")
+ {
+ path = lineedit->text();
+ }
+
+ fileBrowser->setPath(path);
+ CONNECT(fileBrowser, fileSelectNotifier, this, &DGWindow::selectMapFile);
+ fileBrowser->show();
+}
+
+void DGWindow::selectKitFile(const std::string& filename)
+{
+ lineedit->setText(filename);
+
+ fileBrowser->hide();
+
+ std::string drumkit = lineedit->text();
+
+ config.lastkit = drumkit;
+ config.save();
+
+ drumkitFileProgress->setProgress(0);
+ drumkitFileProgress->setState(ProgressBarState::Blue);
+
+ LoadDrumKitMessage *msg = new LoadDrumKitMessage();
+ msg->drumkitfile = drumkit;
+
+ messageHandler.sendMessage(MSGRCV_ENGINE, msg);
+}
+
+void DGWindow::selectMapFile(const std::string& filename)
+{
+ lineedit2->setText(filename);
+ fileBrowser->hide();
+
+ std::string midimap = lineedit2->text();
+
+ config.lastmidimap = midimap;
+ config.save();
+
+ LoadMidimapMessage *msg = new LoadMidimapMessage();
+ msg->midimapfile = midimap;
+ messageHandler.sendMessage(MSGRCV_ENGINE, msg);
+}
+
+
+} // GUI::
diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h
new file mode 100644
index 0000000..6eb4226
--- /dev/null
+++ b/plugingui/dgwindow.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * dgwindow.h
+ *
+ * Mon Nov 23 20:30:45 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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.
+ */
+#pragma once
+
+#include "window.h"
+
+#include "label.h"
+#include "lineedit.h"
+#include "checkbox.h"
+#include "button.h"
+#include "knob.h"
+#include "progressbar.h"
+#include "filebrowser.h"
+#include "layout.h"
+
+class MessageHandler;
+
+namespace GUI {
+
+class Config;
+class Header;
+class File;
+
+class DGWindow : public Window {
+public:
+ DGWindow(MessageHandler& messageHandler, Config& config);
+
+ Header* header;
+
+ File* drumkitFile;
+ LineEdit* lineedit;
+ ProgressBar* drumkitFileProgress;
+
+ File* midimapFile;
+ LineEdit* lineedit2;
+ ProgressBar* midimapFileProgress;
+
+ // Humanized velocity controls:
+ CheckBox* velocityCheck;
+ Knob* attackKnob;
+ Knob* falloffKnob;
+ FileBrowser* fileBrowser;
+
+protected:
+ // From Widget:
+ void repaintEvent(RepaintEvent* repaintEvent) override;
+
+private:
+ void attackValueChanged(float value);
+ void falloffValueChanged(float value);
+ void velocityCheckClick(bool checked);
+ void kitBrowseClick();
+ void midimapBrowseClick();
+ void selectKitFile(const std::string& filename);
+ void selectMapFile(const std::string& filename);
+
+ MessageHandler& messageHandler;
+ Config& config;
+
+ VBoxLayout layout{this};
+
+ Image back{":bg.png"};
+ Image logo{":logo.png"};
+};
+
+} // GUI::
diff --git a/plugingui/directory.cc b/plugingui/directory.cc
index 1465c86..08bf59a 100644
--- a/plugingui/directory.cc
+++ b/plugingui/directory.cc
@@ -28,7 +28,7 @@
#include <dirent.h>
#include <stdio.h>
-#include <string>
+#include <string>
#include <algorithm>
#include <vector>
#include <string.h>
@@ -44,14 +44,16 @@
// http://en.wikipedia.org/wiki/Path_(computing)
#ifdef WIN32
- #define SEP "\\"
+#define SEP "\\"
#else
- #define SEP "/"
+#define SEP "/"
#endif
+namespace GUI {
+
Directory::Directory(std::string path)
{
- setPath(path);
+ setPath(path);
}
Directory::~Directory()
@@ -60,384 +62,507 @@ Directory::~Directory()
std::string Directory::seperator()
{
- return SEP;
+ return SEP;
}
void Directory::setPath(std::string path)
{
- DEBUG(directory, "Setting path to '%s'\n", path.c_str());
- this->_path = cleanPath(path);
- refresh();
+ //DEBUG(directory, "Setting path to '%s'\n", path.c_str());
+ this->_path = cleanPath(path);
+ refresh();
}
size_t Directory::count()
{
- return _files.size();
+ return _files.size();
}
void Directory::refresh()
{
- _files = listFiles(_path, DIRECTORY_HIDDEN);
-// _files = listFiles(_path);
+ _files = listFiles(_path, DIRECTORY_HIDDEN);
+ //_files = listFiles(_path);
}
bool Directory::cd(std::string dir)
{
- //TODO: Should this return true or false?
- if(dir.empty() || dir == ".") return true;
-
- DEBUG(directory, "Changing to '%s'\n", dir.c_str());
- if(exists(_path + SEP + dir)) {
- std::string path = _path + SEP + dir;
- setPath(path);
- refresh();
- return true;
- } else {
- return false;
- }
+ //TODO: Should this return true or false?
+ if(dir.empty() || dir == ".")
+ {
+ return true;
+ }
+
+ //DEBUG(directory, "Changing to '%s'\n", dir.c_str());
+ if(exists(_path + SEP + dir))
+ {
+ std::string path = _path + SEP + dir;
+ setPath(path);
+ refresh();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
bool Directory::cdUp()
{
- return this->cd("..");
+ return this->cd("..");
}
std::string Directory::path()
{
- return cleanPath(_path);
+ return cleanPath(_path);
}
Directory::EntryList Directory::entryList()
{
- return _files;
+ return _files;
}
#define MAX_FILE_LENGTH 1024
-std::string Directory::cwd() {
- char path[MAX_FILE_LENGTH];
- char* c = getcwd(path, MAX_FILE_LENGTH);
-
- if(c) return c;
- else return "";
+std::string Directory::cwd()
+{
+ char path[MAX_FILE_LENGTH];
+ char* c = getcwd(path, MAX_FILE_LENGTH);
+
+ if(c)
+ {
+ return c;
+ }
+ else
+ {
+ return "";
+ }
}
std::string Directory::cleanPath(std::string path)
{
- DEBUG(directory, "Cleaning path '%s'\n", path.c_str());
-
- Directory::Path pathlst = parsePath(path);
- return Directory::pathToStr(pathlst);
+ //DEBUG(directory, "Cleaning path '%s'\n", path.c_str());
+ Directory::Path pathlst = parsePath(path);
+ return Directory::pathToStr(pathlst);
}
Directory::EntryList Directory::listFiles(std::string path, unsigned char filter)
{
- DEBUG(directory, "Listing files in '%s'\n", path.c_str());
-
- Directory::EntryList entries;
- DIR *dir = opendir(path.c_str());
- if(!dir) {
- DEBUG(directory, "Couldn't open directory '%s\n", path.c_str());
- return entries;
- }
-
- std::vector<std::string> directories;
- std::vector<std::string> files;
-
- struct dirent *entry;
- while((entry = readdir(dir)) != NULL) {
- std::string name = entry->d_name;
- if(name == ".") continue;
-
- if(Directory::isRoot(path) && name == "..") continue;
-
- unsigned char entryinfo = 0;
- if(isHidden(path + SEP + name)) {
- entryinfo |= DIRECTORY_HIDDEN;
- }
-
- std::string entrypath = path;
- entrypath += SEP;
- entrypath += entry->d_name;
- if(Directory::isDir(entrypath)) {
- if(!(entryinfo && filter)) {
- if(name == "..") directories.push_back(entry->d_name);
- else directories.push_back(std::string(SEP) + entry->d_name);
- }
- }
- else {
- int drumkit_suffix_length = strlen(DRUMKIT_SUFFIX);
- if((int)name.size() < drumkit_suffix_length) continue;
- if(name.substr(name.length() - drumkit_suffix_length,
- drumkit_suffix_length) != DRUMKIT_SUFFIX) {
- continue;
- }
-
-
-// if(!(entryinfo && filter)) {
- files.push_back(entry->d_name);
-// }
- }
- }
-
+ DEBUG(directory, "Listing files in '%s'\n", path.c_str());
+
+ Directory::EntryList entries;
+ DIR *dir = opendir(path.c_str());
+ if(!dir)
+ {
+ //DEBUG(directory, "Couldn't open directory '%s\n", path.c_str());
+ return entries;
+ }
+
+ std::vector<std::string> directories;
+ std::vector<std::string> files;
+
+ struct dirent *entry;
+ while((entry = readdir(dir)) != nullptr)
+ {
+ std::string name = entry->d_name;
+ if(name == ".")
+ {
+ continue;
+ }
+
+ if(Directory::isRoot(path) && name == "..")
+ {
+ continue;
+ }
+
+ unsigned char entryinfo = 0;
+ if(isHidden(path + SEP + name))
+ {
+ entryinfo |= DIRECTORY_HIDDEN;
+ }
+
+ std::string entrypath = path;
+ entrypath += SEP;
+ entrypath += entry->d_name;
+ if(Directory::isDir(entrypath))
+ {
+ if(!(entryinfo && filter))
+ {
+ if(name == "..")
+ {
+ directories.push_back(entry->d_name);
+ }
+ else
+ {
+ directories.push_back(std::string(SEP) + entry->d_name);
+ }
+ }
+ }
+ else
+ {
+ int drumkit_suffix_length = strlen(DRUMKIT_SUFFIX);
+ if((int)name.size() < drumkit_suffix_length)
+ {
+ continue;
+ }
+
+ if(name.substr(name.length() - drumkit_suffix_length,
+ drumkit_suffix_length) != DRUMKIT_SUFFIX)
+ {
+ continue;
+ }
+
+
+ //if(!(entryinfo && filter)) {
+ files.push_back(entry->d_name);
+ //}
+ }
+ }
#ifdef WIN32
- DEBUG(directory, "Root is %s\n", Directory::root(path).c_str());
- DEBUG(directory, "Current path %s is root? %d", path.c_str(), Directory::isRoot(path));
-if(Directory::isRoot(path)) entries.push_back("..");
+ //DEBUG(directory, "Root is %s\n", Directory::root(path).c_str());
+ //DEBUG(directory, "Current path %s is root? %d", path.c_str(),
+ // Directory::isRoot(path));
+ if(Directory::isRoot(path))
+ {
+ entries.push_back("..");
+ }
#endif
- // sort
- for(int x = 0; x < (int)directories.size(); x++) {
- for(int y = 0; y < (int)directories.size(); y++) {
- if(directories[x] < directories[y]) {
-
- std::string tmp = directories[x];
- directories[x] = directories[y];
- directories[y] = tmp;
- }
- }
- }
-
- for(int x = 0; x < (int)files.size(); x++) {
- for(int y = 0; y < (int)files.size(); y++) {
- if(files[x] < files[y]) {
-
- std::string tmp = files[x];
- files[x] = files[y];
- files[y] = tmp;
- }
- }
- }
-
-
- for(std::vector<std::string>::iterator it = directories.begin(); it != directories.end(); it++) {
- entries.push_back(*it);
- }
-
- for(std::vector<std::string>::iterator it = files.begin(); it != files.end(); it++) {
- entries.push_back(*it);
- }
-
-
- return entries;
+ // sort
+ for(int x = 0; x < (int)directories.size(); x++)
+ {
+ for(int y = 0; y < (int)directories.size(); y++)
+ {
+ if(directories[x] < directories[y])
+ {
+ std::string tmp = directories[x];
+ directories[x] = directories[y];
+ directories[y] = tmp;
+ }
+ }
+ }
+
+ for(int x = 0; x < (int)files.size(); x++)
+ {
+ for(int y = 0; y < (int)files.size(); y++)
+ {
+ if(files[x] < files[y])
+ {
+ std::string tmp = files[x];
+ files[x] = files[y];
+ files[y] = tmp;
+ }
+ }
+ }
+
+
+ for(auto directory : directories)
+ {
+ entries.push_back(directory);
+ }
+
+ for(auto file : files)
+ {
+ entries.push_back(file);
+ }
+
+ closedir(dir);
+ return entries;
}
bool Directory::isRoot(std::string path)
{
#ifdef WIN32
- std::transform(path.begin(), path.end(), path.begin(), ::tolower);
- std::string root_str = Directory::root(path);
- std::transform(root_str.begin(), root_str.end(), root_str.begin(), ::tolower);
- // TODO: This is not a correct root calculation, but works with partitions
- if(path.size() == 2) {
- if(path == root_str) return true;
- else return false;
- } else if (path.size() == 3) {
- if(path == root_str + SEP) return true;
- return false;
- } else {
- return false;
- }
+ std::transform(path.begin(), path.end(), path.begin(), ::tolower);
+ std::string root_str = Directory::root(path);
+ std::transform(root_str.begin(), root_str.end(), root_str.begin(), ::tolower);
+
+ // TODO: This is not a correct root calculation, but works with partitions
+ if(path.size() == 2)
+ {
+ if(path == root_str)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (path.size() == 3)
+ {
+ if(path == root_str + SEP)
+ {
+ return true;
+ }
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
#else
- if(path == SEP) return true;
- else return false;
+ if(path == SEP)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
#endif
}
std::string Directory::root()
{
- return root(cwd());
+ return root(cwd());
}
std::string Directory::root(std::string path)
{
#ifdef WIN32
- if(path.size() < 2) {
- return "c:"; // just something default when input is bad
- } else {
- return path.substr(0, 2);
- }
+ if(path.size() < 2)
+ {
+ return "c:"; // just something default when input is bad
+ }
+ else
+ {
+ return path.substr(0, 2);
+ }
#else
- return SEP;
+ return SEP;
#endif
}
Directory::DriveList Directory::drives()
{
- Directory::DriveList drives;
+ Directory::DriveList drives;
#ifdef WIN32
- unsigned int d = GetLogicalDrives();
- for(int i = 0; i < 32; i++) {
- if(d & (1 << i)) {
- drive_t drive;
- char name[] = "x:";
- name[0] = i + 'a';
-
- drive.name = name;
- drive.number = i;
- drives.push_back(drive);
- }
- }
+ unsigned int d = GetLogicalDrives();
+ for(int i = 0; i < 32; ++i)
+ {
+ if(d & (1 << i))
+ {
+ drive_t drive;
+ char name[] = "x:";
+ name[0] = i + 'a';
+
+ drive.name = name;
+ drive.number = i;
+ drives.push_back(drive);
+ }
+ }
#endif
- return drives;
+ return drives;
}
bool Directory::isDir()
{
- return isDir(_path);
+ return isDir(_path);
}
bool Directory::isDir(std::string path)
{
- DEBUG(directory, "Is '%s' a directory?\n", path.c_str());
- struct stat st;
- if(stat(path.c_str(), &st) == 0) {
- if((st.st_mode & S_IFDIR) != 0) {
- DEBUG(directory, "\t...yes!\n");
- return true;
- }
- }
- DEBUG(directory, "\t...no!\n");
- return false;
+ //DEBUG(directory, "Is '%s' a directory?\n", path.c_str());
+ struct stat st;
+ if(stat(path.c_str(), &st) == 0)
+ {
+ if((st.st_mode & S_IFDIR) != 0)
+ {
+ //DEBUG(directory, "\t...yes!\n");
+ return true;
+ }
+ }
+ //DEBUG(directory, "\t...no!\n");
+ return false;
}
bool Directory::fileExists(std::string filename)
{
- return !isDir(_path + SEP + filename);
+ return !isDir(_path + SEP + filename);
}
bool Directory::exists(std::string path)
{
- struct stat st;
- if(stat(path.c_str(), &st) == 0) {
- return true;
- } else {
- return false;
- }
+ struct stat st;
+ if(stat(path.c_str(), &st) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
-bool Directory::isHidden(std::string path)
+bool Directory::isHidden(std::string path)
{
- DEBUG(directory, "Is '%s' hidden?\n", path.c_str());
+ //DEBUG(directory, "Is '%s' hidden?\n", path.c_str());
#ifdef WIN32
- // We dont want to filter out '..' pointing to root of a partition
- unsigned pos = path.find_last_of("/\\");
- std::string entry = path.substr(pos+1);
- if(entry == "..") {
- return false;
- }
-
- DWORD fattribs = GetFileAttributes(path.c_str());
- if(fattribs & FILE_ATTRIBUTE_HIDDEN) {
- DEBUG(directory, "\t...yes!\n");
- return true;
- }
- else if(fattribs & FILE_ATTRIBUTE_SYSTEM) {
- DEBUG(directory, "\t...yes!\n");
- return true;
- }
- else {
- DEBUG(directory, "\t...no!\n");
- return false;
- }
+ // We dont want to filter out '..' pointing to root of a partition
+ unsigned pos = path.find_last_of("/\\");
+ std::string entry = path.substr(pos+1);
+ if(entry == "..")
+ {
+ return false;
+ }
+
+ DWORD fattribs = GetFileAttributes(path.c_str());
+ if(fattribs & FILE_ATTRIBUTE_HIDDEN)
+ {
+ //DEBUG(directory, "\t...yes!\n");
+ return true;
+ }
+ else
+ {
+ if(fattribs & FILE_ATTRIBUTE_SYSTEM)
+ {
+ //DEBUG(directory, "\t...yes!\n");
+ return true;
+ }
+ else
+ {
+ //DEBUG(directory, "\t...no!\n");
+ return false;
+ }
+ }
#else
- unsigned pos = path.find_last_of("/\\");
- std::string entry = path.substr(pos+1);
- if(entry.size() > 1 &&
- entry.at(0) == '.' &&
- entry.at(1) != '.') {
- DEBUG(directory, "\t...yes!\n");
- return true;
- }
- else {
- DEBUG(directory, "\t...no!\n");
- return false;
- }
+ unsigned pos = path.find_last_of("/\\");
+ std::string entry = path.substr(pos+1);
+ if(entry.size() > 1 &&
+ entry.at(0) == '.' &&
+ entry.at(1) != '.')
+ {
+ //DEBUG(directory, "\t...yes!\n");
+ return true;
+ }
+ else
+ {
+ //DEBUG(directory, "\t...no!\n");
+ return false;
+ }
#endif
}
Directory::Path Directory::parsePath(std::string path_str)
{
- //TODO: Handle "." input and propably other special cases
-
- DEBUG(directory, "Parsing path '%s'", path_str.c_str());
- Directory::Path path;
-
- std::string current_char;
- std::string prev_char;
- std::string dir;
- for(size_t c = 0; c < path_str.size(); c++) {
- current_char = path_str.at(c);
-
- if(current_char == SEP) {
- if(prev_char == SEP) {
- dir.clear();
- prev_char = current_char;
- continue;
- } else if(prev_char == ".") {
- prev_char = current_char;
- continue;
- }
-
- if(!dir.empty()) path.push_back(dir);
- dir.clear();
- continue;
- } else if(current_char == ".") {
- if(prev_char == ".") {
- dir.clear();
- if(!path.empty()) path.pop_back();
- continue;
- }
- }
-
- dir += current_char;
- prev_char = current_char;
- }
-
- if(!dir.empty()) path.push_back(dir);
-
- return path;
+ //TODO: Handle "." input and propably other special cases
+
+ //DEBUG(directory, "Parsing path '%s'", path_str.c_str());
+ Directory::Path path;
+
+ std::string current_char;
+ std::string prev_char;
+ std::string dir;
+ for(size_t c = 0; c < path_str.size(); ++c)
+ {
+ current_char = path_str.at(c);
+
+ if(current_char == SEP)
+ {
+ if(prev_char == SEP)
+ {
+ dir.clear();
+ prev_char = current_char;
+ continue;
+ }
+ else
+ {
+ if(prev_char == ".")
+ {
+ prev_char = current_char;
+ continue;
+ }
+ }
+ if(!dir.empty())
+ {
+ path.push_back(dir);
+ }
+ dir.clear();
+ continue;
+ }
+ else
+ {
+ if(current_char == ".")
+ {
+ if(prev_char == ".")
+ {
+ dir.clear();
+ if(!path.empty())
+ {
+ path.pop_back();
+ }
+ continue;
+ }
+ }
+ }
+ dir += current_char;
+ prev_char = current_char;
+ }
+
+ if(!dir.empty())
+ {
+ path.push_back(dir);
+ }
+
+ return path;
}
std::string Directory::pathToStr(Directory::Path& path)
{
- std::string cleaned_path;
- DEBUG(directory, "Number of directories in path is %d\n", (int)path.size());
+ std::string cleaned_path;
+ //DEBUG(directory, "Number of directories in path is %d\n", (int)path.size());
- for(Directory::Path::iterator it = path.begin();
- it != path.end(); it++) {
- std::string dir = *it;
- DEBUG(directory, "\tDir '%s'\n", dir.c_str());
+ for(auto it = path.begin(); it != path.end(); ++it)
+ {
+ std::string dir = *it;
+ //DEBUG(directory, "\tDir '%s'\n", dir.c_str());
#ifdef WIN32
- if(it != path.begin()) cleaned_path += SEP;
- cleaned_path += dir;
+ if(it != path.begin())
+ {
+ cleaned_path += SEP;
+ }
+ cleaned_path += dir;
#else
- cleaned_path += SEP + dir;
+ cleaned_path += SEP + dir;
#endif
- }
+ }
- DEBUG(directory, "Cleaned path '%s'\n", cleaned_path.c_str());
+ //DEBUG(directory, "Cleaned path '%s'\n", cleaned_path.c_str());
- if(cleaned_path.empty()) {
- cleaned_path = Directory::root();
+ if(cleaned_path.empty())
+ {
+ cleaned_path = Directory::root();
#ifdef WIN32
- cleaned_path += SEP;
-#endif
- }
+ cleaned_path += SEP;
+#endif
+ }
#ifdef WIN32
- if(cleaned_path.size() == 2) cleaned_path += SEP;
+ if(cleaned_path.size() == 2)
+ {
+ cleaned_path += SEP;
+ }
#endif
- return cleaned_path;
+ return cleaned_path;
}
std::string Directory::pathDirectory(std::string filepath)
{
- if(Directory::isDir(filepath)) return filepath;
-
- Directory::Path path = parsePath(filepath);
- if(path.size() > 0) path.pop_back();
-
- return Directory::pathToStr(path);
+ if(Directory::isDir(filepath))
+ {
+ return filepath;
+ }
+
+ Directory::Path path = parsePath(filepath);
+ if(path.size() > 0)
+ {
+ path.pop_back();
+ }
+
+ return Directory::pathToStr(path);
}
+
+} // GUI::
diff --git a/plugingui/directory.h b/plugingui/directory.h
index 04ed3e7..a3f0059 100644
--- a/plugingui/directory.h
+++ b/plugingui/directory.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_DIRECTORY_H__
-#define __DRUMGIZMO_DIRECTORY_H__
+#pragma once
#include <string>
#include <list>
@@ -38,56 +37,57 @@
#define DIRECTORY_HIDDEN 1
+namespace GUI {
+
class Directory {
+public:
+ typedef struct drive {
+ int number;
+ std::string name;
+ } drive_t;
+
+ typedef std::list<std::string> EntryList;
+ typedef std::list<drive> DriveList;
+
+ Directory(std::string path);
+ ~Directory();
+
+ std::string seperator();
+
+ size_t count();
+ void refresh();
+ std::string path();
+ bool cdUp();
+ bool cd(std::string dir);
+ bool isDir();
+ void setPath(std::string path);
+ bool fileExists(std::string file);
+
+ // Add filter, ie. directories or files only
+ EntryList entryList();
+
+ //void setSorting();
+
+ static std::string cwd();
+ static std::string root();
+ static std::string root(std::string path);
+ static std::string cleanPath(std::string path);
+ static Directory::EntryList listFiles(std::string path, unsigned char filter = 0);
+ static bool isRoot(std::string path);
+ static Directory::DriveList drives();
+ static bool isDir(std::string path);
+ static bool isHidden(std::string entry);
+ static bool exists(std::string path);
+ static std::string pathDirectory(std::string filepath);
+
+private:
+ std::string _path;
+ EntryList _files;
+ DriveList _drives;
- public:
- typedef struct drive {
- int number;
- std::string name;
- } drive_t;
-
- typedef std::list<std::string> EntryList;
- typedef std::list<drive> DriveList;
-
- Directory(std::string path);
- ~Directory();
-
- std::string seperator();
-
- size_t count();
- void refresh();
- std::string path();
- bool cdUp();
- bool cd(std::string dir);
- bool isDir();
- void setPath(std::string path);
- bool fileExists(std::string file);
-
- // Add filter, ie. directories or files only
- EntryList entryList();
-
- //void setSorting();
-
- static std::string cwd();
- static std::string root();
- static std::string root(std::string path);
- static std::string cleanPath(std::string path);
- static Directory::EntryList listFiles(std::string path, unsigned char filter = 0);
- static bool isRoot(std::string path);
- static Directory::DriveList drives();
- static bool isDir(std::string path);
- static bool isHidden(std::string entry);
- static bool exists(std::string path);
- static std::string pathDirectory(std::string filepath);
-
- private:
- std::string _path;
- EntryList _files;
- DriveList _drives;
-
- typedef std::list<std::string> Path;
- static Path parsePath(std::string path);
- static std::string pathToStr(Path &path);
+ typedef std::list<std::string> Path;
+ static Path parsePath(std::string path);
+ static std::string pathToStr(Path &path);
};
-#endif/*__DRUMGIZMO_DIRECTORY_H__*/
+} // GUI::
diff --git a/plugingui/eventhandler.cc b/plugingui/eventhandler.cc
index cec5fab..9a6fa8d 100644
--- a/plugingui/eventhandler.cc
+++ b/plugingui/eventhandler.cc
@@ -29,166 +29,237 @@
#include "window.h"
#include "painter.h"
-GUI::EventHandler::EventHandler(GUI::NativeWindow *n, GUI::Window *w)
-{
- native = n;
- window = w;
+namespace GUI {
- last_click = 0;
- last_was_dbl_click = false;
-}
+EventHandler::EventHandler(NativeWindow& nativeWindow, Window& window)
+ : window(window)
+ , nativeWindow(nativeWindow)
+// , last_click(0)
+ , lastWasDoubleClick(false)
+{}
-bool GUI::EventHandler::hasEvent()
+bool EventHandler::hasEvent()
{
- return native->hasEvent();
+ return nativeWindow.hasEvent();
}
-GUI::Event *GUI::EventHandler::getNextEvent()
+Event *EventHandler::getNextEvent()
{
- return native->getNextEvent();
+ return nativeWindow.getNextEvent();
}
-void GUI::EventHandler::registerCloseHandler(void (*handler)(void *), void *ptr)
+Event *EventHandler::peekNextEvent()
{
- this->closeHandler = handler;
- this->closeHandlerPtr = ptr;
+ return nativeWindow.peekNextEvent();
}
-void GUI::EventHandler::processEvents()
+void EventHandler::processEvents()
{
- while(hasEvent()) {
- Painter p(window); // Make sure we only redraw buffer one time.
-
- Event *event = getNextEvent();
-
- if(event == NULL) continue;
-
- // Widget *widget = gctx->widgets[event->window_id];
- switch(event->type()) {
- case Event::Repaint:
- // window->repaint((RepaintEvent*)event);
- window->redraw();
- break;
- case Event::Resize:
- {
- // window->repaint((RepaintEvent*)event)
- ResizeEvent *re = (ResizeEvent*)event;
- if(re->width != window->width() || re->height != window->height()) {
- window->resized(re->width, re->height);
- //window->repaint_r(NULL);
- }
- }
- break;
- case Event::MouseMove:
- {
- MouseMoveEvent *me = (MouseMoveEvent*)event;
-
- Widget *w = window->find(me->x, me->y);
- Widget *oldw = window->mouseFocus();
- if(w != oldw) {
- // Send focus leave to oldw
- if(oldw) oldw->mouseLeaveEvent();
- // Send focus enter to w
- if(w) w->mouseEnterEvent();
-
- window->setMouseFocus(w);
- }
-
- if(window->buttonDownFocus()) {
- Widget *w = window->buttonDownFocus();
- /*
- if(me->x < w->x()) me->x = w->x();
- if(me->x > w->x() + w->width()) me->x = w->x() + w->width();
- if(me->y < w->y()) me->y = w->y();
- if(me->y > w->y() + w->height()) me->y = w->y() + w->height();
- */
- me->x -= w->windowX();
- me->y -= w->windowY();
-
- window->buttonDownFocus()->mouseMoveEvent(me);
- break;
- }
-
- if(w) {
- me->x -= w->windowX();
- me->y -= w->windowY();
- w->mouseMoveEvent(me);
- }
- }
- break;
- case Event::Button:
- {
- if(last_was_dbl_click) {
- last_was_dbl_click = false;
- continue;
- }
- ButtonEvent *be = (ButtonEvent *)event;
-
- last_was_dbl_click = be->doubleclick;
-
- Widget *w = window->find(be->x, be->y);
-
- if(window->buttonDownFocus()) {
- if(be->direction == -1) {
- Widget *w = window->buttonDownFocus();
- /*
- if(be->x < w->x()) be->x = w->x();
- if(be->x > w->x() + w->width()) be->x = w->x() + w->width();
- if(be->y < w->y()) be->y = w->y();
- if(be->y > w->y() + w->height()) be->y = w->y() + w->height();
- */
- be->x -= w->windowX();
- be->y -= w->windowY();
-
- w->buttonEvent(be);
- break;
- } else {
- window->setButtonDownFocus(NULL);
- }
- }
-
- if(w) {
- be->x -= w->windowX();
- be->y -= w->windowY();
-
- w->buttonEvent(be);
-
- if(be->direction == 1) {
- if(w->catchMouse()) window->setButtonDownFocus(w);
- }
-
- if(w->isFocusable()) window->setKeyboardFocus(w);
- }
- }
- break;
- case Event::Scroll:
- {
- ScrollEvent *se = (ScrollEvent *)event;
-
- Widget *w = window->find(se->x, se->y);
-
- //printf("scroller (%d,%d) %p\n", se->x, se->y, w);
-
- if(w) {
- se->x -= w->windowX();
- se->y -= w->windowY();
-
- w->scrollEvent(se);
- }
- }
- break;
- case Event::Key:
- // window->key((KeyEvent*)event);
- // lineedit->keyEvent((KeyEvent*)event);
- if(window->keyboardFocus())
- window->keyboardFocus()->keyEvent((KeyEvent*)event);
- break;
- case Event::Close:
- if(closeHandler) closeHandler(closeHandlerPtr);
- //delete window;
- //window = NULL;
- break;
- }
- delete event;
- }
+ while(hasEvent())
+ {
+ Painter p(window); // Make sure we only redraw buffer one time.
+
+ auto event = getNextEvent();
+
+ if(event == nullptr)
+ {
+ continue;
+ }
+
+ switch(event->type()) {
+ case EventType::repaint:
+ window.redraw();
+ break;
+
+ case EventType::resize:
+ {
+ while(true)
+ {
+ if(!hasEvent())
+ {
+ break;
+ }
+
+ auto peekEvent = peekNextEvent();
+ if(!peekEvent || (peekEvent->type() != EventType::resize))
+ {
+ break;
+ }
+
+ event = getNextEvent();
+ }
+
+ auto resizeEvent = static_cast<ResizeEvent*>(event);
+ if((resizeEvent->width != window.width()) ||
+ (resizeEvent->height != window.height()))
+ {
+ window.resized(resizeEvent->width, resizeEvent->height);
+ }
+ }
+ break;
+
+ case EventType::mouseMove:
+ {
+ while(true)
+ {
+ if(!hasEvent())
+ {
+ break;
+ }
+
+ auto peekEvent = peekNextEvent();
+ if(!peekEvent || (peekEvent->type() != EventType::mouseMove))
+ {
+ break;
+ }
+
+ event = getNextEvent();
+ }
+
+ auto moveEvent = static_cast<MouseMoveEvent*>(event);
+
+ 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->windowX();
+ moveEvent->y -= widget->windowY();
+
+ window.buttonDownFocus()->mouseMoveEvent(moveEvent);
+ break;
+ }
+
+ if(widget)
+ {
+ moveEvent->x -= widget->windowX();
+ moveEvent->y -= widget->windowY();
+ widget->mouseMoveEvent(moveEvent);
+ }
+ }
+ break;
+
+ case EventType::button:
+ {
+ if(lastWasDoubleClick)
+ {
+ lastWasDoubleClick = false;
+ continue;
+ }
+
+ auto buttonEvent = static_cast<ButtonEvent*>(event);
+
+ 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->windowX();
+ buttonEvent->y -= widget->windowY();
+
+ widget->buttonEvent(buttonEvent);
+ window.setButtonDownFocus(nullptr);
+ break;
+ }
+ }
+
+ if(widget)
+ {
+ buttonEvent->x -= widget->windowX();
+ buttonEvent->y -= widget->windowY();
+
+ widget->buttonEvent(buttonEvent);
+
+ if((buttonEvent->direction == Direction::down) &&
+ widget->catchMouse())
+ {
+ window.setButtonDownFocus(widget);
+ }
+
+ if(widget->isFocusable())
+ {
+ window.setKeyboardFocus(widget);
+ }
+ }
+ }
+ break;
+
+ case EventType::scroll:
+ {
+ int delta = 0;
+ while(true)
+ {
+ if(!hasEvent())
+ {
+ break;
+ }
+
+ auto peekEvent = peekNextEvent();
+ if(!peekEvent || (peekEvent->type() != EventType::scroll))
+ {
+ break;
+ }
+
+ auto scrollEvent = static_cast<ScrollEvent*>(event);
+ delta += scrollEvent->delta;
+ event = getNextEvent();
+ }
+
+ auto scrollEvent = static_cast<ScrollEvent*>(event);
+ scrollEvent->delta += delta;
+
+ auto widget = window.find(scrollEvent->x, scrollEvent->y);
+ if(widget)
+ {
+ scrollEvent->x -= widget->windowX();
+ scrollEvent->y -= widget->windowY();
+
+ widget->scrollEvent(scrollEvent);
+ }
+ }
+ break;
+
+ case EventType::key:
+ {
+
+ // TODO: Filter out multiple arrow events.
+
+ auto keyEvent = static_cast<KeyEvent*>(event);
+ if(window.keyboardFocus())
+ {
+ window.keyboardFocus()->keyEvent(keyEvent);
+ }
+ }
+ break;
+
+ case EventType::close:
+ closeNotifier();
+ break;
+ }
+
+ delete event;
+ }
}
+
+} // GUI::
diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h
index 028418d..b011f87 100644
--- a/plugingui/eventhandler.h
+++ b/plugingui/eventhandler.h
@@ -24,39 +24,42 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_EVENTHANDLER_H__
-#define __DRUMGIZMO_EVENTHANDLER_H__
+#pragma once
#include "guievent.h"
#include "nativewindow.h"
-//#include "window.h"
+#include "notifier.h"
namespace GUI {
+
class Window;
class EventHandler {
public:
- EventHandler(NativeWindow *native, Window *window);
+ EventHandler(NativeWindow& nativeWindow, Window& window);
- void processEvents();
+ //! \brief Process all events currently in the event queue.
+ void processEvents();
- bool hasEvent();
- Event *getNextEvent();
+ //! \brief Query if any events are currently in the event queue.
+ bool hasEvent();
- void registerCloseHandler(void (*handler)(void *), void *ptr);
+ //! \brief Get a single event from the event queue.
+ //! \return A pointer to the event or nullptr if there are none.
+ Event *getNextEvent();
-private:
- Window *window;
- int last_click;
- void (*closeHandler)(void *);
- void *closeHandlerPtr;
+ //! \brief Get a single event from the event queue without popping it.
+ //! \return A pointer to the event or nullptr if there are none.
+ Event *peekNextEvent();
- // Used to ignore mouse button release after a double click.
- bool last_was_dbl_click;
+ Notifier<> closeNotifier;
- NativeWindow *native;
-};
+private:
+ Window& window;
+ NativeWindow& nativeWindow;
+ // Used to ignore mouse button release after a double click.
+ bool lastWasDoubleClick;
};
-#endif/*__DRUMGIZMO_EVENTHANDLER_H__*/
+} // GUI::
diff --git a/plugingui/filebrowser.cc b/plugingui/filebrowser.cc
index f025c25..6313415 100644
--- a/plugingui/filebrowser.cc
+++ b/plugingui/filebrowser.cc
@@ -45,224 +45,216 @@
#include <direct.h>
#endif
-struct GUI::FileBrowser::private_data {
- GUI::LineEdit *lineedit;
- GUI::ListBox *listbox;
- void (*filesel_handler)(void *, std::string);
- void *ptr;
- Directory *dir;
+namespace GUI {
+
+FileBrowser::FileBrowser(Widget *parent)
+ : Widget(parent)
+ , dir(Directory::cwd())
+ , lbl_path(this)
+ , lineedit(this)
+ , listbox(this)
+ , btn_sel(this)
+ , btn_esc(this)
+ , back(":bg.png")
+{
#ifdef WIN32
- bool above_root;
- bool in_root;
+ above_root = false;
#endif
-};
-static void cancel(void *ptr)
-{
- GUI::FileBrowser *fp = (GUI::FileBrowser *)ptr;
- fp->hide();
-}
-
-static void changeDir(void *ptr)
-{
- struct GUI::FileBrowser::private_data *prv =
- (struct GUI::FileBrowser::private_data *) ptr;
-
- GUI::ListBox *lb = prv->listbox;
- GUI::LineEdit *le = prv->lineedit;
- std::string value = lb->selectedValue();
- Directory* dir = prv->dir;
-
-// if(!Directory::isDir(dir->path() + dir->seperator())) {
-// return;
-// }
+ lbl_path.setText("Path:");
- lb->clear();
-
- INFO(filebrowser, "Changing path to '%s'\n",
- (dir->path() + dir->seperator() + value).c_str());
-
-#ifdef WIN32
- if(prv->above_root && !value.empty()) {
- dir->setPath(value + dir->seperator());
- value.clear();
- prv->above_root = false;
- }
-#endif
+ //lineedit.setReadOnly(true);
+ CONNECT(&lineedit, enterPressedNotifier, this, &FileBrowser::handleKeyEvent);
+ CONNECT(&listbox, selectionNotifier,
+ this, &FileBrowser::listSelectionChanged);
- if(value.empty() && !dir->isDir() && Directory::exists(dir->path())) {
- DEBUG(filebrowser, "Selecting file '%s'\n", dir->path().c_str());
- if(prv->filesel_handler) prv->filesel_handler(prv->ptr, dir->path().c_str());
- return;
- }
+ btn_sel.setText("Select");
+ CONNECT(&btn_sel, clickNotifier, this, &FileBrowser::selectButtonClicked);
- if(!value.empty() && dir->fileExists(value)) {
- std::string file = dir->path() + dir->seperator() + value;
- DEBUG(filebrowser, "Selecting file '%s'\n", file.c_str());
- if(prv->filesel_handler) prv->filesel_handler(prv->ptr, file);
- return;
- }
+ btn_esc.setText("Cancel");
+ CONNECT(&btn_esc, clickNotifier, this, &FileBrowser::cancelButtonClicked);
- std::vector<GUI::ListBoxBasic::Item> items;
+ changeDir();
+}
-#ifdef WIN32
- if(Directory::isRoot(dir->path()) && value == "..") {
- DEBUG(filebrowser, "Showing partitions...\n");
- Directory::DriveList entries = dir->drives();
- for(Directory::DriveList::iterator it = entries.begin();
- it != entries.end(); it++) {
- GUI::ListBoxBasic::Item item;
- std::string name = (*it).name;
- item.name = name;
- item.value = name;
- items.push_back(item);
- }
- prv->above_root = true;
- } else {
-#endif
-
- if(!value.empty() && !dir->cd(value)) {
- DEBUG(filebrowser, "Error changing to '%s'\n",
- (dir->path() + dir->seperator() + value).c_str());
- return;
- }
-
- Directory::EntryList entries = dir->entryList();
-
- if(entries.empty()) {
- dir->cdUp();
- entries = dir->entryList();
- }
-
- DEBUG(filebrowser, "Setting path of lineedit to %s\n",
- dir->path().c_str());
- le->setText(dir->path());
-
- for(Directory::EntryList::iterator it = entries.begin();
- it != entries.end(); it++) {
- GUI::ListBoxBasic::Item item;
- std::string name = *it;
- item.name = name;
- item.value = name;
- items.push_back(item);
- }
-#ifdef WIN32
- }
-#endif
- lb->addItems(items);
+FileBrowser::~FileBrowser()
+{
}
-static void handleKeyEvent(void *ptr) {
- struct GUI::FileBrowser::private_data *prv =
- (struct GUI::FileBrowser::private_data *) ptr;
-
- GUI::ListBox *lb = prv->listbox;
- lb->clearSelectedValue();
- GUI::LineEdit *le = prv->lineedit;
-
- std::string value = le->text();
- if(value.size() > 1 && value[0] == '@') {
- DEBUG(filebrowser, "Selecting ref-file '%s'\n", value.c_str());
- if(prv->filesel_handler) {
- prv->filesel_handler(prv->ptr, value);
- }
- return;
- }
-
- prv->dir->setPath(le->text());
- changeDir(ptr);
+void FileBrowser::setPath(const std::string& path)
+{
+ INFO(filebrowser, "Setting path to '%s'\n", path.c_str());
+
+ if(!path.empty())
+ {
+ dir.setPath(Directory::pathDirectory(path));
+ }
+ else
+ {
+ dir.setPath(Directory::pathDirectory(Directory::cwd()));
+ }
+
+ listbox.clear();
+
+ changeDir();
}
-GUI::FileBrowser::FileBrowser(GUI::Widget *parent)
- : GUI::Widget(parent),
- lbl_path(this), lineedit(this), listbox(this), btn_sel(this), btn_esc(this),
- back(":bg.png")
+void FileBrowser::resize(int w, int h)
{
- prv = new struct GUI::FileBrowser::private_data();
- prv->filesel_handler = NULL;
+ Widget::resize(w,h);
- prv->dir = new Directory(Directory::cwd());
-#ifdef WIN32
- prv->above_root = false;
-#endif
+ int offset = 0;
+ int brd = 5; // border
+ int btn_h = 30;
- lbl_path.setText("Path:");
+ offset += brd;
-// lineedit.setReadOnly(true);
- prv->lineedit = &lineedit;
- prv->lineedit->registerEnterPressedHandler(handleKeyEvent, prv);
+ lbl_path.move(0, offset);
+ lineedit.move(60, offset);
- prv->listbox = &listbox;
- listbox.registerSelectHandler(changeDir, prv);
+ offset += btn_h;
- btn_sel.setText("Select");
- btn_sel.registerClickHandler(changeDir, prv);
+ lbl_path.resize(60, btn_h);
+ lineedit.resize(w - 60 - brd, btn_h);
- btn_esc.setText("Cancel");
- btn_esc.registerClickHandler(cancel, this);
+ offset += brd;
- changeDir(prv);
+ listbox.move(brd, offset);
+ listbox.resize(w - 1 - 2*brd, h - btn_h - 2*brd - offset);
- resize(200, 190);
+ btn_esc.move(brd, h - btn_h - brd);
+ btn_esc.resize((w - 1 - 2*brd) / 2 - brd / 2, btn_h);
+
+ btn_sel.move(brd + w / 2 - brd / 2, h - btn_h - brd);
+ btn_sel.resize((w - 1 - 2*brd) / 2, btn_h);
}
-GUI::FileBrowser::~FileBrowser()
+void FileBrowser::repaintEvent(RepaintEvent* repaintEvent)
{
- // delete prv->listbox;
- delete prv;
+ Painter p(*this);
+ p.drawImageStretched(0,0, back, width(), height());
}
-void GUI::FileBrowser::setPath(std::string path)
+void FileBrowser::listSelectionChanged()
{
- INFO(filebrowser, "Setting path to '%s'\n", path.c_str());
- if(path.empty()) path = Directory::cwd();
+ changeDir();
+}
- prv->dir->setPath(Directory::pathDirectory(path));
- prv->listbox->clear();
+void FileBrowser::selectButtonClicked()
+{
+ changeDir();
+}
- changeDir(prv);
+void FileBrowser::cancelButtonClicked()
+{
+ cancel();
}
-void GUI::FileBrowser::resize(int w, int h)
+void FileBrowser::handleKeyEvent()
{
- GUI::Widget::resize(w,h);
+ listbox.clearSelectedValue();
+
+ std::string value = lineedit.text();
+ if((value.size() > 1) && (value[0] == '@'))
+ {
+ DEBUG(filebrowser, "Selecting ref-file '%s'\n", value.c_str());
+ fileSelectNotifier(value);
+ return;
+ }
+
+ dir.setPath(lineedit.text());
+ changeDir();
+}
- int offset = 0;
- int brd = 5; // border
- int btn_h = 30;
+void FileBrowser::cancel()
+{
+ hide();
+}
- offset += brd;
+void FileBrowser::changeDir()
+{
+ std::string value = listbox.selectedValue();
- lbl_path.move(0, offset);
- lineedit.move(60, offset);
+// if(!Directory::isDir(dir->path() + dir->seperator()))
+// {
+// return;
+// }
- offset += btn_h;
+ listbox.clear();
- lbl_path.resize(60, btn_h);
- lineedit.resize(w - 60 - brd, btn_h);
+ INFO(filebrowser, "Changing path to '%s'\n",
+ (dir.path() + dir.seperator() + value).c_str());
- offset += brd;
+#ifdef WIN32
+ if(above_root && !value.empty())
+ {
+ dir.setPath(value + dir.seperator());
+ value.clear();
+ above_root = false;
+ }
+#endif
- listbox.move(brd, offset);
- listbox.resize(w - 1 - 2*brd, h - btn_h - 2*brd - offset);
+ if(value.empty() && !dir.isDir() && Directory::exists(dir.path()))
+ {
+ DEBUG(filebrowser, "Selecting file '%s'\n", dir.path().c_str());
+ fileSelectNotifier(dir.path());
+ return;
+ }
- btn_esc.move(brd, h - btn_h - brd);
- btn_esc.resize((w - 1 - 2*brd) / 2 - brd / 2, btn_h);
+ if(!value.empty() && dir.fileExists(value))
+ {
+ std::string file = dir.path() + dir.seperator() + value;
+ DEBUG(filebrowser, "Selecting file '%s'\n", file.c_str());
+ fileSelectNotifier(file);
+ return;
+ }
- btn_sel.move(brd + w / 2 - brd / 2, h - btn_h - brd);
- btn_sel.resize((w - 1 - 2*brd) / 2, btn_h);
-}
+ std::vector<ListBoxBasic::Item> items;
-void GUI::FileBrowser::registerFileSelectHandler(void (*handler)(void *,
- std::string),
- void *ptr)
-{
- prv->filesel_handler = handler;
- prv->ptr = ptr;
+#ifdef WIN32
+ if(Directory::isRoot(dir.path()) && (value == ".."))
+ {
+ DEBUG(filebrowser, "Showing partitions...\n");
+ for(auto drive : dir.drives())
+ {
+ ListBoxBasic::Item item;
+ item.name = drive.name;
+ item.value = drive.name;
+ items.push_back(item);
+ }
+ above_root = true;
+ }
+ else
+#endif
+ {
+ if(!value.empty() && !dir.cd(value))
+ {
+ DEBUG(filebrowser, "Error changing to '%s'\n",
+ (dir.path() + dir.seperator() + value).c_str());
+ return;
+ }
+
+ Directory::EntryList entries = dir.entryList();
+
+ if(entries.empty())
+ {
+ dir.cdUp();
+ entries = dir.entryList();
+ }
+
+ DEBUG(filebrowser, "Setting path of lineedit to %s\n", dir.path().c_str());
+ lineedit.setText(dir.path());
+
+ for(auto entry : entries)
+ {
+ ListBoxBasic::Item item;
+ item.name = entry;
+ item.value = entry;
+ items.push_back(item);
+ }
+ }
+
+ listbox.addItems(items);
}
-void GUI::FileBrowser::repaintEvent(GUI::RepaintEvent *e)
-{
- Painter p(this);
- p.drawImageStretched(0,0, &back, width(), height());
-}
+} // GUI::
diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h
index 6583b53..bd9dd8e 100644
--- a/plugingui/filebrowser.h
+++ b/plugingui/filebrowser.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_FILEBROWSER_H__
-#define __DRUMGIZMO_FILEBROWSER_H__
+#pragma once
#include "widget.h"
@@ -35,41 +34,48 @@
#include "label.h"
#include "image.h"
#include "directory.h"
+#include "notifier.h"
namespace GUI {
class FileBrowser : public Widget {
public:
- struct private_data;
+ FileBrowser(Widget *parent);
+ ~FileBrowser();
- FileBrowser(Widget *parent);
- ~FileBrowser();
+ void setPath(const std::string& path);
- void setPath(std::string path);
+ Notifier<const std::string&> fileSelectNotifier; // (const std::string& path)
- bool isFocusable() { return true; }
-
- void registerFileSelectHandler(void (*handler)(void *, std::string),
- void *ptr);
-
- virtual void repaintEvent(RepaintEvent *e);
-
- virtual void resize(int w, int h);
+ // From Widget:
+ bool isFocusable() override { return true; }
+ virtual void repaintEvent(RepaintEvent* repaintEvent) override;
+ virtual void resize(int w, int h) override;
private:
- struct private_data *prv;
+ void listSelectionChanged();
+ void selectButtonClicked();
+ void cancelButtonClicked();
+ void handleKeyEvent();
- GUI::Label lbl_path;
- GUI::LineEdit lineedit;
+ Directory dir;
+#ifdef WIN32
+ bool above_root;
+ bool in_root;
+#endif
- GUI::ListBox listbox;
+ void cancel();
+ void changeDir();
- GUI::Button btn_sel;
- GUI::Button btn_esc;
+ Label lbl_path;
- Image back;
-};
+ LineEdit lineedit;
+ ListBox listbox;
+
+ Button btn_sel;
+ Button btn_esc;
+ Image back;
};
-#endif/*__DRUMGIZMO_FILEBROWSER_H__*/
+} // GUI::
diff --git a/plugingui/font.cc b/plugingui/font.cc
index f96bd95..d02efe7 100644
--- a/plugingui/font.cc
+++ b/plugingui/font.cc
@@ -26,106 +26,100 @@
*/
#include "font.h"
-#ifdef X11
-#include <X11/Xlib.h>
-#endif/*X11*/
+namespace GUI {
-GUI::Font::Font(std::string fontfile)
- : img_font(fontfile)
+Font::Font(const std::string& fontfile)
+ : img_font(fontfile)
{
- int px = 0;
- int c;
- for(c = 0; c < 255 && px < (int)img_font.width(); c++) {
- character_offset[c] = px + 1;
- character_pre_bias[c] = 0;
- character_post_bias[c] = 0;
- if(c > 0) {
- character_width[c - 1] =
- character_offset[c] - character_offset[c - 1] - 1;
- }
- px++;
- GUI::Colour c;
- while(px < (int)img_font.width()) {
- c = img_font.getPixel(px, 0);
- // Find next purple pixel in top row:
- if(c.red == 1 && c.green == 0 && c.blue == 1 && c.alpha == 1) break;
- px++;
- }
- }
- c++;
- character_width[c - 1] = character_offset[c] - character_offset[c - 1] - 1;
-}
-
-void GUI::Font::setFace(std::string face)
-{
- face = face;
-}
+ size_t px = 0;
+ size_t c;
-std::string GUI::Font::face()
-{
- return "";//face;
-}
+ for(c = 0; c < characters.size() && px < img_font.width(); ++c)
+ {
+ auto& character = characters[c];
+ character.offset = px + 1;
-void GUI::Font::setSize(size_t points)
-{
- (void)points;
-}
+ if(c > 0)
+ {
+ characters[c - 1].width =
+ character.offset - characters[c - 1].offset - 1;
+ }
-size_t GUI::Font::size()
-{
- return 0;
+ ++px;
+
+ Colour pixel;
+ while(px < img_font.width())
+ {
+ pixel = img_font.getPixel(px, 0);
+
+ // Find next purple pixel in top row:
+ if((pixel.red == 1) && (pixel.green == 0) &&
+ (pixel.blue == 1) && (pixel.alpha == 1))
+ {
+ break;
+ }
+
+ ++px;
+ }
+
+ characters[c] = character;
+ }
+
+ ++c;
+
+ characters[c - 1].width = characters[c].offset - characters[c - 1].offset - 1;
}
-size_t GUI::Font::textWidth(std::string text)
+size_t Font::textWidth(const std::string& text) const
{
- size_t len = 0;
+ size_t len = 0;
- for(size_t i = 0; i < text.length(); i++) {
- unsigned int cha = text[i];
- len += character_width[(char)cha] + 1 + character_post_bias[(char)cha];
- }
+ for(auto cha : text)
+ {
+ auto& character = characters[cha];
+ len += character.width + spacing + character.post_bias;
+ }
- return len;
+ return len;
}
-size_t GUI::Font::textHeight(std::string text)
+size_t Font::textHeight(const std::string& text) const
{
- return img_font.height();
+ return img_font.height();
}
-GUI::PixelBufferAlpha *GUI::Font::render(std::string text)
+void Font::setLetterSpacing(int letter_spacing)
{
- int border = 1;
- PixelBufferAlpha *pb =
- new PixelBufferAlpha(textWidth(text), textHeight(text));
-
- int x_offset = 0;
- for(size_t i = 0; i < text.length(); i++) {
- unsigned int cha = text[i];
- for(size_t x = 0; x < character_width[(char)cha]; x++) {
- for(size_t y = 0; y < img_font.height(); y++) {
- Colour c = img_font.getPixel(x + (character_offset[(char)cha]), y);
- pb->setPixel(x + x_offset + character_pre_bias[(char)cha], y,
- c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255);
- }
- }
- x_offset += character_width[(char)cha] + border +
- character_post_bias[(char)cha];
- }
-
- return pb;
+ spacing = letter_spacing;
}
-#ifdef TEST_FONT
-//deps:
-//cflags:
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
+int Font::letterSpacing() const
+{
+ return spacing;
+}
-TEST_END;
+PixelBufferAlpha *Font::render(const std::string& text) const
+{
+ PixelBufferAlpha *pb =
+ new PixelBufferAlpha(textWidth(text), textHeight(text));
+
+ int x_offset = 0;
+ for(auto cha : text)
+ {
+ auto& character = characters[cha];
+ for(size_t x = 0; x < character.width; ++x)
+ {
+ for(size_t y = 0; y < img_font.height(); ++y)
+ {
+ Colour c = img_font.getPixel(x + character.offset, y);
+ pb->setPixel(x + x_offset + character.pre_bias, y,
+ c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255);
+ }
+ }
+ x_offset += character.width + spacing + character.post_bias;
+ }
+
+ return pb;
+}
-#endif/*TEST_FONT*/
+} // GUI::
diff --git a/plugingui/font.h b/plugingui/font.h
index b47fbde..e29528d 100644
--- a/plugingui/font.h
+++ b/plugingui/font.h
@@ -24,11 +24,10 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_FONT_H__
-#define __DRUMGIZMO_FONT_H__
+#pragma once
#include <string>
-#include <map>
+#include <array>
#include "pixelbuffer.h"
#include "image.h"
@@ -37,27 +36,29 @@ namespace GUI {
class Font {
public:
- Font(std::string fontfile = ":font.png");
-
- void setFace(std::string face);
- std::string face();
+ Font(const std::string& fontfile = ":font.png");
- void setSize(size_t points);
- size_t size();
+ size_t textWidth(const std::string& text) const;
+ size_t textHeight(const std::string& text = "") const;
- size_t textWidth(std::string text);
- size_t textHeight(std::string text = "");
+ void setLetterSpacing(int letterSpacing);
+ int letterSpacing() const;
- PixelBufferAlpha *render(std::string text);
+ PixelBufferAlpha *render(const std::string& text) const;
private:
- Image img_font;
+ Image img_font;
- std::map<char, int> character_offset;
- std::map<char, size_t> character_width;
- std::map<char, int> character_pre_bias;
- std::map<char, int> character_post_bias;
-};
+ class Character {
+ public:
+ int offset{0};
+ size_t width{0};
+ int pre_bias{0};
+ int post_bias{0};
+ };
+ std::array<Character, 255> characters;
+ int spacing{1};
};
-#endif/*__DRUMGIZMO_FONT_H__*/
+
+} // GUI::
diff --git a/plugingui/guievent.h b/plugingui/guievent.h
index 4732101..6e2ded9 100644
--- a/plugingui/guievent.h
+++ b/plugingui/guievent.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_GUI_EVENT_H__
-#define __DRUMGIZMO_GUI_EVENT_H__
+#pragma once
#include <unistd.h>
@@ -38,104 +37,117 @@
namespace GUI {
+enum class EventType {
+ mouseMove,
+ repaint,
+ button,
+ scroll,
+ key,
+ close,
+ resize
+};
+
class Event {
public:
- typedef enum {
- MouseMove,
- Repaint,
- Button,
- Scroll,
- Key,
- Close,
- Resize
- } Type;
- virtual ~Event() {}
-
- virtual Type type() = 0;
+ virtual ~Event() {}
+
+ virtual EventType type() = 0;
#ifdef X11
- ::Window window_id;
+ ::Window window_id;
#endif/*X11*/
};
class MouseMoveEvent : public Event {
public:
- Type type() { return MouseMove; }
+ EventType type() { return EventType::mouseMove; }
+
+ int x;
+ int y;
+};
+
+
+enum class Direction {
+ up,
+ down,
+};
- int x;
- int y;
+enum class MouseButton {
+ right,
+ middle,
+ left,
};
class ButtonEvent : public Event {
public:
- Type type() { return Button; }
+ EventType type() { return EventType::button; }
- int x;
- int y;
+ int x;
+ int y;
- int direction;
- int button;
- int doubleclick;
+ Direction direction;
+ MouseButton button;
+
+ bool doubleClick;
};
class ScrollEvent : public Event {
public:
- Type type() { return Scroll; }
+ EventType type() { return EventType::scroll; }
- int x;
- int y;
+ int x;
+ int y;
- int delta;
+ int delta;
};
class RepaintEvent : public Event {
public:
- Type type() { return Repaint; }
+ EventType type() { return EventType::repaint; }
+
+ int x;
+ int y;
+ size_t width;
+ size_t height;
+};
- 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:
- Type type() { return Key; }
-
- int direction;
- int keycode;
- std::string text;
-
- enum {
- KEY_UNKNOWN =-1,
- KEY_LEFT = 1,
- KEY_RIGHT = 2,
- KEY_UP = 3,
- KEY_DOWN = 4,
- KEY_DELETE = 5,
- KEY_BACKSPACE = 6,
- KEY_HOME = 7,
- KEY_END = 8,
- KEY_PGDOWN = 9,
- KEY_PGUP = 10,
- KEY_ENTER = 11,
- KEY_CHARACTER = 0xffff // character data is stored in 'text'
- };
+ EventType type() { return EventType::key; }
+
+ Direction direction;
+
+ Key keycode;
+ std::string text;
};
class CloseEvent : public Event {
public:
- Type type() { return Close; }
+ EventType type() { return EventType::close; }
};
class ResizeEvent : public Event {
public:
- Type type() { return Resize; }
-
- size_t width;
- size_t height;
-};
+ EventType type() { return EventType::resize; }
+ size_t width;
+ size_t height;
};
-#endif/*__DRUMGIZMO_GUI_EVENT_H__*/
+} // GUI::
diff --git a/plugingui/image.cc b/plugingui/image.cc
index 65b8242..3cefbb3 100644
--- a/plugingui/image.cc
+++ b/plugingui/image.cc
@@ -26,94 +26,100 @@
*/
#include "image.h"
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdint.h>
+#include <cstring>
+#include <cstdint>
+#include <cstdlib>
#include <hugin.hpp>
#include "resource.h"
-// http://blog.hammerian.net/2009/reading-png-images-from-memory/
-
#include "lodepng/lodepng.h"
-GUI::Image::Image(const char* data, size_t size)
+namespace GUI {
+
+Image::Image(const char* data, size_t size)
{
- load(data, size);
+ load(data, size);
}
-GUI::Image::Image(std::string filename)
+Image::Image(const std::string& filename)
{
- GUI::Resource rc(filename);
- load(rc.data(), rc.size());
+ Resource rc(filename);
+ load(rc.data(), rc.size());
}
-GUI::Image::~Image()
+Image::~Image()
{
- free(image_data);
+ std::free(image_data);
}
-void GUI::Image::setError(int err)
+void Image::setError()
{
- GUI::Resource rc(":png_error");
+ Resource rc(":png_error");
- const unsigned char *p = (const unsigned char *)rc.data();
+ const unsigned char* p = (const unsigned char*)rc.data();
- uint32_t iw, ih;
+ std::uint32_t iw, ih;
- memcpy(&iw, p, sizeof(uint32_t)); p += sizeof(uint32_t);
- memcpy(&ih, p, sizeof(uint32_t)); p += sizeof(uint32_t);
+ std::memcpy(&iw, p, sizeof(uint32_t));
+ p += sizeof(uint32_t);
- w = iw;
- h = ih;
+ std::memcpy(&ih, p, sizeof(uint32_t));
+ p += sizeof(uint32_t);
- DEBUG(image, "w:%d, h:%d\n", (int)w, (int)h);
+ _width = iw;
+ _height = ih;
- image_data = (unsigned char*)malloc(rc.size() - 8);
- memcpy(image_data, p, rc.size() - 8);
+ size_t image_size = rc.size() - (sizeof(iw) + sizeof(ih));
+ image_data = (unsigned char*)std::malloc(image_size);
+ memcpy(image_data, p, image_size);
}
-void GUI::Image::load(const char* data, size_t size)
+void Image::load(const char* data, size_t size)
{
- //unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h,
- // const unsigned char* in, size_t insize);
- unsigned iw, ih;
- unsigned res = lodepng_decode32((unsigned char**)&image_data, &iw, &ih,
- (const unsigned char*)data, size);
- w = iw;
- h = ih;
-
- if(res != 0) {
- ERR(image, "[read_png_file] Error during init_io");
- setError(3);
- return;
- }
+ unsigned int iw, ih;
+ unsigned int res = lodepng_decode32((unsigned char**)&image_data,
+ &iw, &ih,
+ (const unsigned char*)data, size);
+
+ _width = iw;
+ _height = ih;
+
+ if(res != 0)
+ {
+ ERR(image, "Error in lodepng_decode32: %d", res);
+ setError();
+ return;
+ }
}
-size_t GUI::Image::width()
+size_t Image::width() const
{
- return w;
+ return _width;
}
-size_t GUI::Image::height()
+size_t Image::height() const
{
- return h;
+ return _height;
}
-GUI::Colour GUI::Image::getPixel(size_t x, size_t y)
+Colour Image::getPixel(size_t x, size_t y) const
{
- if(x > width() || y > height()) return GUI::Colour(0,0,0,0);
- unsigned char *ptr = &image_data[(x + y * width()) * 4];
- float r = ptr[0];
- float g = ptr[1];
- float b = ptr[2];
- float a = ptr[3];
- GUI::Colour c(r / 255.0,
- g / 255.0,
- b / 255.0,
- a / 255.0);
- return c;
+ if(x > _width || y > _height)
+ {
+ return Colour(0,0,0,0);
+ }
+
+ unsigned char* ptr = &image_data[(x + y * width()) * 4];
+
+ float r = ptr[0];
+ float g = ptr[1];
+ float b = ptr[2];
+ float a = ptr[3];
+
+ Colour c(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
+
+ return c;
}
+
+} // GUI::
diff --git a/plugingui/image.h b/plugingui/image.h
index cec1518..0decc22 100644
--- a/plugingui/image.h
+++ b/plugingui/image.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_IMAGE_H__
-#define __DRUMGIZMO_IMAGE_H__
+#pragma once
#include <string>
@@ -36,24 +35,22 @@ namespace GUI {
class Image {
public:
- Image(const char* data, size_t size);
- Image(std::string filename);
- ~Image();
+ Image(const char* data, size_t size);
+ Image(const std::string& filename);
+ ~Image();
- size_t width();
- size_t height();
+ size_t width() const;
+ size_t height() const;
- Colour getPixel(size_t x, size_t y);
+ Colour getPixel(size_t x, size_t y) const;
private:
- void setError(int err);
+ void setError();
- void load(const char* data, size_t size);
+ void load(const char* data, size_t size);
- size_t w, h;
- unsigned char *image_data;
+ size_t _width, _height;
+ unsigned char* image_data;
};
-};
-
-#endif/*__DRUMGIZMO_IMAGE_H__*/
+} // GUI::
diff --git a/plugingui/knob.cc b/plugingui/knob.cc
index 4cac180..ab2eca9 100644
--- a/plugingui/knob.cc
+++ b/plugingui/knob.cc
@@ -37,169 +37,167 @@
#endif
#include <math.h>
-GUI::Knob::Knob(Widget *parent)
- : GUI::Widget(parent), img_knob(":knob.png")
+namespace GUI {
+
+Knob::Knob(Widget *parent)
+ : Widget(parent)
+ , img_knob(":knob.png")
{
- state = up;
+ state = up;
- val = 0.0;
- maximum = 1.0;
- minimum = 0.0;
- mouse_offset_x = 0;
+ maximum = 1.0;
+ minimum = 0.0;
- handler = NULL;
- ptr = NULL;
-}
+ currentValue = minimum;
-void GUI::Knob::setValue(float v)
-{
- val = v;
- if(handler) handler(ptr);
- repaintEvent(NULL);
+ mouse_offset_x = 0;
}
-float GUI::Knob::value()
+void Knob::setValue(float value)
{
- return val;
+ internalSetValue(value);
}
-void GUI::Knob::registerClickHandler(void (*handler)(void *), void *ptr)
+float Knob::value()
{
- this->handler = handler;
- this->ptr = ptr;
+ return currentValue;
}
-void GUI::Knob::scrollEvent(ScrollEvent *e)
+void Knob::scrollEvent(ScrollEvent* scrollEvent)
{
- val -= e->delta / 200.0;
- if(val < 0) val = 0;
- if(val > 1) val = 1;
-
- if(handler) handler(ptr);
-
- repaintEvent(NULL);
+ float value = currentValue - (scrollEvent->delta / 200.0);
+ internalSetValue(value);
}
-void GUI::Knob::mouseMoveEvent(MouseMoveEvent *e)
+void Knob::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent)
{
- if(state == down) {
- if(mouse_offset_x == (e->x + -1*e->y)) return;
+ if(state == down)
+ {
+ if(mouse_offset_x == (mouseMoveEvent->x + (-1 * mouseMoveEvent->y)))
+ {
+ return;
+ }
- float dval = mouse_offset_x - (e->x + -1*e->y);
- val -= dval / 300.0;
+ float dval =
+ mouse_offset_x - (mouseMoveEvent->x + (-1 * mouseMoveEvent->y));
+ float value = currentValue - (dval / 300.0);
- if(val < 0) val = 0;
- if(val > 1) val = 1;
+ internalSetValue(value);
- if(handler) handler(ptr);
- repaintEvent(NULL);
-
- mouse_offset_x = e->x + -1*e->y;
- }
+ mouse_offset_x = mouseMoveEvent->x + (-1 * mouseMoveEvent->y);
+ }
}
-void GUI::Knob::keyEvent(KeyEvent *e)
+void Knob::keyEvent(KeyEvent* keyEvent)
{
- if(e->direction != -1) return;
-
- switch(e->keycode) {
- case GUI::KeyEvent::KEY_UP:
- val += 0.01;
- break;
- case GUI::KeyEvent::KEY_DOWN:
- val -= 0.01;
- break;
- case GUI::KeyEvent::KEY_RIGHT:
- val += 0.01;
- break;
- case GUI::KeyEvent::KEY_LEFT:
- val -= 0.01;
- break;
- case GUI::KeyEvent::KEY_HOME:
- val = 0;
- break;
- case GUI::KeyEvent::KEY_END:
- val = 1;
- break;
- default:
- break;
- }
-
- if(val < 0) val = 0;
- if(val > 1) val = 1;
-
- repaintEvent(NULL);
+ if(keyEvent->direction != Direction::up)
+ {
+ return;
+ }
+
+ float value = currentValue;
+ 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 GUI::Knob::buttonEvent(ButtonEvent *e)
+void Knob::buttonEvent(ButtonEvent* buttonEvent)
{
- if(e->direction == 1) {
- state = down;
- mouse_offset_x = e->x + -1*e->y;
- if(handler) handler(ptr);
- repaintEvent(NULL);
- }
- if(e->direction == -1) {
- state = up;
- mouse_offset_x = e->x + -1*e->y;
- repaintEvent(NULL);
- clicked();
- if(handler) handler(ptr);
- }
+ if(buttonEvent->direction == Direction::down)
+ {
+ state = down;
+ mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y);
+ }
+
+ if(buttonEvent->direction == Direction::up)
+ {
+ state = up;
+ mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y);
+ clicked();
+ }
}
-void GUI::Knob::repaintEvent(GUI::RepaintEvent *e)
+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);
-
- char buf[64];
- sprintf(buf, "%.2f", val * maximum);
- Font font;
- p.drawText(center_x - font.textWidth(buf) / 2 + 1,
- center_y + font.textHeight(buf) / 2 + 1, font, buf);
-
- double padval = val * 0.8 + 0.1; // Make it start from 20% and stop at 80%
-
- double from_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.6;
- double from_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.6;
-
- double to_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.8;
- double to_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.8;
-
- // Draw "fat" line by drawing 9 lines with moved start/ending points.
- p.setColour(Colour(1, 0, 0, 1));
- 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);
-
- }
- }
+ 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);
+
+ char buf[64];
+ sprintf(buf, "%.2f", currentValue * maximum);
+ 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 = currentValue * 0.8 + 0.1;
+
+ double from_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.6;
+ double from_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.6;
+
+ double to_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.8;
+ double to_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.8;
+
+ // Draw "fat" line by drawing 9 lines with moved start/ending points.
+ p.setColour(Colour(1, 0, 0, 1));
+ 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);
+ }
+ }
}
-#ifdef TEST_KNOB
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
+void Knob::internalSetValue(float value)
+{
+ if(value < minimum)
+ {
+ value = minimum;
+ }
+
+ if(value > maximum)
+ {
+ value = maximum;
+ }
+
+ if(value == currentValue)
+ {
+ return;
+ }
+
+ currentValue = value;
+ valueChangedNotifier(currentValue);
+ repaintEvent(nullptr);
+}
-#endif/*TEST_KNOB*/
+} // GUI::
diff --git a/plugingui/knob.h b/plugingui/knob.h
index a6af499..4a71b2e 100644
--- a/plugingui/knob.h
+++ b/plugingui/knob.h
@@ -24,57 +24,57 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_KNOB_H__
-#define __DRUMGIZMO_KNOB_H__
+#pragma once
#include "widget.h"
-
#include "image.h"
+#include "font.h"
+#include "notifier.h"
namespace GUI {
class Knob : public Widget {
public:
- Knob(Widget *parent);
+ Knob(Widget *parent);
- bool catchMouse() { return true; }
- bool isFocusable() { return true; }
+ // From Widget:
+ bool catchMouse() override { return true; }
+ bool isFocusable() override { return true; }
- void setValue(float value);
- float value();
+ void setValue(float value);
+ float value();
- void registerClickHandler(void (*handler)(void *), void *ptr);
+ Notifier<float> valueChangedNotifier; // (float newValue)
- //protected:
- virtual void clicked() {}
+protected:
+ virtual void clicked() {}
- virtual void repaintEvent(RepaintEvent *e);
- virtual void buttonEvent(ButtonEvent *e);
- virtual void mouseMoveEvent(MouseMoveEvent *e);
- virtual void scrollEvent(ScrollEvent *e);
- virtual void keyEvent(KeyEvent *e);
+ // 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:
- typedef enum {
- up,
- down
- } state_t;
-
- float val;
- float maximum;
- float minimum;
+ //! Sets the internal value and sends out the changed notification.
+ void internalSetValue(float value);
- state_t state;
+ typedef enum {
+ up,
+ down
+ } state_t;
- GUI::Image img_knob;
+ state_t state;
- void (*handler)(void *);
- void *ptr;
+ float currentValue;
+ float maximum;
+ float minimum;
- int mouse_offset_x;
-
-};
+ Image img_knob;
+ int mouse_offset_x;
+ Font font;
};
-#endif/*__DRUMGIZMO_KNOB_H__*/
+} // GUI::
diff --git a/plugingui/label.cc b/plugingui/label.cc
index bcc7005..f4a2cc1 100644
--- a/plugingui/label.cc
+++ b/plugingui/label.cc
@@ -27,43 +27,53 @@
#include "label.h"
#include "painter.h"
+#include "guievent.h"
-GUI::Label::Label(GUI::Widget *parent) : GUI::Widget(parent)
+namespace GUI {
+
+Label::Label(Widget *parent)
+ : Widget(parent)
{
}
-void GUI::Label::setText(std::string text)
+void Label::setText(const std::string& text)
{
- _text = text;
- repaintEvent(NULL);
+ _text = text;
+ repaintEvent(nullptr);
}
-void GUI::Label::repaintEvent(GUI::RepaintEvent *e)
+void Label::setAlignment(TextAlignment alignment)
{
- Painter p(this);
-
- p.clear();
-
- p.setColour(Colour(1));
+ this->alignment = alignment;
+}
- Font font(":fontemboss.png");
- p.drawText(10, (height() + font.textHeight()) / 2, font, _text, true);
+void Label::resizeToText()
+{
+ resize(font.textWidth(_text) + border, font.textHeight());
}
+void Label::repaintEvent(RepaintEvent* repaintEvent)
+{
+ Painter p(*this);
-#ifdef TEST_LABEL
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
+ p.clear();
-TEST_BEGIN;
+ p.setColour(Colour(1));
-// TODO: Put some testcode here (see test.h for usable macros).
+ 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;
+ }
-TEST_END;
+ p.drawText(offset, (height() + font.textHeight()) / 2, font, _text, true);
+}
-#endif/*TEST_LABEL*/
+} // GUI::
diff --git a/plugingui/label.h b/plugingui/label.h
index 50f02d6..794778d 100644
--- a/plugingui/label.h
+++ b/plugingui/label.h
@@ -24,30 +24,41 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_LABEL_H__
-#define __DRUMGIZMO_LABEL_H__
+#pragma once
#include "widget.h"
-#include <string>
+#include "font.h"
-#include "guievent.h"
+#include <string>
namespace GUI {
+enum class TextAlignment {
+ left,
+ center,
+ right,
+};
+
class Label : public Widget {
public:
- Label(Widget *parent);
+ Label(Widget *parent);
- void setText(std::string text);
+ void setText(const std::string& text);
- //protected:
- virtual void repaintEvent(RepaintEvent *e);
+ void setAlignment(TextAlignment alignment);
-private:
- std::string _text;
-};
+ void resizeToText();
+protected:
+ // From Widget:
+ virtual void repaintEvent(RepaintEvent* repaintEvent) override;
+
+private:
+ std::string _text;
+ Font font{":fontemboss.png"};
+ TextAlignment alignment{TextAlignment::left};
+ int border{0};
};
-#endif/*__DRUMGIZMO_LABEL_H__*/
+} // GUI::
diff --git a/plugingui/layout.cc b/plugingui/layout.cc
new file mode 100644
index 0000000..65042a4
--- /dev/null
+++ b/plugingui/layout.cc
@@ -0,0 +1,219 @@
+/* -*- 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 "layout.h"
+
+#include "widget.h"
+
+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<Widget*>(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)
+{
+ LayoutItemList::iterator i = items.begin();
+ while(i != items.end())
+ {
+ if(*i == item)
+ {
+ i = items.erase(i);
+ continue;
+ }
+ ++i;
+ }
+
+ 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)
+ {
+ item->resize(w, parent->height() / items.size());
+ }
+
+ 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)
+ {
+ item->resize(parent->width() / items.size(), 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;
+}
+
+} // GUI::
diff --git a/plugingui/layout.h b/plugingui/layout.h
new file mode 100644
index 0000000..949c1ca
--- /dev/null
+++ b/plugingui/layout.h
@@ -0,0 +1,135 @@
+/* -*- 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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.
+ */
+#pragma once
+
+#include <list>
+#include <cstdlib>
+
+#include "notifier.h"
+
+namespace GUI {
+
+class Layout;
+
+class LayoutItem {
+public:
+ LayoutItem();
+ virtual ~LayoutItem();
+
+ void setLayoutParent(Layout* parent);
+
+ virtual void resize(int width, int height) = 0;
+ virtual void move(size_t x, size_t y) = 0;
+ virtual int x() = 0;
+ virtual int y() = 0;
+ virtual size_t width() = 0;
+ virtual size_t height() = 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<LayoutItem *> 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;
+};
+
+} // GUI::
diff --git a/plugingui/led.cc b/plugingui/led.cc
index d26a0de..6950140 100644
--- a/plugingui/led.cc
+++ b/plugingui/led.cc
@@ -28,79 +28,70 @@
#include "painter.h"
-GUI::LED::LED(Widget *parent)
- : GUI::Widget(parent)
+namespace GUI {
+
+LED::LED(Widget *parent)
+ : Widget(parent)
+ , state(Off)
{
- state = off;
}
-void GUI::LED::setState(GUI::LED::state_t state)
+void LED::setState(state_t state)
{
- if(this->state != state) {
- this->state = state;
- repaintEvent(NULL);
- }
+ if(this->state != state)
+ {
+ this->state = state;
+ repaintEvent(nullptr);
+ }
}
-void GUI::LED::repaintEvent(GUI::RepaintEvent *e)
+void LED::repaintEvent(RepaintEvent* repaintEvent)
{
- size_t h = height() - 1;
- size_t w = width() - 1;
+ 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;
- }
+ 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);
+ 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);
+ 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);
+ p.setColour(Colour(1, alpha));
+ p.drawFilledCircle(w / 3, h / 3, size / 6);
}
-#ifdef TEST_LED
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_LED*/
+} // GUI::
diff --git a/plugingui/led.h b/plugingui/led.h
index 7bbd59a..6b1b730 100644
--- a/plugingui/led.h
+++ b/plugingui/led.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_LED_H__
-#define __DRUMGIZMO_LED_H__
+#pragma once
#include "widget.h"
@@ -33,24 +32,23 @@ namespace GUI {
class LED : public Widget {
public:
- typedef enum {
- red,
- green,
- blue,
- off
- } state_t;
+ typedef enum {
+ Red,
+ Green,
+ Blue,
+ Off
+ } state_t;
- LED(Widget *parent);
+ LED(Widget *parent);
- void setState(state_t state);
+ void setState(state_t state);
- //protected:
- void repaintEvent(RepaintEvent *e);
+protected:
+ // From Widget:
+ void repaintEvent(RepaintEvent* repaintEvent) override;
private:
- state_t state;
+ state_t state;
};
-};
-
-#endif/*__DRUMGIZMO_LED_H__*/
+} // GUI::
diff --git a/plugingui/lineedit.cc b/plugingui/lineedit.cc
index 5e1eb9b..2df40ff 100644
--- a/plugingui/lineedit.cc
+++ b/plugingui/lineedit.cc
@@ -27,213 +27,271 @@
#include "lineedit.h"
#include <stdio.h>
-
-#include "window.h"
-
-#include <assert.h>
-
#include <hugin.hpp>
#define BORDER 10
-GUI::LineEdit::LineEdit(Widget *parent)
- : GUI::Widget(parent)
+namespace GUI {
+
+LineEdit::LineEdit(Widget *parent)
+ : Widget(parent)
{
- pos = 0;
- offsetpos = 0;
- setReadOnly(false);
-
- box.topLeft = new Image(":widget_tl.png");
- box.top = new Image(":widget_t.png");
- box.topRight = new Image(":widget_tr.png");
- box.left = new Image(":widget_l.png");
- box.right = new Image(":widget_r.png");
- box.bottomLeft = new Image(":widget_bl.png");
- box.bottom = new Image(":widget_b.png");
- box.bottomRight = new Image(":widget_br.png");
- box.center = new Image(":widget_c.png");
-
- handler = NULL;
+ setReadOnly(false);
+
+ box.topLeft = new Image(":widget_tl.png");
+ box.top = new Image(":widget_t.png");
+ box.topRight = new Image(":widget_tr.png");
+ box.left = new Image(":widget_l.png");
+ box.right = new Image(":widget_r.png");
+ box.bottomLeft = new Image(":widget_bl.png");
+ box.bottom = new Image(":widget_b.png");
+ box.bottomRight = new Image(":widget_br.png");
+ box.center = new Image(":widget_c.png");
}
-void GUI::LineEdit::registerEnterPressedHandler(void (*handler)(void *), void *ptr)
+LineEdit::~LineEdit()
{
- this->handler = handler;
- this->ptr = ptr;
+ delete box.topLeft;
+ delete box.top;
+ delete box.topRight;
+ delete box.left;
+ delete box.right;
+ delete box.bottomLeft;
+ delete box.bottom;
+ delete box.bottomRight;
+ delete box.center;
}
-void GUI::LineEdit::setReadOnly(bool ro)
+void LineEdit::setReadOnly(bool ro)
{
- readonly = ro;
+ readonly = ro;
}
-bool GUI::LineEdit::readOnly()
+bool LineEdit::readOnly()
{
- return readonly;
+ return readonly;
}
-void GUI::LineEdit::setText(std::string text)
+void LineEdit::setText(const std::string& text)
{
- _text = text;
- pos = text.size();
-
- repaintEvent(NULL);
- textChanged();
+ _text = text;
+ pos = text.size();
+
+ visibleText = _text;
+ offsetPos = 0;
+
+ repaintEvent(nullptr);
+ textChanged();
}
-std::string GUI::LineEdit::text()
+std::string LineEdit::text()
{
- return _text;
+ return _text;
}
-void GUI::LineEdit::buttonEvent(ButtonEvent *e)
+void LineEdit::buttonEvent(ButtonEvent *buttonEvent)
{
- if(readOnly()) return;
-
-
- if(e->direction == 1) {
- for(int i = 0; i < (int)_visibletext.length(); i++) {
- if(e->x < (int)(font.textWidth(_visibletext.substr(0, i)) + BORDER)) {
- pos = i + offsetpos;
- break;
- }
- }
- repaintEvent(NULL);
- }
+ if(readOnly())
+ {
+ 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;
+ }
+ }
+ repaintEvent(nullptr);
+ }
}
-void GUI::LineEdit::keyEvent(GUI::KeyEvent *e)
+void LineEdit::keyEvent(KeyEvent *keyEvent)
{
- if(readOnly()) return;
-
- bool change = false;
-
- if(e->direction == -1) {
-
- if(e->keycode == GUI::KeyEvent::KEY_LEFT) {
- if(pos) pos--;
- if(offsetpos >= pos) walkstate = WALK_LEFT;
-
- } else if(e->keycode == GUI::KeyEvent::KEY_HOME) {
- pos = 0;
-
- } else if(e->keycode == GUI::KeyEvent::KEY_END) {
- pos = _text.length();
-
- } else if(e->keycode == GUI::KeyEvent::KEY_RIGHT) {
- if(pos < _text.length()) pos++;
- if(offsetpos + _visibletext.length() <= pos &&
- pos < _text.length()) walkstate = WALK_RIGHT;
-
- } else if(e->keycode == GUI::KeyEvent::KEY_DELETE) {
- if(pos < _text.length()) {
- std::string t = _text.substr(0, pos);
- t += _text.substr(pos + 1, std::string::npos);
- _text = t;
- change = true;
- }
-
- } else if(e->keycode == GUI::KeyEvent::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;
- }
-
- } else if(e->keycode == GUI::KeyEvent::KEY_CHARACTER) {
- std::string pre = _text.substr(0, pos);
- std::string post = _text.substr(pos, std::string::npos);
- _text = pre + e->text + post;
- change = true;
- pos++;
-
- } else if(e->keycode == GUI::KeyEvent::KEY_ENTER) {
- if(handler) handler(ptr);
- }
- repaintEvent(NULL);
- }
-
- if(change) textChanged();
+ 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;
+ }
+
+ repaintEvent(nullptr);
+ }
+
+ if(change)
+ {
+ textChanged();
+ }
}
-void GUI::LineEdit::repaintEvent(GUI::RepaintEvent *e)
+void LineEdit::repaintEvent(RepaintEvent *repaintEvent)
{
- Painter p(this);
-
- p.clear();
-
- int w = width();
- int h = height();
- if(w == 0 || h == 0) return;
- p.drawBox(0, 0, &box, w, h);
-
- p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
-
- if(walkstate == WALK_LEFT) {
- _visibletext = _text.substr(pos, std::string::npos);
- offsetpos = pos;
- }
- else if(walkstate == WALK_RIGHT) {
- int d = (offsetpos < _text.length()) ? 1 : 0;
- _visibletext = _text.substr(offsetpos + d);
- offsetpos = offsetpos + d;
- }
- else {
- _visibletext = _text;
- offsetpos = 0;
- }
- while(true) {
- int textwidth = font.textWidth(_visibletext);
- if(textwidth > w - BORDER - 4 + 3) {
- if(walkstate == WALK_LEFT) {
- _visibletext = _visibletext.substr(0, _visibletext.length()-1);
- }
- else if(walkstate == WALK_RIGHT) {
- _visibletext = _visibletext.substr(0, _visibletext.length()-1);
- }
- else {
- if(offsetpos < pos) {
- _visibletext = _visibletext.substr(1);
- offsetpos++;
- }
- else {
- _visibletext = _visibletext.substr(0, _visibletext.length() - 1);
- }
- }
- }
- else {
- 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);
- }
+ Painter p(*this);
+
+ p.clear();
+
+ int w = width();
+ int h = height();
+ if((w == 0) || (h == 0))
+ {
+ return;
+ }
+
+ p.drawBox(0, 0, box, w, h);
+
+ p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
+
+ 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:
+ break;
+ }
+
+ while(true)
+ {
+ int textWidth = font.textWidth(visibleText);
+ if(textWidth <= (w - BORDER - 4 + 3))
+ {
+ 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);
+ }
}
-#ifdef TEST_LINEEDIT
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_LINEEDIT*/
+} // GUI::
diff --git a/plugingui/lineedit.h b/plugingui/lineedit.h
index f85e9bd..ae1c7b8 100644
--- a/plugingui/lineedit.h
+++ b/plugingui/lineedit.h
@@ -24,9 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_LINEEDIT_H__
-#define __DRUMGIZMO_LINEEDIT_H__
-
+#pragma once
#include <string>
@@ -38,49 +36,45 @@ namespace GUI {
class LineEdit : public Widget {
public:
- LineEdit(Widget *parent);
+ LineEdit(Widget *parent);
+ ~LineEdit();
- bool isFocusable() { return true; }
+ bool isFocusable() override { return true; }
- std::string text();
- void setText(std::string text);
+ std::string text();
+ void setText(const std::string& text);
- void setReadOnly(bool readonly);
- bool readOnly();
+ void setReadOnly(bool readonly);
+ bool readOnly();
- void registerEnterPressedHandler(void (*handler)(void *), void *ptr);
+ Notifier<> enterPressedNotifier;
- //protected:
- virtual void keyEvent(KeyEvent *e);
- virtual void repaintEvent(RepaintEvent *e);
- virtual void buttonEvent(ButtonEvent *e);
+ //protected:
+ virtual void keyEvent(KeyEvent *keyEvent) override;
+ virtual void repaintEvent(RepaintEvent *repaintEvent) override;
+ virtual void buttonEvent(ButtonEvent *buttonEvent) override;
protected:
- virtual void textChanged() {}
+ virtual void textChanged() {}
private:
- Painter::Box box;
-
- Font font;
+ Painter::Box box;
- std::string _text;
- size_t pos;
- std::string _visibletext;
- size_t offsetpos;
+ Font font;
- enum state_t {
- NOOP = 0,
- WALK_LEFT = 1,
- WALK_RIGHT = 2
- };
- state_t walkstate;
+ std::string _text;
+ size_t pos{0};
+ std::string visibleText;
+ size_t offsetPos{0};
- bool readonly;
-
- void (*handler)(void *);
- void *ptr;
-};
+ enum state_t {
+ Noop,
+ WalkLeft,
+ WalkRight,
+ };
+ state_t walkstate{Noop};
+ bool readonly;
};
-#endif/*__DRUMGIZMO_LINEEDIT_H__*/
+} // GUI::
diff --git a/plugingui/listbox.cc b/plugingui/listbox.cc
index ed873b2..8097ca9 100644
--- a/plugingui/listbox.cc
+++ b/plugingui/listbox.cc
@@ -29,95 +29,97 @@
#include "painter.h"
#include "font.h"
-#include <stdio.h>
-
-GUI::ListBox::ListBox(GUI::Widget *parent)
- : GUI::Widget(parent)
+namespace GUI {
+
+ListBox::ListBox(Widget *parent)
+ : Widget(parent)
+ , selectionNotifier(basic.selectionNotifier)
+ , clickNotifier(basic.clickNotifier)
+ , valueChangedNotifier(basic.valueChangedNotifier)
+ , basic(this)
{
- box.topLeft = new Image(":widget_tl.png");
- box.top = new Image(":widget_t.png");
- box.topRight = new Image(":widget_tr.png");
- box.left = new Image(":widget_l.png");
- box.right = new Image(":widget_r.png");
- box.bottomLeft = new Image(":widget_bl.png");
- box.bottom = new Image(":widget_b.png");
- box.bottomRight = new Image(":widget_br.png");
- box.center = new Image(":widget_c.png");
-
- basic = new GUI::ListBoxBasic(this);
- basic->move(box.left->width(), box.top->height());
+ box.topLeft = new Image(":widget_tl.png");
+ box.top = new Image(":widget_t.png");
+ box.topRight = new Image(":widget_tr.png");
+ box.left = new Image(":widget_l.png");
+ box.right = new Image(":widget_r.png");
+ box.bottomLeft = new Image(":widget_bl.png");
+ box.bottom = new Image(":widget_b.png");
+ box.bottomRight = new Image(":widget_br.png");
+ box.center = new Image(":widget_c.png");
+
+ basic.move(box.left->width(), box.top->height());
}
-GUI::ListBox::~ListBox()
+ListBox::~ListBox()
{
+ delete box.topLeft;
+ delete box.top;
+ delete box.topRight;
+ delete box.left;
+ delete box.right;
+ delete box.bottomLeft;
+ delete box.bottom;
+ delete box.bottomRight;
+ delete box.center;
}
-void GUI::ListBox::addItem(std::string name, std::string value)
+void ListBox::addItem(std::string name, std::string value)
{
- basic->addItem(name, value);
+ basic.addItem(name, value);
}
-void GUI::ListBox::addItems(std::vector<ListBoxBasic::Item> &items)
+void ListBox::addItems(std::vector<ListBoxBasic::Item> &items)
{
- basic->addItems(items);
+ basic.addItems(items);
}
-void GUI::ListBox::clear()
+void ListBox::clear()
{
- basic->clear();
+ basic.clear();
}
-bool GUI::ListBox::selectItem(int index)
+bool ListBox::selectItem(int index)
{
- return basic->selectItem(index);
+ return basic.selectItem(index);
}
-std::string GUI::ListBox::selectedName()
+std::string ListBox::selectedName()
{
- return basic->selectedName();
+ return basic.selectedName();
}
-std::string GUI::ListBox::selectedValue()
+std::string ListBox::selectedValue()
{
- return basic->selectedValue();
+ return basic.selectedValue();
}
-void GUI::ListBox::clearSelectedValue()
+void ListBox::clearSelectedValue()
{
- basic->clearSelectedValue();
+ basic.clearSelectedValue();
}
-void GUI::ListBox::registerClickHandler(void (*handler)(void *), void *ptr)
+void ListBox::repaintEvent(RepaintEvent* repaintEvent)
{
- basic->registerClickHandler(handler, ptr);
-}
+ Painter p(*this);
-void GUI::ListBox::registerSelectHandler(void (*handler)(void *), void *ptr)
-{
- basic->registerSelectHandler(handler, ptr);
-}
+ p.clear();
-void GUI::ListBox::registerValueChangeHandler(void (*handler)(void *),
- void *ptr)
-{
- basic->registerValueChangeHandler(handler, ptr);
-}
+ int w = width();
+ int h = height();
+ if(w == 0 || h == 0)
+ {
+ return;
+ }
-void GUI::ListBox::repaintEvent(GUI::RepaintEvent *e)
-{
- GUI::Painter p(this);
-
- p.clear();
-
- int w = width();
- int h = height();
- if(w == 0 || h == 0) return;
- p.drawBox(0, 0, &box, w, h);
+ p.drawBox(0, 0, box, w, h);
}
-void GUI::ListBox::resize(int width, int height)
+void ListBox::resize(int width, int height)
{
- GUI::Widget::resize(width, height);
- basic->resize(width - (box.left->width() + box.right->width()),
- height - (box.top->height() + box.bottom->height()));
+ Widget::resize(width, height);
+ basic.resize(width - (box.left->width() + box.right->width()),
+ height - (box.top->height() + box.bottom->height()));
}
+
+} // GUI::
diff --git a/plugingui/listbox.h b/plugingui/listbox.h
index c8677e7..f805fcb 100644
--- a/plugingui/listbox.h
+++ b/plugingui/listbox.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_LISTBOX_H__
-#define __DRUMGIZMO_LISTBOX_H__
+#pragma once
#include <string.h>
#include <vector>
@@ -38,31 +37,31 @@ namespace GUI {
class ListBox : public Widget {
public:
- ListBox(Widget *parent);
- ~ListBox();
+ ListBox(Widget *parent);
+ ~ListBox();
- void addItem(std::string name, std::string value);
- void addItems(std::vector<ListBoxBasic::Item> &items);
+ void addItem(std::string name, std::string value);
+ void addItems(std::vector<ListBoxBasic::Item> &items);
- void clear();
- bool selectItem(int index);
- std::string selectedName();
- std::string selectedValue();
- void clearSelectedValue();
+ void clear();
+ bool selectItem(int index);
+ std::string selectedName();
+ std::string selectedValue();
+ void clearSelectedValue();
- void registerSelectHandler(void (*handler)(void *), void *ptr);
- void registerClickHandler(void (*handler)(void *), void *ptr);
- void registerValueChangeHandler(void (*handler)(void *), void *ptr);
+ // From Widget:
+ virtual void repaintEvent(RepaintEvent* repaintEvent) override;
+ virtual void resize(int w, int h) override;
- virtual void repaintEvent(GUI::RepaintEvent *e);
- virtual void resize(int w, int h);
+ // Forwarded notifiers from ListBoxBasic::basic
+ Notifier<>& selectionNotifier;
+ Notifier<>& clickNotifier;
+ Notifier<>& valueChangedNotifier;
private:
- ListBoxBasic *basic;
+ ListBoxBasic basic;
- Painter::Box box;
+ Painter::Box box;
};
-};
-
-#endif/*__DRUMGIZMO_LISTBOX_H__*/
+} // GUI::
diff --git a/plugingui/listboxbasic.cc b/plugingui/listboxbasic.cc
index df7877d..10d6c66 100644
--- a/plugingui/listboxbasic.cc
+++ b/plugingui/listboxbasic.cc
@@ -1,4 +1,3 @@
-
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
* listboxbasic.cc
@@ -30,305 +29,332 @@
#include "painter.h"
#include "font.h"
-#include <stdio.h>
-#include <hugin.hpp>
-
-void scrolled(void *ptr)
-{
- GUI::ListBoxBasic *l = (GUI::ListBoxBasic *)ptr;
- l->repaintEvent(NULL);
-}
+namespace GUI {
-GUI::ListBoxBasic::ListBoxBasic(GUI::Widget *parent)
- : GUI::Widget(parent), scroll(this), bg_img(":widget_c.png")
+ListBoxBasic::ListBoxBasic(Widget *parent)
+ : Widget(parent)
+ , scroll(this)
+ , bg_img(":widget_c.png")
{
- scroll.move(0,0);
- scroll.resize(18, 100);
+ scroll.move(0,0);
+ scroll.resize(18, 100);
- scroll.registerValueChangeHandler(scrolled, this);
+ CONNECT(&scroll, valueChangeNotifier,
+ this, &ListBoxBasic::onScrollBarValueChange);
- padding = 4;
- btn_size = 18;
+ padding = 4;
+ btn_size = 18;
- selected = -1;
- marked = -1;
-
- clk_handler = NULL;
- clk_ptr = NULL;
-
- sel_handler = NULL;
- sel_ptr = NULL;
-
- valch_handler = NULL;
- valch_ptr = NULL;
+ selected = -1;
+ marked = -1;
}
-GUI::ListBoxBasic::~ListBoxBasic()
+ListBoxBasic::~ListBoxBasic()
{
}
-void GUI::ListBoxBasic::setSelection(int index)
+void ListBoxBasic::setSelection(int index)
{
- selected = index;
- if(valch_handler) valch_handler(valch_ptr);
+ selected = index;
+ if(marked == -1)
+ {
+ marked = index;
+ }
+ valueChangedNotifier();
}
-void GUI::ListBoxBasic::addItem(std::string name, std::string value)
+void ListBoxBasic::addItem(const std::string& name, const std::string& value)
{
- std::vector<GUI::ListBoxBasic::Item> items;
- GUI::ListBoxBasic::Item item;
- item.name = name;
- item.value = value;
- items.push_back(item);
- addItems(items);
+ std::vector<ListBoxBasic::Item> items;
+ ListBoxBasic::Item item;
+ item.name = name;
+ item.value = value;
+ items.push_back(item);
+ addItems(items);
}
-void GUI::ListBoxBasic::addItems(std::vector<GUI::ListBoxBasic::Item> &is)
+void ListBoxBasic::addItems(const std::vector<ListBoxBasic::Item>& newItems)
{
- // DEBUG(list, "addItems %lu\n", is.size());
- std::vector<GUI::ListBoxBasic::Item>::iterator i = is.begin();
- while(i != is.end()) {
- items.push_back(*i);
- i++;
- }
-
-/*
- // sort
- for(int x = 0; x < (int)items.size(); x++) {
- for(int y = 0; y < (int)items.size(); y++) {
- if(items[x].name < items[y].name) {
- if(x == selected) setSelection(y);
- else if(selected == y) setSelection(x);
-
- GUI::ListBoxBasic::Item tmp = items[x];
- items[x] = items[y];
- items[y] = tmp;
- }
- }
- }
-*/
-
- if(selected == -1) setSelection((int)items.size() - 1);
- setSelection(0);
-
- int numitems = height() / (font.textHeight() + padding);
- scroll.setRange(numitems);
- scroll.setMaximum(items.size());
+ for(auto& item : newItems)
+ {
+ items.push_back(item);
+ }
+
+ if(selected == -1)
+ {
+ //setSelection((int)items.size() - 1);
+ setSelection(0);
+ }
+
+ int numitems = height() / (font.textHeight() + padding);
+ scroll.setRange(numitems);
+ scroll.setMaximum(items.size());
+ repaintEvent(nullptr);
}
-void GUI::ListBoxBasic::clear()
+void ListBoxBasic::clear()
{
- items.clear();
- setSelection(-1);
- scroll.setValue(0);
- repaintEvent(NULL);
+ items.clear();
+ setSelection(-1);
+ marked = -1;
+ scroll.setValue(0);
+ repaintEvent(nullptr);
}
-bool GUI::ListBoxBasic::selectItem(int index)
+bool ListBoxBasic::selectItem(int index)
{
- if(index < 0 || index > (int)items.size() - 1) return false;
- setSelection(index);
- repaintEvent(NULL);
- return true;
-}
+ if(index < 0 || (index > (int)items.size() - 1))
+ {
+ return false;
+ }
-std::string GUI::ListBoxBasic::selectedName()
-{
- if(selected < 0 || selected > (int)items.size() - 1) return "";
- return items[selected].name;
-}
+ setSelection(index);
+ repaintEvent(nullptr);
-std::string GUI::ListBoxBasic::selectedValue()
-{
- if(selected < 0 || selected > (int)items.size() - 1) return "";
- return items[selected].value;
+ return true;
}
-void GUI::ListBoxBasic::clearSelectedValue()
+std::string ListBoxBasic::selectedName()
{
- setSelection(-1);
+ if(selected < 0 || (selected > (int)items.size() - 1))
+ {
+ return "";
+ }
+
+ return items[selected].name;
}
-void GUI::ListBoxBasic::registerClickHandler(void (*handler)(void *), void *ptr)
+std::string ListBoxBasic::selectedValue()
{
- this->clk_handler = handler;
- this->clk_ptr = ptr;
+ if(selected < 0 || (selected > (int)items.size() - 1))
+ {
+ return "";
+ }
+
+ return items[selected].value;
}
-void GUI::ListBoxBasic::registerSelectHandler(void (*handler)(void *), void *ptr)
+void ListBoxBasic::clearSelectedValue()
{
- this->sel_handler = handler;
- this->sel_ptr = ptr;
+ setSelection(-1);
}
-void GUI::ListBoxBasic::registerValueChangeHandler(void (*handler)(void *),
- void *ptr)
+void ListBoxBasic::onScrollBarValueChange(int value)
{
- this->valch_handler = handler;
- this->valch_ptr = ptr;
+ repaintEvent(nullptr);
}
-void GUI::ListBoxBasic::repaintEvent(GUI::RepaintEvent *e)
+void ListBoxBasic::repaintEvent(RepaintEvent* repaintEvent)
{
- DEBUG(list, "repaint\n");
- GUI::Painter p(this);
-
- p.clear();
-
- int w = width();
- int h = height();
- if(w == 0 || h == 0) return;
-
- p.drawImageStretched(0, 0, &bg_img, w, h);
-
- p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
-
- 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++) {
- GUI::ListBoxBasic::Item *i = &items[idx];
- if(idx == selected) {
- p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 0.5));
- 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(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
-
- p.drawText(2, yoffset + font.textHeight(), font, i->name);
- yoffset += font.textHeight() + padding;
- }
+ Painter p(*this);
+
+ p.clear();
+
+ int w = width();
+ int h = height();
+
+ if((w == 0) || (h == 0))
+ {
+ return;
+ }
+
+ p.drawImageStretched(0, 0, bg_img, w, h);
+
+ p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
+
+ 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.0/255.0, 219.0/255.0 , 255.0/255.0, 0.5));
+ 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.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
+
+ p.drawText(2, yoffset + font.textHeight(), font, item.name);
+ yoffset += font.textHeight() + padding;
+ }
}
-void GUI::ListBoxBasic::scrollEvent(ScrollEvent *e)
+void ListBoxBasic::scrollEvent(ScrollEvent* scrollEvent)
{
- scroll.scrollEvent(e);
+ // forward scroll event to scroll bar.
+ scroll.scrollEvent(scrollEvent);
}
-void GUI::ListBoxBasic::keyEvent(GUI::KeyEvent *e)
+void ListBoxBasic::keyEvent(KeyEvent* keyEvent)
{
- if(e->direction != -1) return;
-
- switch(e->keycode) {
- case GUI::KeyEvent::KEY_UP:
- {
- marked--;
- if(marked < 0) marked = 0;
-
- if(marked < scroll.value()) {
- scroll.setValue(marked);
- }
- }
- break;
- case GUI::KeyEvent::KEY_DOWN:
- {
- // Number of items that can be displayed at a time.
- int numitems = height() / (font.textHeight() + padding);
-
- marked++;
- if(marked > ((int)items.size() - 1)) marked = (int)items.size() - 1;
-
- if(marked > (scroll.value() + numitems - 1)) {
- scroll.setValue(marked - numitems + 1);
- }
- }
- break;
- case GUI::KeyEvent::KEY_HOME:
- marked = 0;
- if(marked < scroll.value()) {
- scroll.setValue(marked);
- }
- break;
- case GUI::KeyEvent::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 GUI::KeyEvent::KEY_CHARACTER:
- if(e->text == " ") {
- setSelection(marked);
- // if(sel_handler) sel_handler(sel_ptr);
- }
- break;
- case GUI::KeyEvent::KEY_ENTER:
- setSelection(marked);
- if(sel_handler) sel_handler(sel_ptr);
- break;
- default:
- break;
- }
-
- repaintEvent(NULL);
+ 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;
+ }
+
+ repaintEvent(nullptr);
}
-void GUI::ListBoxBasic::buttonEvent(ButtonEvent *e)
+void ListBoxBasic::buttonEvent(ButtonEvent* buttonEvent)
{
- if(e->x > ((int)width() - btn_size) && e->y < ((int)width() - 1)) {
- if(e->y > 0 && e->y < btn_size) {
- if(e->direction == -1) return;
- scroll.setValue(scroll.value() - 1);
- return;
- }
-
- if(e->y > ((int)height() - btn_size) && e->y < ((int)height() - 1)) {
- if(e->direction == -1) return;
- scroll.setValue(scroll.value() + 1);
- return;
- }
- }
-
- if(e->direction == -1) {
- int skip = scroll.value();
- size_t yoffset = padding / 2;
- for(int idx = skip; idx < (int)items.size(); idx++) {
- yoffset += font.textHeight() + padding;
- if(e->y < (int)yoffset - (padding / 2)) {
- setSelection(idx);
- marked = selected;
- if(clk_handler) clk_handler(clk_ptr);
- break;
- }
- }
-
- repaintEvent(NULL);
- }
-
- if(e->direction != -1) {
- int skip = scroll.value();
- size_t yoffset = padding / 2;
- for(int idx = skip; idx < (int)items.size(); idx++) {
- yoffset += font.textHeight() + padding;
- if(e->y < (int)yoffset - (padding / 2)) {
- marked = idx;
- break;
- }
- }
-
- repaintEvent(NULL);
- }
-
- if(e->doubleclick && sel_handler) sel_handler(sel_ptr);
+ 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;
+ }
+ }
+
+ repaintEvent(nullptr);
+ }
+
+ 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;
+ }
+ }
+
+ repaintEvent(nullptr);
+ }
+
+ if(buttonEvent->doubleClick)
+ {
+ selectionNotifier();
+ }
}
-void GUI::ListBoxBasic::resize(int w, int h)
+void ListBoxBasic::resize(int w, int h)
{
- GUI::Widget::resize(w,h);
- scroll.move(w - scroll.width(), 0);
- scroll.resize(scroll.width(), h);
+ Widget::resize(w,h);
+ scroll.move(w - scroll.width(), 0);
+ scroll.resize(scroll.width(), h);
}
+
+} // GUI::
diff --git a/plugingui/listboxbasic.h b/plugingui/listboxbasic.h
index deb4a67..3a190da 100644
--- a/plugingui/listboxbasic.h
+++ b/plugingui/listboxbasic.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_LISTBOXBASIC_H__
-#define __DRUMGIZMO_LISTBOXBASIC_H__
+#pragma once
#include <string.h>
#include <vector>
@@ -33,69 +32,62 @@
#include "widget.h"
#include "font.h"
#include "painter.h"
-
#include "scrollbar.h"
+#include "notifier.h"
namespace GUI {
class ListBoxBasic : public Widget {
public:
- class Item {
- public:
- std::string name;
- std::string value;
- };
-
- ListBoxBasic(Widget *parent);
- ~ListBoxBasic();
-
- bool isFocusable() { return true; }
+ class Item {
+ public:
+ std::string name;
+ std::string value;
+ };
- void addItem(std::string name, std::string value);
- void addItems(std::vector<Item> &items);
+ ListBoxBasic(Widget *parent);
+ ~ListBoxBasic();
- void clear();
- bool selectItem(int index);
- std::string selectedName();
- std::string selectedValue();
+ void addItem(const std::string& name, const std::string& value);
+ void addItems(const std::vector<Item>& items);
- void clearSelectedValue();
+ void clear();
+ bool selectItem(int index);
+ std::string selectedName();
+ std::string selectedValue();
- void registerSelectHandler(void (*handler)(void *), void *ptr);
- void registerClickHandler(void (*handler)(void *), void *ptr);
- void registerValueChangeHandler(void (*handler)(void *), void *ptr);
+ void clearSelectedValue();
- virtual void repaintEvent(RepaintEvent *e);
- virtual void buttonEvent(ButtonEvent *e);
- virtual void scrollEvent(ScrollEvent *e);
- virtual void keyEvent(KeyEvent *e);
- virtual void resize(int w, int h);
+ Notifier<> selectionNotifier;
+ Notifier<> clickNotifier;
+ Notifier<> valueChangedNotifier;
-private:
- ScrollBar scroll;
+ // From Widget:
+ virtual void resize(int w, int h) override;
- Image bg_img;
+protected:
+ void onScrollBarValueChange(int value);
- void setSelection(int index);
+ // 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;
- std::vector<Item> items;
+ ScrollBar scroll;
- int selected;
- int marked;
- GUI::Font font;
- int padding;
- int btn_size;
+ Image bg_img;
- void (*sel_handler)(void *);
- void *sel_ptr;
+ void setSelection(int index);
- void (*clk_handler)(void *);
- void *clk_ptr;
-
- void (*valch_handler)(void *);
- void *valch_ptr;
-};
+ std::vector<Item> items;
+ int selected;
+ int marked;
+ Font font;
+ int padding;
+ int btn_size;
};
-#endif/*__DRUMGIZMO_LISTBOXBASIC_H__*/
+} // GUI::
diff --git a/plugingui/listboxthin.cc b/plugingui/listboxthin.cc
index 3f0fbc6..16ea49e 100644
--- a/plugingui/listboxthin.cc
+++ b/plugingui/listboxthin.cc
@@ -29,90 +29,92 @@
#include "painter.h"
#include "font.h"
-#include <stdio.h>
-
-GUI::ListBoxThin::ListBoxThin(GUI::Widget *parent)
- : GUI::Widget(parent)
+namespace GUI {
+
+ListBoxThin::ListBoxThin(Widget *parent)
+ : Widget(parent)
+ , selectionNotifier(basic.selectionNotifier)
+ , clickNotifier(basic.clickNotifier)
+ , valueChangedNotifier(basic.valueChangedNotifier)
+ , basic(this)
{
- box.topLeft = new Image(":thinlistbox_tl.png");
- box.top = new Image(":thinlistbox_t.png");
- box.topRight = new Image(":thinlistbox_tr.png");
- box.left = new Image(":thinlistbox_l.png");
- box.right = new Image(":thinlistbox_r.png");
- box.bottomLeft = new Image(":thinlistbox_bl.png");
- box.bottom = new Image(":thinlistbox_b.png");
- box.bottomRight = new Image(":thinlistbox_br.png");
- box.center = new Image(":thinlistbox_c.png");
-
- basic = new GUI::ListBoxBasic(this);
- basic->move(box.left->width(), box.top->height());
+ box.topLeft = new Image(":thinlistbox_tl.png");
+ box.top = new Image(":thinlistbox_t.png");
+ box.topRight = new Image(":thinlistbox_tr.png");
+ box.left = new Image(":thinlistbox_l.png");
+ box.right = new Image(":thinlistbox_r.png");
+ box.bottomLeft = new Image(":thinlistbox_bl.png");
+ box.bottom = new Image(":thinlistbox_b.png");
+ box.bottomRight = new Image(":thinlistbox_br.png");
+ box.center = new Image(":thinlistbox_c.png");
+
+ basic.move(box.left->width(), box.top->height());
}
-GUI::ListBoxThin::~ListBoxThin()
+ListBoxThin::~ListBoxThin()
{
+ delete box.topLeft;
+ delete box.top;
+ delete box.topRight;
+ delete box.left;
+ delete box.right;
+ delete box.bottomLeft;
+ delete box.bottom;
+ delete box.bottomRight;
+ delete box.center;
}
-void GUI::ListBoxThin::addItem(std::string name, std::string value)
+void ListBoxThin::addItem(std::string name, std::string value)
{
- basic->addItem(name, value);
+ basic.addItem(name, value);
}
-void GUI::ListBoxThin::addItems(std::vector<ListBoxBasic::Item> &items)
+void ListBoxThin::addItems(std::vector<ListBoxBasic::Item> &items)
{
- basic->addItems(items);
+ basic.addItems(items);
}
-void GUI::ListBoxThin::clear()
+void ListBoxThin::clear()
{
- basic->clear();
+ basic.clear();
}
-bool GUI::ListBoxThin::selectItem(int index)
+bool ListBoxThin::selectItem(int index)
{
- return basic->selectItem(index);
+ return basic.selectItem(index);
}
-std::string GUI::ListBoxThin::selectedName()
+std::string ListBoxThin::selectedName()
{
- return basic->selectedName();
+ return basic.selectedName();
}
-std::string GUI::ListBoxThin::selectedValue()
+std::string ListBoxThin::selectedValue()
{
- return basic->selectedValue();
+ return basic.selectedValue();
}
-void GUI::ListBoxThin::registerClickHandler(void (*handler)(void *), void *ptr)
+void ListBoxThin::repaintEvent(RepaintEvent* repaintEvent)
{
- basic->registerClickHandler(handler, ptr);
-}
+ Painter p(*this);
-void GUI::ListBoxThin::registerSelectHandler(void (*handler)(void *), void *ptr)
-{
- basic->registerSelectHandler(handler, ptr);
-}
+ p.clear();
-void GUI::ListBoxThin::registerValueChangeHandler(void (*handler)(void *),
- void *ptr)
-{
- basic->registerValueChangeHandler(handler, ptr);
-}
+ int w = width();
+ int h = height();
+ if(w == 0 || h == 0)
+ {
+ return;
+ }
-void GUI::ListBoxThin::repaintEvent(GUI::RepaintEvent *e)
-{
- GUI::Painter p(this);
-
- p.clear();
-
- int w = width();
- int h = height();
- if(w == 0 || h == 0) return;
- p.drawBox(0, 0, &box, w, h);
+ p.drawBox(0, 0, box, w, h);
}
-void GUI::ListBoxThin::resize(int width, int height)
+void ListBoxThin::resize(int width, int height)
{
- GUI::Widget::resize(width, height);
- basic->resize(width - (box.left->width() + box.right->width()),
- height - (box.top->height() + box.bottom->height()));
+ Widget::resize(width, height);
+ basic.resize(width - (box.left->width() + box.right->width()),
+ height - (box.top->height() + box.bottom->height()));
}
+
+} // GUI::
diff --git a/plugingui/listboxthin.h b/plugingui/listboxthin.h
index 9c5363a..bc9399b 100644
--- a/plugingui/listboxthin.h
+++ b/plugingui/listboxthin.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_LISTBOXTHIN_H__
-#define __DRUMGIZMO_LISTBOXTHIN_H__
+#pragma once
#include <string.h>
#include <vector>
@@ -33,35 +32,36 @@
#include "widget.h"
#include "painter.h"
#include "listboxbasic.h"
+#include "notifier.h"
namespace GUI {
class ListBoxThin : public Widget {
public:
- ListBoxThin(Widget *parent);
- ~ListBoxThin();
+ ListBoxThin(Widget *parent);
+ ~ListBoxThin();
- void addItem(std::string name, std::string value);
- void addItems(std::vector<ListBoxBasic::Item> &items);
+ void addItem(std::string name, std::string value);
+ void addItems(std::vector<ListBoxBasic::Item> &items);
- void clear();
- bool selectItem(int index);
- std::string selectedName();
- std::string selectedValue();
+ void clear();
+ bool selectItem(int index);
+ std::string selectedName();
+ std::string selectedValue();
- void registerSelectHandler(void (*handler)(void *), void *ptr);
- void registerClickHandler(void (*handler)(void *), void *ptr);
- void registerValueChangeHandler(void (*handler)(void *), void *ptr);
+ // From Widget:
+ virtual void repaintEvent(GUI::RepaintEvent* repaintEvent) override;
+ virtual void resize(int w, int h) override;
- virtual void repaintEvent(GUI::RepaintEvent *e);
- virtual void resize(int w, int h);
+ // Forwarded notifier from ListBoxBasic::basic
+ Notifier<>& selectionNotifier;
+ Notifier<>& clickNotifier;
+ Notifier<>& valueChangedNotifier;
private:
- ListBoxBasic *basic;
+ ListBoxBasic basic;
- Painter::Box box;
+ Painter::Box box;
};
-};
-
-#endif/*__DRUMGIZMO_LISTBOXTHIN_H__*/
+} // GUI::
diff --git a/plugingui/nativewindow.h b/plugingui/nativewindow.h
index d68909d..a44693c 100644
--- a/plugingui/nativewindow.h
+++ b/plugingui/nativewindow.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_NATIVEWINDOW_H__
-#define __DRUMGIZMO_NATIVEWINDOW_H__
+#pragma once
#include <string>
@@ -33,25 +32,53 @@
namespace GUI {
+//! \brief Interface class for native window implementations.
class NativeWindow {
public:
- NativeWindow() {}
- virtual ~NativeWindow() {}
-
- virtual void setFixedSize(int width, int height) = 0;
- virtual void resize(int width, int height) = 0;
- virtual void move(int x, int y) = 0;
- virtual void show() = 0;
- virtual void setCaption(const std::string &caption) = 0;
- virtual void hide() = 0;
- virtual void handleBuffer() = 0;
- virtual void redraw() = 0;
- virtual void grabMouse(bool grab) = 0;
-
- virtual bool hasEvent() = 0;
- virtual Event *getNextEvent() = 0;
-};
+ NativeWindow() {}
+ virtual ~NativeWindow() {}
+
+ //! \brief Set a fixed size to the window.
+ //! It resizes the window and disallows user resizing.
+ virtual void setFixedSize(int width, int height) = 0;
+
+ // TODO: setScalable(bool) ??
+
+ //! \brief Set a new size of the window.
+ virtual void resize(int width, int height) = 0;
+
+ //! \brief Move the window to a new position.
+ virtual void move(int x, int y) = 0;
+
+ //! \brief Show the window if it is hidden.
+ virtual void show() = 0;
+
+ //! \brief Hides the window.
+ virtual void hide() = 0;
+
+ //! \brief Sets the window caption in the title bar (if it has one).
+ virtual void setCaption(const std::string &caption) = 0;
+
+ //! \brief Recreate a window render buffer based on the internal buffer.
+ //! This need to be called whenever the internal buffer size has changed.
+ virtual void handleBuffer() = 0;
+
+ //! \brief Draw the internal rendering buffer to the window buffer.
+ virtual void redraw() = 0;
+
+ //! \brief Toggle capture mouse mode.
+ virtual void grabMouse(bool grab) = 0;
+
+ //! \brief Query if the event queue contains any events.
+ virtual bool hasEvent() = 0;
+
+ //! \brief Read a single event from the event queue.
+ //! \return A pointer to the event or nullptr is none exists.
+ virtual Event *getNextEvent() = 0;
+ //! \brief Read next event without popping it from the event queue.
+ //! \return A pointer to the event or nullptr is none exists.
+ virtual Event* peekNextEvent() = 0;
};
-#endif/*__DRUMGIZMO_NATIVEWINDOW_H__*/
+} // GUI::
diff --git a/plugingui/nativewindow_pugl.cc b/plugingui/nativewindow_pugl.cc
index 45cddab..b9dcd54 100644
--- a/plugingui/nativewindow_pugl.cc
+++ b/plugingui/nativewindow_pugl.cc
@@ -29,184 +29,228 @@
#include <stdlib.h>
#include <list>
-#include "hugin.hpp"
+#ifdef __APPLE__
+#include <OpenGL/glu.h>
+#else
+#include <GL/glu.h>
+#include <GL/glext.h>
+#include <GL/gl.h>
+#endif
+
+#include "window.h"
#include "guievent.h"
-static GUI::Window* windowptr;
-static std::list<GUI::Event*> eventq;
+#include <hugin.hpp>
-static void onDisplay(PuglView* view)
+namespace GUI {
+
+void NativeWindowPugl::onDisplay(PuglView* view)
{
+ NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view);
+ Window* windowptr = native->window;
- glDisable(GL_DEPTH_TEST);
- glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT);
- GLuint image;
+ GLuint image;
- glGenTextures(1, &image);
+ glGenTextures(1, &image);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ 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_LINEAR); //GL_NEAREST = no smoothing
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //GL_NEAREST = no smoothing
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, windowptr->wpixbuf.width,
- windowptr->wpixbuf.height, 0, GL_RGB, GL_UNSIGNED_BYTE,
- windowptr->wpixbuf.buf);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, windowptr->wpixbuf.width,
+ windowptr->wpixbuf.height, 0, GL_RGB, GL_UNSIGNED_BYTE,
+ windowptr->wpixbuf.buf);
- glEnable(GL_TEXTURE_2D);
-
- glBegin(GL_QUADS);
- glTexCoord2d(0.0, 0.0); glVertex2f(0.0, 0.0);
- glTexCoord2d(0.0, 1.0); glVertex2f(0.0, windowptr->wpixbuf.height);
- glTexCoord2d(1.0, 1.0); glVertex2f(windowptr->wpixbuf.width, windowptr->wpixbuf.height);
- glTexCoord2d(1.0, 0.0); glVertex2f(windowptr->wpixbuf.width, 0.0);
- glEnd();
+ glEnable(GL_TEXTURE_2D);
- glDeleteTextures(1, &image);
- glDisable(GL_TEXTURE_2D);
- glFlush();
-
- puglPostRedisplay(view);
-}
+ glBegin(GL_QUADS);
+ glTexCoord2d(0.0, 0.0); glVertex2f(0.0, 0.0);
+ glTexCoord2d(0.0, 1.0); glVertex2f(0.0, windowptr->wpixbuf.height);
+ glTexCoord2d(1.0, 1.0); glVertex2f(windowptr->wpixbuf.width, windowptr->wpixbuf.height);
+ glTexCoord2d(1.0, 0.0); glVertex2f(windowptr->wpixbuf.width, 0.0);
+ glEnd();
-static void onMouse(PuglView* view, int button, bool press, int x, int y)
-{
- DEBUG(nativewindow_pugl, "Mouse %d %s at (%d,%d)\n", button,
- press? "down":"up", x, y);
+ glDeleteTextures(1, &image);
+ glDisable(GL_TEXTURE_2D);
+ glFlush();
- GUI::ButtonEvent* e = new GUI::ButtonEvent();
- e->x = x;
- e->y = y;
- e->button = button;
- e->direction = press?1:-1;
- e->doubleclick = false;
+ puglPostRedisplay(view);
+}
- eventq.push_back(e);
+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);
}
-static void onKeyboard(PuglView* view, bool press, uint32_t key)
+void NativeWindowPugl::onKeyboard(PuglView* view, bool press, uint32_t key)
{
- if(press) {
- GUI::KeyEvent* e = new GUI::KeyEvent();
- e->direction = press?-1:1;
+ NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view);
+
+ KeyEvent* e = new KeyEvent();
+ e->direction = press ? Direction::down : Direction::up;
+
+ printf("%d\n", key);
- printf("%d\n", key);
-
- switch(key) {
- case PUGL_KEY_LEFT: e->keycode = GUI::KeyEvent::KEY_LEFT; break;
- case PUGL_KEY_RIGHT: e->keycode = GUI::KeyEvent::KEY_RIGHT; break;
- case PUGL_KEY_UP: e->keycode = GUI::KeyEvent::KEY_UP; break;
- case PUGL_KEY_DOWN: e->keycode = GUI::KeyEvent::KEY_DOWN; break;
- case PUGL_KEY_PAGE_UP: e->keycode = GUI::KeyEvent::KEY_PGDOWN; break;
- case PUGL_KEY_PAGE_DOWN: e->keycode = GUI::KeyEvent::KEY_PGUP; break;
- default: e->keycode = GUI::KeyEvent::KEY_UNKNOWN; break;
- }
+ 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 == GUI::KeyEvent::KEY_UNKNOWN) {
- e->keycode = GUI::KeyEvent::KEY_CHARACTER;
- e->text.assign(1, (char)key);
- }
+ // TODO: perform character type check
+ if(e->keycode == Key::unknown)
+ {
+ e->keycode = Key::character;
+ e->text.assign(1, (char)key);
+ }
- printf("\t text: %s\n", e->text.c_str());
-
- eventq.push_back(e);
- }
+ printf("\t text: %s\n", e->text.c_str());
+
+ native->eventq.push_back(e);
}
-GUI::NativeWindowPugl::NativeWindowPugl(GUI::Window *window)
- : GUI::NativeWindow()
+NativeWindowPugl::NativeWindowPugl(Window *window)
+ : window(window)
{
- INFO(nativewindow, "Running with PuGL native window\n");
- this->window = window;
- windowptr = window;
- view = NULL;
- init();
+ INFO(nativewindow, "Running with PuGL native window\n");
+ init();
}
-GUI::NativeWindowPugl::~NativeWindowPugl()
+NativeWindowPugl::~NativeWindowPugl()
{
- puglDestroy(view);
+ puglDestroy(view);
}
-void GUI::NativeWindowPugl::init() {
- PuglView* old = view;
- if(view) old = view;
-// view = puglCreate(0, "DrumgGizmo", window->x(), window->y(), false, true);
- view = puglCreate(0, "DrumgGizmo", 370, 330, false, true);
- puglSetDisplayFunc(view, onDisplay);
- puglSetMouseFunc(view, onMouse);
- puglSetKeyboardFunc(view, onKeyboard);
+void NativeWindowPugl::init() {
+ PuglView* oldView = view;
+ if(view)
+ {
+ oldView = view;
+ }
+
+// view = puglCreate(0, "DrumgGizmo", window->x(), window->y(), false, true);
+ view = puglCreate(0, "DrumgGizmo", 370, 330, false, true);
+ puglSetHandle(view, (PuglHandle)this);
+ puglSetDisplayFunc(view, onDisplay);
+ puglSetMouseFunc(view, onMouse);
+ puglSetKeyboardFunc(view, onKeyboard);
+
+ if(oldView)
+ {
+ free(oldView);
+ }
+}
- if(old) free(old);
+void NativeWindowPugl::setFixedSize(int width, int height)
+{
+// redraw();
}
-void GUI::NativeWindowPugl::setFixedSize(int width, int height)
+void NativeWindowPugl::resize(int width, int height)
{
-// redraw();
+// DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height);
+// init();
+// redraw();
}
-void GUI::NativeWindowPugl::resize(int width, int height)
+void NativeWindowPugl::move(int x, int y)
{
-// DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height);
-// init();
-// redraw();
+// redraw();
}
-void GUI::NativeWindowPugl::move(int x, int y)
+void NativeWindowPugl::show()
{
-// redraw();
+// redraw();
}
-void GUI::NativeWindowPugl::show()
+void NativeWindowPugl::hide()
{
-// redraw();
+// redraw();
}
-void GUI::NativeWindowPugl::hide()
+void NativeWindowPugl::handleBuffer()
{
-// redraw();
+ onDisplay(view);
}
-void GUI::NativeWindowPugl::handleBuffer()
+void NativeWindowPugl::redraw()
{
- onDisplay(view);
+// handleBuffer();
}
-void GUI::NativeWindowPugl::redraw()
+void NativeWindowPugl::setCaption(const std::string &caption)
{
-// handleBuffer();
+// redraw();
}
-void GUI::NativeWindowPugl::setCaption(const std::string &caption)
+void NativeWindowPugl::grabMouse(bool grab)
{
-// redraw();
+// redraw();
}
-void GUI::NativeWindowPugl::grabMouse(bool grab)
+bool NativeWindowPugl::hasEvent()
{
-// redraw();
+ // dirty hack - assume that this function is called enough times to get fluent gui
+ // ^^ Bad assumption
+ puglProcessEvents(view);
+ return !eventq.empty();
}
-bool GUI::NativeWindowPugl::hasEvent()
+Event *NativeWindowPugl::getNextEvent()
{
- // dirty hack - assume that this function is called enough times to get fluent gui
- // ^^ Bad assumption
- puglProcessEvents(view);
- return !eventq.empty();
+ Event *event = nullptr;
+
+ if(!eventq.empty()) {
+ event = eventq.front();
+ eventq.pop_front();
+ }
+ return event;
}
-GUI::Event *GUI::NativeWindowPugl::getNextEvent()
+Event *NativeWindowPugl::peekNextEvent()
{
- Event *event = NULL;
-
- if(!eventq.empty()) {
- event = eventq.front();
- eventq.pop_front();
- }
- return event;
+ Event *event = nullptr;
+
+ if(!eventq.empty()) {
+ event = eventq.front();
+ }
+ return event;
}
+
+} // GUI::
diff --git a/plugingui/nativewindow_pugl.h b/plugingui/nativewindow_pugl.h
index cf761fd..335e7e4 100644
--- a/plugingui/nativewindow_pugl.h
+++ b/plugingui/nativewindow_pugl.h
@@ -24,49 +24,48 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_NATIVEWINDOW_PUGL_H__
-#define __DRUMGIZMO_NATIVEWINDOW_PUGL_H__
-#endif/*__DRUMGIZMO_NATIVEWINDOW_PUGL_H__*/
+#pragma once
#include "nativewindow.h"
-
-#include "window.h"
-
#include "pugl.h"
-#ifdef __APPLE__
-# include <OpenGL/glu.h>
-#else
-# include <GL/glu.h>
-# include <GL/glext.h>
-# include <GL/gl.h>
-#endif
+#include <list>
namespace GUI {
+class Event;
class Window;
+
class NativeWindowPugl : public NativeWindow {
public:
- NativeWindowPugl(GUI::Window *window);
- ~NativeWindowPugl();
+ NativeWindowPugl(Window *window);
+ ~NativeWindowPugl();
- void init();
- void setFixedSize(int width, int height);
- void resize(int width, int height);
- void move(int x, int y);
- void show();
- void setCaption(const std::string &caption);
- void hide();
- void handleBuffer();
- void redraw();
- void grabMouse(bool grab);
+ void init();
+ void setFixedSize(int width, int height);
+ void resize(int width, int height);
+ void move(int x, int y);
+ void show();
+ void setCaption(const std::string &caption);
+ void hide();
+ void handleBuffer();
+ void redraw();
+ void grabMouse(bool grab);
- bool hasEvent();
- Event *getNextEvent();
+ bool hasEvent();
+ Event *getNextEvent();
+ Event *peekNextEvent();
private:
- GUI::Window *window;
- PuglView* view;
-};
+ Window* window{nullptr};
+ PuglView* view{nullptr};
+
+ std::list<Event*> eventq;
+ // Internal pugl c-callbacks
+ 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);
};
+
+} // GUI::
diff --git a/plugingui/nativewindow_win32.cc b/plugingui/nativewindow_win32.cc
index 871bafe..cf39010 100644
--- a/plugingui/nativewindow_win32.cc
+++ b/plugingui/nativewindow_win32.cc
@@ -26,49 +26,56 @@
*/
#include "nativewindow_win32.h"
-#ifdef WIN32
-
#include "window.h"
-LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+#include <cstring>
+
+namespace GUI {
+
+LRESULT CALLBACK NativeWindowWin32::dialogProc(HWND hwnd, UINT msg,
+ WPARAM wp, LPARAM lp)
{
- GUI::NativeWindowWin32 *native =
- (GUI::NativeWindowWin32 *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ NativeWindowWin32* native =
+ (NativeWindowWin32*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
- // NOTE: 'native' is NULL intil the WM_CREATE message has been handled.
- if(!native) return DefWindowProc(hwnd, msg, wp, lp);
+ // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled.
+ if(!native)
+ {
+ return DefWindowProc(hwnd, msg, wp, lp);
+ }
- GUI::Window *window = native->window;
+ Window& window = native->window;
switch(msg) {
case WM_SIZE:
- {
- static bool first = true;
- if(!first) {
- GUI::ResizeEvent *e = new GUI::ResizeEvent();
- e->width = LOWORD(lp);
- e->height = HIWORD(lp);
- native->event = e;
- first = false;
- }
- }
+ {
+ static bool first = true;
+ if(!first)
+ {
+ ResizeEvent* resizeEvent = new ResizeEvent();
+ resizeEvent->width = LOWORD(lp);
+ resizeEvent->height = HIWORD(lp);
+ native->event = resizeEvent;
+ first = false;
+ }
+ }
break;
case WM_MOVE:
- {
-// GUI::MoveEvent *e = new GUI::MoveEvent();
-// e->x = (int)(short) LOWORD(lp);
-// e->y = (int)(short) HIWORD(lp);
-// native->event = e;
- }
+ {
+// MoveEvent* moveEvent = new MoveEvent();
+// moveEvent->x = (short)LOWORD(lp);
+// moveEvent->y = (short)HIWORD(lp);
+// native->event = moveEvent;
+ }
break;
case WM_CLOSE:
- {
- GUI::CloseEvent *e = new GUI::CloseEvent();
- native->event = e;
- }
- break;
+ {
+ CloseEvent* closeEvent = new CloseEvent();
+ native->event = closeEvent;
+ }
+ break;
// HWND child, old;
// old = 0;
@@ -83,31 +90,30 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
// else PostQuitMessage(0);
// return 0;
case WM_MOUSEMOVE:
- {
-
- GUI::MouseMoveEvent *e = new GUI::MouseMoveEvent();
- e->x = (int)(short) LOWORD(lp);
- e->y = (int)(short) HIWORD(lp);
- native->event = e;
- }
+ {
+ MouseMoveEvent* mouseMoveEvent = new MouseMoveEvent();
+ mouseMoveEvent->x = (short)LOWORD(lp);
+ mouseMoveEvent->y = (short)HIWORD(lp);
+ native->event = mouseMoveEvent;
+ }
break;
case WM_MOUSEWHEEL:
- {
- GUI::ScrollEvent *e = new GUI::ScrollEvent();
-
- // NOTE: lp is coordinates in screen space, not client space.
- POINT p;
- p.x = (int)(short) LOWORD(lp);
- p.y = (int)(short) HIWORD(lp);
- ScreenToClient(hwnd, &p);
-
- e->x = p.x;
- e->y = p.y;
- e->delta = -1 * (short)HIWORD(wp) / 60;
- native->event = e;
- }
- break;
+ {
+ ScrollEvent* scrollEvent = new ScrollEvent();
+
+ // 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;
+ native->event = scrollEvent;
+ }
+ break;
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
@@ -118,283 +124,324 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
case WM_MBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN:
- {
- GUI::ButtonEvent *e = new GUI::ButtonEvent();
- e->x = (int)(short) LOWORD(lp);
- e->y = (int)(short) HIWORD(lp);
-
- if(msg == WM_LBUTTONUP ||
- msg == WM_LBUTTONDBLCLK ||
- msg == WM_LBUTTONDOWN) e->button = 0;
-
- if(msg == WM_RBUTTONUP ||
- msg == WM_RBUTTONDBLCLK ||
- msg == WM_RBUTTONDOWN) e->button = 1;
-
- if(msg == WM_MBUTTONUP ||
- msg == WM_MBUTTONDBLCLK ||
- msg == WM_MBUTTONDOWN) e->button = 2;
-
- e->direction = 0;
- if(msg == WM_LBUTTONUP ||
- msg == WM_RBUTTONUP ||
- msg == WM_MBUTTONUP) e->direction = -1;
-
- if(msg == WM_LBUTTONDOWN ||
- msg == WM_RBUTTONDOWN ||
- msg == WM_MBUTTONDOWN) e->direction = 1;
-
- e->doubleclick = (msg == WM_LBUTTONDBLCLK ||
- msg == WM_RBUTTONDBLCLK ||
- msg == WM_MBUTTONDBLCLK);
-
- native->event = e;
- }
+ {
+ ButtonEvent* buttonEvent = new ButtonEvent();
+
+ 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_RBUTTONUP ||
+ msg == WM_RBUTTONDBLCLK ||
+ msg == WM_RBUTTONDOWN)
+ {
+ buttonEvent->button = MouseButton::middle;
+ }
+ else if(msg == WM_MBUTTONUP ||
+ msg == WM_MBUTTONDBLCLK ||
+ msg == WM_MBUTTONDOWN)
+ {
+ buttonEvent->button = MouseButton::right;
+ }
+ else
+ {
+ delete buttonEvent;
+ break; // unknown button
+ }
+
+ 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)
+ {
+ buttonEvent->direction = Direction::down;
+ }
+
+ buttonEvent->doubleClick = (msg == WM_LBUTTONDBLCLK ||
+ msg == WM_RBUTTONDBLCLK ||
+ msg == WM_MBUTTONDBLCLK);
+
+ native->event = buttonEvent;
+ }
break;
case WM_KEYDOWN:
- {
- GUI::KeyEvent *e = new GUI::KeyEvent();
- //printf("wp: %d\n", wp);
- switch(wp) {
- case 37: e->keycode = GUI::KeyEvent::KEY_LEFT; break;
- case 39: e->keycode = GUI::KeyEvent::KEY_RIGHT; break;
- case 38: e->keycode = GUI::KeyEvent::KEY_UP; break;
- case 40: e->keycode = GUI::KeyEvent::KEY_DOWN; break;
- case 8: e->keycode = GUI::KeyEvent::KEY_BACKSPACE; break;
- case 46: e->keycode = GUI::KeyEvent::KEY_DELETE; break;
- case 36: e->keycode = GUI::KeyEvent::KEY_HOME; break;
- case 35: e->keycode = GUI::KeyEvent::KEY_END; break;
- case 33: e->keycode = GUI::KeyEvent::KEY_PGUP; break;
- case 34: e->keycode = GUI::KeyEvent::KEY_PGDOWN; break;
- case 13: e->keycode = GUI::KeyEvent::KEY_ENTER; break;
- default: e->keycode = GUI::KeyEvent::KEY_UNKNOWN; break;
- }
- e->text = "";
- e->direction = -1;
- native->event = e;
- }
+ case WM_KEYUP:
+ {
+ KeyEvent* keyEvent = new KeyEvent();
+
+ 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 = keyEvent;
+ }
break;
case WM_CHAR:
- {
- //printf("WM_CHAR %d %d\n", (int)lp, (int)wp);
- if(wp >= ' ') { // Filter control chars.
- GUI::KeyEvent *e = new GUI::KeyEvent();
- e->keycode = GUI::KeyEvent::KEY_CHARACTER;
- e->text += (char)wp;
- e->direction = -1;
- native->event = e;
- }
- }
+ {
+ if(wp >= ' ') // Filter control chars.
+ {
+ KeyEvent* keyEvent = new KeyEvent();
+ keyEvent->keycode = Key::character;
+ keyEvent->text += (char)wp;
+ keyEvent->direction = Direction::up;
+ native->event = keyEvent;
+ }
+ }
break;
case WM_PAINT:
- {
- GUI::RepaintEvent *e = new GUI::RepaintEvent();
- e->x = 0;
- e->y = 0;
- e->width = 100;
- e->height = 100;
- native->event = e;
-
- // Move to window.h (in class)
- HDC pDC;
- HBITMAP old;
- HBITMAP ourbitmap;
- int * framebuf;
- GUI::PixelBuffer &px = window->wpixbuf;
-
- { // Create bitmap (move to window.cc)
- HDC hDC;
- BITMAPINFO bitmapinfo;
- hDC = CreateCompatibleDC(NULL);
- 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(NULL);
- old = (HBITMAP__*)SelectObject(pDC, ourbitmap);
- DeleteDC(hDC);
- }
-
- { // Copy GUI::PixelBuffer to framebuffer (move to window.cc)
- int i,j,k;
- for (k=0,i=0;i<(int)px.height;i++) {
- for (j=0;j<(int)px.width;j++,k++) {
- *(framebuf+k)=RGB(px.buf[(j + i * px.width) * 3 + 2],
- px.buf[(j + i * px.width) * 3 + 1],
- px.buf[(j + i * px.width) * 3 + 0]);
- }
- }
- }
-
- PAINTSTRUCT ps;
- HDC hdc = BeginPaint(native->m_hwnd, &ps);
- BitBlt(hdc, 0, 0, px.width, px.height, pDC, 0, 0, SRCCOPY);
- EndPaint(native->m_hwnd, &ps);
-
- { // Destroy bitmap (move to window.cc)
- SelectObject(pDC,old);
- DeleteDC(pDC);
- DeleteObject(ourbitmap);
-
- }
- }
+ {
+ RepaintEvent* repaintEvent = new RepaintEvent();
+ repaintEvent->x = 0;
+ repaintEvent->y = 0;
+ repaintEvent->width = 100;
+ repaintEvent->height = 100;
+ native->event = 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);
+ }
+
+ { // Copy PixelBuffer to framebuffer
+ int i, j, k;
+ for(k = 0, i = 0; i < (int)px.height; ++i)
+ {
+ for(j = 0; j < (int)px.width; ++j, ++k)
+ {
+ *(framebuf + k) = RGB(px.buf[(j + i * px.width) * 3 + 2],
+ px.buf[(j + i * px.width) * 3 + 1],
+ px.buf[(j + i * px.width) * 3 + 0]);
+ }
+ }
+ }
+
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(native->m_hwnd, &ps);
+ BitBlt(hdc, 0, 0, px.width, px.height, pDC, 0, 0, SRCCOPY);
+ EndPaint(native->m_hwnd, &ps);
+
+ { // Destroy bitmap (move to window.cc)
+ SelectObject(pDC,old);
+ DeleteDC(pDC);
+ DeleteObject(ourbitmap);
+ }
+ }
+
return DefWindowProc(hwnd, msg, wp, lp);
}
return DefWindowProc(hwnd, msg, wp, lp);
}
-// Delared in eventhandler.cc
-LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
-
-GUI::NativeWindowWin32::NativeWindowWin32(GUI::Window *window)
- : GUI::NativeWindow()
+NativeWindowWin32::NativeWindowWin32(Window& window)
+ : window(window)
{
- this->window = window;
-
WNDCLASSEX wcex;
WNDID wndId;
- m_hwnd = 0;
- m_className = NULL;
- event = NULL;
+ std::memset(&wcex, 0, sizeof(wcex));
- memset(&wcex, 0, sizeof(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.
-
+ //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(NULL, IDC_ARROW);
- // Set data:
+ wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ // Set data:
wcex.cbWndExtra = sizeof(NativeWindowWin32*); // Size of data.
- wcex.hInstance = GetModuleHandle(NULL);
+ wcex.hInstance = GetModuleHandle(nullptr);
- // if(ex_style && WS_EX_TRANSPARENT == WS_EX_TRANSPARENT) {
- // wcex.hbrBackground = NULL;
- // } else {
- wcex.hbrBackground = NULL;//(HBRUSH) COLOR_BACKGROUND + 1;
- // }
-
- wcex.lpszClassName = m_className = strdup("DrumGizmoClass");
+ // 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);
- /*
+ /*
if(parent) {
style = style | WS_CHILD;
wndId = parent->getWndId();
} else {
- */
- //style = style | WS_OVERLAPPEDWINDOW;
- wndId = 0;
- // }
+ */
+ //style = style | WS_OVERLAPPEDWINDOW;
+ wndId = 0;
+ // }
m_hwnd = CreateWindowEx(0/*ex_style*/, m_className,
- "DGBasisWidget",
- (WS_OVERLAPPEDWINDOW | WS_VISIBLE),
- window->x(), window->y(),
- window->width(), window->height(),
- wndId, NULL,
- GetModuleHandle(NULL), NULL);
+ "DGBasisWidget",
+ (WS_OVERLAPPEDWINDOW | WS_VISIBLE),
+ window.x(), window.y(),
+ window.width(), window.height(),
+ wndId, nullptr,
+ GetModuleHandle(nullptr), nullptr);
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this);
}
-GUI::NativeWindowWin32::~NativeWindowWin32()
+NativeWindowWin32::~NativeWindowWin32()
{
- UnregisterClass(m_className, GetModuleHandle(NULL));
+ UnregisterClass(m_className, GetModuleHandle(nullptr));
free(m_className);
}
-void GUI::NativeWindowWin32::setFixedSize(int width, int height)
+void NativeWindowWin32::setFixedSize(int width, int height)
{
- resize(width, height);
- LONG style = GetWindowLong(m_hwnd, GWL_STYLE);
- style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
- SetWindowLong(m_hwnd, GWL_STYLE, style);
+ resize(width, height);
+ LONG style = GetWindowLong(m_hwnd, GWL_STYLE);
+ style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
+ SetWindowLong(m_hwnd, GWL_STYLE, style);
}
-void GUI::NativeWindowWin32::resize(int width, int height)
+void NativeWindowWin32::resize(int width, int height)
{
- SetWindowPos(m_hwnd, NULL, -1, -1, (int)width, (int)height, SWP_NOMOVE);
- RECT r;
- GetClientRect(m_hwnd, &r);
- int w = width - r.right;
- int h = height - r.bottom;
+ SetWindowPos(m_hwnd, nullptr, -1, -1, (int)width, (int)height, SWP_NOMOVE);
+ RECT r;
+ GetClientRect(m_hwnd, &r);
+ int w = width - r.right;
+ int h = height - r.bottom;
- SetWindowPos(m_hwnd, NULL, -1, -1, width + w, height + h, SWP_NOMOVE);
+ SetWindowPos(m_hwnd, nullptr, -1, -1, width + w, height + h, SWP_NOMOVE);
}
-void GUI::NativeWindowWin32::move(int x, int y)
+void NativeWindowWin32::move(int x, int y)
{
- SetWindowPos(m_hwnd, NULL, (int)x, (int)y, -1, -1, SWP_NOSIZE);
+ SetWindowPos(m_hwnd, nullptr, (int)x, (int)y, -1, -1, SWP_NOSIZE);
}
-void GUI::NativeWindowWin32::show()
+void NativeWindowWin32::show()
{
- ShowWindow(m_hwnd, SW_SHOW);
+ ShowWindow(m_hwnd, SW_SHOW);
}
-void GUI::NativeWindowWin32::handleBuffer()
+void NativeWindowWin32::handleBuffer()
{
}
-void GUI::NativeWindowWin32::hide()
+void NativeWindowWin32::hide()
{
- ShowWindow(m_hwnd, SW_HIDE);
+ ShowWindow(m_hwnd, SW_HIDE);
}
-void GUI::NativeWindowWin32::redraw()
+void NativeWindowWin32::redraw()
{
- RedrawWindow(m_hwnd, NULL, NULL, RDW_ERASE|RDW_INVALIDATE);
- UpdateWindow(m_hwnd);
+ RedrawWindow(m_hwnd, nullptr, nullptr, RDW_ERASE|RDW_INVALIDATE);
+ UpdateWindow(m_hwnd);
}
-void GUI::NativeWindowWin32::setCaption(const std::string &caption)
+void NativeWindowWin32::setCaption(const std::string &caption)
{
- SetWindowText(m_hwnd, caption.c_str());
+ SetWindowText(m_hwnd, caption.c_str());
+}
+
+void NativeWindowWin32::grabMouse(bool grab)
+{
+ if(grab)
+ {
+ SetCapture(m_hwnd);
+ }
+ else
+ {
+ ReleaseCapture();
+ }
}
-void GUI::NativeWindowWin32::grabMouse(bool grab)
+bool NativeWindowWin32::hasEvent()
{
- if(grab) SetCapture(m_hwnd);
- else ReleaseCapture();
+ MSG msg;
+ return PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE) != 0;
}
-bool GUI::NativeWindowWin32::hasEvent()
+Event* NativeWindowWin32::getNextEvent()
{
- MSG msg;
- return PeekMessage(&msg, NULL, 0, 0, 0) != 0;
+ Event* event = nullptr;
+
+ MSG msg;
+ if(GetMessage(&msg, nullptr, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ event = this->event;
+ this->event = nullptr;
+
+ return event;
}
-GUI::Event *GUI::NativeWindowWin32::getNextEvent()
+Event* NativeWindowWin32::peekNextEvent()
{
- Event *event = NULL;
+ Event* event = nullptr;
- MSG msg;
- if(GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
+ MSG msg;
+ if(PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
}
- event = this->event;
- this->event = NULL;
+ event = this->event;
+ this->event = nullptr;
- return event;
+ return event;
}
-#endif/*WIN32*/
+} // GUI::
diff --git a/plugingui/nativewindow_win32.h b/plugingui/nativewindow_win32.h
index 6afc7b1..fa4b6bc 100644
--- a/plugingui/nativewindow_win32.h
+++ b/plugingui/nativewindow_win32.h
@@ -24,13 +24,11 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_NATIVEWINDOW_WIN32_H__
-#define __DRUMGIZMO_NATIVEWINDOW_WIN32_H__
-
-#ifdef WIN32
+#pragma once
#include "nativewindow.h"
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef HWND WNDID;
@@ -41,31 +39,30 @@ class Event;
class NativeWindowWin32 : public NativeWindow {
public:
- NativeWindowWin32(GUI::Window *window);
- ~NativeWindowWin32();
+ NativeWindowWin32(Window& window);
+ ~NativeWindowWin32();
- void setFixedSize(int width, int height);
- void resize(int width, int height);
- void move(int x, int y);
- void show();
- void setCaption(const std::string &caption);
- void hide();
- void handleBuffer();
- void redraw();
- void grabMouse(bool grab);
+ void setFixedSize(int width, int height) override;
+ void resize(int width, int height) override;
+ void move(int x, int y) override;
+ void show() override;
+ void setCaption(const std::string &caption) override;
+ void hide() override;
+ void handleBuffer() override;
+ void redraw() override;
+ void grabMouse(bool grab) override;
- bool hasEvent();
- Event *getNextEvent();
+ bool hasEvent() override;
+ Event* getNextEvent() override;
+ Event* peekNextEvent() override;
- // Needed by dialogProc
- GUI::Window *window;
- WNDID m_hwnd;
- char *m_className;
- Event *event;
-};
+private:
+ static LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
+ Window& window;
+ WNDID m_hwnd = 0;
+ char* m_className = nullptr;
+ Event* event = nullptr;
};
-#endif/*WIN32*/
-
-#endif/*__DRUMGIZMO_NATIVEWINDOW_WIN32_H__*/
+} // GUI::
diff --git a/plugingui/nativewindow_x11.cc b/plugingui/nativewindow_x11.cc
index cb6cf73..a0316b9 100644
--- a/plugingui/nativewindow_x11.cc
+++ b/plugingui/nativewindow_x11.cc
@@ -26,105 +26,152 @@
*/
#include "nativewindow_x11.h"
-#ifdef X11
#include <X11/Xutil.h>
#include <stdlib.h>
+#include <hugin.hpp>
+
#include "window.h"
-GUI::NativeWindowX11::NativeWindowX11(GUI::Window *window)
- : GUI::NativeWindow()
+namespace GUI {
+
+NativeWindowX11::NativeWindowX11(Window& window)
+ : buffer(nullptr)
+ , window(window)
{
- display = XOpenDisplay(NULL);
-
- this->window = window;
- buffer = NULL;
-
- // Get some colors
- int blackColor = BlackPixel(display, DefaultScreen(display));
-
- ::Window w = DefaultRootWindow(display);
-
- // Create the window
- xwindow = XCreateSimpleWindow(display,
- w,
- window->x(), window->y(),
- window->width(), window->height(),
- 0,
- blackColor, blackColor);
-
- XSelectInput(display, xwindow,
- StructureNotifyMask |
- PointerMotionMask |
- ButtonPressMask |
- ButtonReleaseMask |
- KeyPressMask |
- KeyReleaseMask|
- ExposureMask |
- StructureNotifyMask |
- SubstructureNotifyMask);
-
- // register interest in the delete window message
- wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false);
- XSetWMProtocols(display, xwindow, &wmDeleteMessage, 1);
-
- // "Map" the window (that is, make it appear on the screen)
- XMapWindow(display, xwindow);
-
- // Create a "Graphics Context"
- gc = XCreateGC(display, xwindow, 0, NULL);
+ auto status = XInitThreads();
+ if(status)
+ {
+ ERR(X11, "Could not initialise threaded Xlib calls (XInitThreads)");
+ }
+
+ display = XOpenDisplay(nullptr);
+ if(display == nullptr)
+ {
+ ERR(X11, "XOpenDisplay failed");
+ return;
+ }
+
+ screen = DefaultScreen(display);
+
+ // Get some colors
+ int blackColor = BlackPixel(display, screen);
+
+ ::Window rootWindow = DefaultRootWindow(display);
+
+ // Create the window
+ unsigned long border = 0;
+ xwindow = XCreateSimpleWindow(display,
+ rootWindow,
+ window.x(), window.y(),
+ window.width(), window.height(),
+ border,
+ blackColor, blackColor);
+
+ long mask = (StructureNotifyMask |
+ PointerMotionMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ KeyPressMask |
+ KeyReleaseMask|
+ ExposureMask |
+ StructureNotifyMask |
+ SubstructureNotifyMask);
+ XSelectInput(display, xwindow, mask);
+
+ // Register the delete window message:
+ wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false);
+
+ Atom protocols[] = { wmDeleteMessage };
+ int count = sizeof(protocols)/sizeof(Atom);
+ XSetWMProtocols(display, xwindow, protocols, count);
+
+ // "Map" the window (that is, make it appear on the screen)
+ XMapWindow(display, xwindow);
+
+ // Create a "Graphics Context"
+ gc = XCreateGC(display, xwindow, 0, nullptr);
}
-GUI::NativeWindowX11::~NativeWindowX11()
+NativeWindowX11::~NativeWindowX11()
{
- XDestroyWindow(display, xwindow);
- //widgets.erase(window);
- XCloseDisplay(display);
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ XDestroyWindow(display, xwindow);
+ XCloseDisplay(display);
}
-void GUI::NativeWindowX11::setFixedSize(int width, int height)
+void NativeWindowX11::setFixedSize(int width, int height)
{
- resize(width, height);
-
- XSizeHints *size_hints;
- size_hints = XAllocSizeHints();
-
- if(size_hints == NULL) {
- //fprintf(stderr,"XMallocSizeHints() failed\n");
- //exit(1);
- return;
- }
-
- size_hints->flags = USPosition | PMinSize | PMaxSize;
- size_hints->min_width = size_hints->max_width = width;
- size_hints->min_height = size_hints->max_height = height;
- /*
- size_hints->min_aspect.x = window->width()/window->height();
- size_hints->max_aspect.x = window->width()/window->height();
- size_hints->min_aspect.y = window->width()/window->height();
- size_hints->max_aspect.y = size_hints->min_aspect.y;
- */
- XSetWMNormalHints(display, xwindow, size_hints);
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ resize(width, height);
+
+ XSizeHints* size_hints;
+ size_hints = XAllocSizeHints();
+
+ if(size_hints == nullptr)
+ {
+ ERR(X11,"XMallocSizeHints() failed");
+ return;
+ }
+
+ size_hints->flags = USPosition | PMinSize | PMaxSize;
+ size_hints->min_width = size_hints->max_width = width;
+ size_hints->min_height = size_hints->max_height = height;
+
+ //size_hints->min_aspect.x = (float)window.width()/(float)window.height();
+ //size_hints->max_aspect.x = (float)window.width()/(float)window.height();
+ //size_hints->min_aspect.y = (float)window.width()/(float)window.height();
+ //size_hints->max_aspect.y = size_hints->min_aspect.y;
+
+ XSetWMNormalHints(display, xwindow, size_hints);
}
-void GUI::NativeWindowX11::resize(int width, int height)
+void NativeWindowX11::resize(int width, int height)
{
- XResizeWindow(display, xwindow, width, height);
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ XResizeWindow(display, xwindow, width, height);
}
-void GUI::NativeWindowX11::move(int x, int y)
+void NativeWindowX11::move(int x, int y)
{
- XMoveWindow(display, xwindow, x, y);
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ XMoveWindow(display, xwindow, x, y);
}
-void GUI::NativeWindowX11::show()
+void NativeWindowX11::show()
{
- XMapWindow(display, xwindow);
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ XMapWindow(display, xwindow);
}
-void GUI::NativeWindowX11::hide()
+void NativeWindowX11::hide()
{
- XUnmapWindow(display, xwindow);
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ XUnmapWindow(display, xwindow);
}
static int get_byte_order (void)
@@ -135,254 +182,345 @@ static int get_byte_order (void)
} order;
order.s = 1;
- if ((1 == order.c[0])) {
+ if((1 == order.c[0]))
+ {
return LSBFirst;
- } else {
+ }
+ else
+ {
return MSBFirst;
}
}
-static XImage *create_image_from_buffer(Display *dis, int screen,
- unsigned char *buf,
- int width, int height)
+XImage* NativeWindowX11::createImageFromBuffer(unsigned char* buf,
+ int width, int height)
{
int depth;
- XImage *img = NULL;
- Visual *vis;
+ XImage* img = nullptr;
+ Visual* vis;
double rRatio;
double gRatio;
double bRatio;
- int outIndex = 0;
+ int outIndex = 0;
int i;
int numBufBytes = (3 * (width * height));
-
- depth = DefaultDepth(dis, screen);
- vis = DefaultVisual(dis, screen);
+
+ depth = DefaultDepth(display, screen);
+ vis = DefaultVisual(display, screen);
rRatio = vis->red_mask / 255.0;
gRatio = vis->green_mask / 255.0;
bRatio = vis->blue_mask / 255.0;
-
- if (depth >= 24) {
+
+ if(depth >= 24)
+ {
size_t numNewBufBytes = (4 * (width * height));
u_int32_t *newBuf = (u_int32_t *)malloc (numNewBufBytes);
-
- for (i = 0; i < numBufBytes; ++i) {
+
+ for(i = 0; i < numBufBytes; ++i)
+ {
unsigned int r, g, b;
r = (buf[i] * rRatio);
++i;
g = (buf[i] * gRatio);
++i;
b = (buf[i] * bRatio);
-
- r &= vis->red_mask;
- g &= vis->green_mask;
- b &= vis->blue_mask;
-
- newBuf[outIndex] = r | g | b;
- ++outIndex;
- }
-
- img = XCreateImage (dis,
- CopyFromParent, depth,
- ZPixmap, 0,
- (char *) newBuf,
- width, height,
- 32, 0
- );
-
- } else if (depth >= 15) {
- size_t numNewBufBytes = (2 * (width * height));
- u_int16_t *newBuf = (u_int16_t *)malloc (numNewBufBytes);
-
- for (i = 0; i < numBufBytes; ++i) {
- unsigned int r, g, b;
- r = (buf[i] * rRatio);
- ++i;
- g = (buf[i] * gRatio);
- ++i;
- b = (buf[i] * bRatio);
-
r &= vis->red_mask;
g &= vis->green_mask;
b &= vis->blue_mask;
-
+
newBuf[outIndex] = r | g | b;
++outIndex;
- }
-
- img = XCreateImage(dis, CopyFromParent, depth, ZPixmap, 0, (char *) newBuf,
- width, height, 16, 0);
- } else {
- //fprintf (stderr, "This program does not support displays with a depth less than 15.");
- return NULL;
+ }
+
+ img = XCreateImage (display,
+ CopyFromParent, depth,
+ ZPixmap, 0,
+ (char*) newBuf,
+ width, height,
+ 32, 0);
+ }
+ else
+ {
+ if(depth >= 15)
+ {
+ size_t numNewBufBytes = (2 * (width * height));
+ u_int16_t* newBuf = (u_int16_t*)malloc (numNewBufBytes);
+
+ for(i = 0; i < numBufBytes; ++i)
+ {
+ unsigned int r, g, b;
+
+ r = (buf[i] * rRatio);
+ ++i;
+ g = (buf[i] * gRatio);
+ ++i;
+ b = (buf[i] * bRatio);
+
+ r &= vis->red_mask;
+ g &= vis->green_mask;
+ b &= vis->blue_mask;
+
+ newBuf[outIndex] = r | g | b;
+ ++outIndex;
+ }
+
+ img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0,
+ (char*)newBuf, width, height, 16, 0);
+ }
+ else
+ {
+ //fprintf (stderr, "This program does not support displays with a depth less than 15.");
+ return nullptr;
+ }
}
XInitImage (img);
- /*Set the client's byte order, so that XPutImage knows what to do with the data.*/
- /*The default in a new X image is the server's format, which may not be what we want.*/
- if ((LSBFirst == get_byte_order ())) {
+
+ // Set the client's byte order, so that XPutImage knows what
+ // to do with the data.
+ // The default in a new X image is the server's format, which
+ // may not be what we want.
+ if((LSBFirst == get_byte_order ()))
+ {
img->byte_order = LSBFirst;
- } else {
+ }
+ else
+ {
img->byte_order = MSBFirst;
}
-
- /*The bitmap_bit_order doesn't matter with ZPixmap images.*/
+
+ // The bitmap_bit_order doesn't matter with ZPixmap images.
img->bitmap_bit_order = MSBFirst;
return img;
-}
+}
-void GUI::NativeWindowX11::handleBuffer()
+void NativeWindowX11::handleBuffer()
{
- if(buffer) XDestroyImage(buffer);
- buffer =
- create_image_from_buffer(display, DefaultScreen(display),
- window->wpixbuf.buf,
- window->wpixbuf.width,
- window->wpixbuf.height);
+ if(buffer)
+ {
+ XDestroyImage(buffer);
+ }
+
+ buffer = createImageFromBuffer(window.wpixbuf.buf,
+ window.wpixbuf.width,
+ window.wpixbuf.height);
}
-void GUI::NativeWindowX11::redraw()
+void NativeWindowX11::redraw()
{
- // http://stackoverflow.com/questions/6384987/load-image-onto-a-window-using-xlib
- if(buffer == NULL) window->updateBuffer();
- XPutImage(display, xwindow, gc, buffer, 0, 0, 0, 0,
- window->width(), window->height());
- XFlush(display);
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ if(buffer == nullptr)
+ {
+ window.updateBuffer();
+ }
+
+ XPutImage(display, xwindow, gc, buffer, 0, 0, 0, 0,
+ window.width(), window.height());
+ XFlush(display);
+}
+
+void NativeWindowX11::setCaption(const std::string &caption)
+{
+ if(display == nullptr)
+ {
+ return;
+ }
+
+ XStoreName(display, xwindow, caption.c_str());
}
-void GUI::NativeWindowX11::setCaption(const std::string &caption)
+void NativeWindowX11::grabMouse(bool grab)
{
- XStoreName(display, xwindow, caption.c_str());
+ (void)grab;
+ // Don't need to do anything on this platform...
}
-void GUI::NativeWindowX11::grabMouse(bool grab)
+bool NativeWindowX11::hasEvent()
{
- (void)grab;
- // Don't need to do anything on this platoform...
+ if(display == nullptr)
+ {
+ return false;
+ }
+
+ return XPending(display);
}
-bool GUI::NativeWindowX11::hasEvent()
+Event* NativeWindowX11::getNextEvent()
{
- return XPending(display);
+ if(display == nullptr)
+ {
+ return nullptr;
+ }
+
+ XEvent xEvent;
+ XNextEvent(display, &xEvent);
+ return translateXMessage(xEvent);
}
-GUI::Event *GUI::NativeWindowX11::getNextEvent()
+Event* NativeWindowX11::peekNextEvent()
{
- Event *event = NULL;
-
- XEvent xe;
- XNextEvent(display, &xe);
-
- if(xe.type == MotionNotify) {
- while(true) { // Hack to make sure only the last event is played.
- if(!hasEvent()) break;
- XEvent nxe;
- XPeekEvent(display, &nxe);
- if(nxe.type != MotionNotify) break;
- XNextEvent(display, &xe);
- }
-
- MouseMoveEvent *e = new MouseMoveEvent();
- e->window_id = xe.xmotion.window;
- e->x = xe.xmotion.x;
- e->y = xe.xmotion.y;
- event = e;
- }
-
- if(xe.type == Expose && xe.xexpose.count == 0) {
- RepaintEvent *e = new RepaintEvent();
- e->window_id = xe.xexpose.window;
- e->x = xe.xexpose.x;
- e->y = xe.xexpose.y;
- e->width = xe.xexpose.width;
- e->height = xe.xexpose.height;
- event = e;
- }
-
- if(xe.type == ConfigureNotify) {
- ResizeEvent *e = new ResizeEvent();
- e->window_id = xe.xconfigure.window;
- // e->x = xe.xconfigure.x;
- // e->y = xe.xconfigure.y;
- e->width = xe.xconfigure.width;
- e->height = xe.xconfigure.height;
- event = e;
- }
-
- if(xe.type == ButtonPress || xe.type == ButtonRelease) {
- if(xe.xbutton.button == 4 || xe.xbutton.button == 5) {
- int scroll = 1;
- while(true) { // Hack to make sure only the last event is played.
- if(!hasEvent()) break;
- XEvent nxe;
- XPeekEvent(display, &nxe);
- if(nxe.type != ButtonPress && nxe.type != ButtonRelease) break;
- scroll += 1;
- XNextEvent(display, &xe);
- }
- ScrollEvent *e = new ScrollEvent();
- e->window_id = xe.xbutton.window;
- e->x = xe.xbutton.x;
- e->y = xe.xbutton.y;
- e->delta = scroll * (xe.xbutton.button==4?-1:1);
- event = e;
- } else {
- ButtonEvent *e = new ButtonEvent();
- e->window_id = xe.xbutton.window;
- e->x = xe.xbutton.x;
- e->y = xe.xbutton.y;
- e->button = 0;
- e->direction = xe.type == ButtonPress?1:-1;
- e->doubleclick =
- xe.type == ButtonPress && (xe.xbutton.time - last_click) < 200;
-
- if(xe.type == ButtonPress) last_click = xe.xbutton.time;
- event = e;
- }
- }
-
- if(xe.type == KeyPress || xe.type == KeyRelease) {
- //printf("key: %d\n", xe.xkey.keycode);
- KeyEvent *e = new KeyEvent();
- e->window_id = xe.xkey.window;
-
- switch(xe.xkey.keycode) {
- case 113: e->keycode = KeyEvent::KEY_LEFT; break;
- case 114: e->keycode = KeyEvent::KEY_RIGHT; break;
- case 111: e->keycode = KeyEvent::KEY_UP; break;
- case 116: e->keycode = KeyEvent::KEY_DOWN; break;
- case 119: e->keycode = KeyEvent::KEY_DELETE; break;
- case 22: e->keycode = KeyEvent::KEY_BACKSPACE; break;
- case 110: e->keycode = KeyEvent::KEY_HOME; break;
- case 115: e->keycode = KeyEvent::KEY_END; break;
- case 117: e->keycode = KeyEvent::KEY_PGDOWN; break;
- case 112: e->keycode = KeyEvent::KEY_PGUP; break;
- case 36: e->keycode = KeyEvent::KEY_ENTER; break;
- default: e->keycode = KeyEvent::KEY_UNKNOWN; break;
- }
-
- char buf[1024];
- int sz = XLookupString(&xe.xkey, buf, sizeof(buf), NULL, NULL);
- if(sz && e->keycode == KeyEvent::KEY_UNKNOWN) {
- e->keycode = KeyEvent::KEY_CHARACTER;
- }
- e->text.append(buf, sz);
-
- e->direction = xe.type == KeyPress?1:-1;
- event = e;
- }
-
- if(xe.type == ClientMessage &&
- (unsigned int)xe.xclient.data.l[0] == wmDeleteMessage) {
- CloseEvent *e = new CloseEvent();
- event = e;
- }
-
- return event;
+ if(display == nullptr)
+ {
+ return nullptr;
+ }
+
+ XEvent peekXEvent;
+ XPeekEvent(display, &peekXEvent);
+ return translateXMessage(peekXEvent, true);
}
-#endif/*X11*/
+ Event* NativeWindowX11::translateXMessage(XEvent& xevent, bool peek)
+{
+ Event* event = nullptr;
+
+ switch(xevent.type) {
+ case MotionNotify:
+ {
+ auto mouseMoveEvent = new MouseMoveEvent();
+ mouseMoveEvent->window_id = xevent.xmotion.window;
+ mouseMoveEvent->x = xevent.xmotion.x;
+ mouseMoveEvent->y = xevent.xmotion.y;
+ event = mouseMoveEvent;
+ }
+ break;
+
+ case Expose:
+ if(xevent.xexpose.count == 0)
+ {
+ auto repaintEvent = new RepaintEvent();
+ repaintEvent->window_id = xevent.xexpose.window;
+ repaintEvent->x = xevent.xexpose.x;
+ repaintEvent->y = xevent.xexpose.y;
+ repaintEvent->width = xevent.xexpose.width;
+ repaintEvent->height = xevent.xexpose.height;
+ event = repaintEvent;
+ }
+ break;
+
+ case ConfigureNotify:
+ {
+ auto resizeEvent = new ResizeEvent();
+ resizeEvent->window_id = xevent.xconfigure.window;
+ //resizeEvent->x = xevent.xconfigure.x;
+ //resizeEvent->y = xevent.xconfigure.y;
+ resizeEvent->width = xevent.xconfigure.width;
+ resizeEvent->height = xevent.xconfigure.height;
+ event = resizeEvent;
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ {
+ if((xevent.xbutton.button == 4) || (xevent.xbutton.button == 5))
+ {
+ int scroll = 1;
+ auto scrollEvent = new ScrollEvent();
+ scrollEvent->window_id = xevent.xbutton.window;
+ scrollEvent->x = xevent.xbutton.x;
+ scrollEvent->y = xevent.xbutton.y;
+ scrollEvent->delta = scroll * ((xevent.xbutton.button == 4) ? -1 : 1);
+ event = scrollEvent;
+ }
+ else
+ {
+ auto buttonEvent = new ButtonEvent();
+ buttonEvent->window_id = xevent.xbutton.window;
+ 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;
+
+ buttonEvent->doubleClick =
+ (xevent.type == ButtonPress) &&
+ ((xevent.xbutton.time - last_click) < 200);
+
+ if(!peek && (xevent.type == ButtonPress))
+ {
+ last_click = xevent.xbutton.time;
+ }
+ event = buttonEvent;
+ }
+ }
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ {
+ auto keyEvent = new KeyEvent();
+ keyEvent->window_id = xevent.xkey.window;
+
+ 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 = keyEvent;
+ }
+ break;
+
+ case ClientMessage:
+ if(((unsigned int)xevent.xclient.data.l[0] == wmDeleteMessage))
+ {
+ auto closeEvent = new CloseEvent();
+ event = closeEvent;
+ }
+ break;
+
+ default:
+ WARN(X11, "Unhandled xevent.type: %d\n", xevent.type);
+ break;
+ }
+
+ return event;
+}
+} // GUI::
diff --git a/plugingui/nativewindow_x11.h b/plugingui/nativewindow_x11.h
index 3dcc0bb..134ab6f 100644
--- a/plugingui/nativewindow_x11.h
+++ b/plugingui/nativewindow_x11.h
@@ -24,11 +24,8 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_NATIVEWINDOW_X11_H__
-#define __DRUMGIZMO_NATIVEWINDOW_X11_H__
-#endif/*__DRUMGIZMO_NATIVEWINDOW_X11_H__*/
+#pragma once
-#ifdef X11
#include <X11/Xlib.h>
#include "nativewindow.h"
@@ -38,35 +35,38 @@ namespace GUI {
class Window;
class NativeWindowX11 : public NativeWindow {
public:
- NativeWindowX11(GUI::Window *window);
- ~NativeWindowX11();
+ NativeWindowX11(Window& window);
+ ~NativeWindowX11();
- void setFixedSize(int width, int height);
- void resize(int width, int height);
- void move(int x, int y);
- void show();
- void setCaption(const std::string &caption);
- void hide();
- void handleBuffer();
- void redraw();
- void grabMouse(bool grab);
-
- bool hasEvent();
- Event *getNextEvent();
+ // From NativeWindow:
+ void setFixedSize(int width, int height) override;
+ void resize(int width, int height) override;
+ void move(int x, int y) override;
+ void show() override;
+ void hide() override;
+ void setCaption(const std::string &caption) override;
+ void handleBuffer() override;
+ void redraw() override;
+ void grabMouse(bool grab) override;
+ bool hasEvent() override;
+ Event* getNextEvent() override;
+ Event* peekNextEvent() override;
private:
- ::Window xwindow;
- GC gc;
- XImage *buffer;
+ Event* translateXMessage(XEvent& xevent, bool peek = false);
+ XImage* createImageFromBuffer(unsigned char* buf, int width, int height);
- GUI::Window *window;
+ ::Window xwindow{0};
+ GC gc{0};
+ XImage* buffer{nullptr};
- int last_click;
+ Window& window;
- Display *display;
- Atom wmDeleteMessage;
-};
+ int last_click{0};
+ Display* display{nullptr};
+ int screen{0};
+ Atom wmDeleteMessage{0};
};
-#endif/*X11*/
+} // GUI::
diff --git a/plugingui/notifier.h b/plugingui/notifier.h
new file mode 100644
index 0000000..328ab7d
--- /dev/null
+++ b/plugingui/notifier.h
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * notifier.h
+ *
+ * Thu Sep 3 15:48:39 CEST 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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.
+ */
+#pragma once
+
+#include <functional>
+#include <vector>
+#include <map>
+#include <set>
+#include <memory>
+
+namespace aux
+{
+ template<int>
+ struct placeholder
+ {
+ };
+}
+
+namespace std
+{
+ template<int N>
+ struct is_placeholder<aux::placeholder<N>>
+ : integral_constant<int, N+1>
+ {
+ };
+}
+
+namespace aux
+{
+ // std::integer_sequence introduced in C++14 so remove this once we start requiring that.
+
+ template<int... Ns>
+ struct int_sequence
+ {
+ };
+
+ template<int N, int... Ns>
+ struct gen_int_sequence
+ : gen_int_sequence<N-1, N-1, Ns...>
+ {
+ };
+
+ template<int... Ns>
+ struct gen_int_sequence<0, Ns...>
+ : int_sequence<Ns...>
+ {
+ };
+};
+
+
+namespace GUI {
+
+class Listener;
+class NotifierBase {
+public:
+ virtual void disconnect(Listener* object) {}
+};
+
+class Listener {
+public:
+ virtual ~Listener()
+ {
+ for(auto signal : signals)
+ {
+ signal->disconnect(this);
+ }
+ }
+
+ void registerNotifier(NotifierBase* signal)
+ {
+ signals.insert(signal);
+ }
+
+ void unregisterNotifier(NotifierBase* signal)
+ {
+ signals.erase(signal);
+ }
+
+private:
+ std::set<NotifierBase*> signals;
+};
+
+template<typename... Args>
+class Notifier : public NotifierBase {
+public:
+ Notifier() {}
+
+ //! \brief When dtor is called it will automatically disconnect all its listeners.
+ ~Notifier()
+ {
+ for(auto& slot : slots)
+ {
+ slot.first->unregisterNotifier(this);
+ }
+ }
+
+ using callback_type = std::function<void(Args...)>;
+
+ //! \brief Connect object to this Notifier.
+ template<typename O, typename F>
+ void connect(O* p, const F& fn)
+ {
+ slots[p] = std::move(construct_mem_fn(fn, p, aux::gen_int_sequence<sizeof...(Args)>{}));
+ if(p && dynamic_cast<Listener*>(p))
+ {
+ dynamic_cast<Listener*>(p)->registerNotifier(this);
+ }
+ }
+
+ //! \brief Disconnect object from this Notifier.
+ void disconnect(Listener* object)
+ {
+ slots.erase(object);
+ }
+
+ //! \brief Activate this notifier by pretending it is a function.
+ //! Example: Notifier<int> foo; foo(42);
+ void operator()(Args... args)
+ {
+ for(auto& slot : slots)
+ {
+ slot.second(args...);
+ }
+ }
+
+private:
+ std::map<Listener*, callback_type> slots;
+
+ template<typename F, typename O, int... Ns>
+ callback_type construct_mem_fn(const F& fn, O* p, aux::int_sequence<Ns...>) const
+ {
+ return std::bind(fn, p, aux::placeholder<Ns>{}...);
+ }
+
+};
+
+} // GUI::
+
+#define CONNECT(SRC, SIG, TAR, SLO) (SRC)->SIG.connect(TAR, SLO)
diff --git a/plugingui/painter.cc b/plugingui/painter.cc
index 842ff11..01fae5d 100644
--- a/plugingui/painter.cc
+++ b/plugingui/painter.cc
@@ -28,461 +28,494 @@
#include "window.h"
-#include <string.h>
+#include <cmath>
-GUI::Painter::Painter(GUI::Widget *widget)
-{
- this->widget = widget;
- widget->window()->beginPaint();
- pixbuf = &widget->pixbuf;
- colour = Colour(0, 0, 0, 0.5);
-}
+namespace GUI {
-GUI::Painter::~Painter()
+Painter::Painter(Widget& widget)
+ : widget(widget)
{
- widget->window()->endPaint();
- flush();
-}
+ if(widget.window())
+ {
+ widget.window()->beginPaint();
+ }
-void GUI::Painter::setColour(Colour colour)
-{
- this->colour = colour;
+ pixbuf = &widget.pixbuf;
+ colour = Colour(0, 0, 0, 0.5);
}
-void GUI::Painter::plot(int x, int y, double c)
+Painter::~Painter()
{
- // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1)
- pixbuf->addPixel(x, y,
- (unsigned char)(colour.red * 255.0),
- (unsigned char)(colour.green * 255.0),
- (unsigned char)(colour.blue * 255.0),
- (unsigned char)(colour.alpha * 255 * c));
+ if(widget.window())
+ {
+ widget.window()->endPaint();
+ }
+ flush();
}
-#include <math.h>
-double GUI::Painter::ipart(double x)
+void Painter::setColour(const Colour& colour)
{
- return floor(x); //integer part of x'
+ this->colour = colour;
}
-
-double GUI::Painter::round(double x)
-{
- return ipart(x + 0.5);
-}
-
-double GUI::Painter::fpart(double x)
-{
- return x - ipart(x);//'fractional part of x'
-}
-
-double GUI::Painter::rfpart(double x)
+
+static void plot(PixelBufferAlpha* pixbuf, const Colour& colour,
+ int x, int y, double c)
{
- return 1 - fpart(x);
-}
+ if((x >= (int)pixbuf->width) || (y >= (int)pixbuf->height))
+ {
+ return;
+ }
+
+ // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1)
+ pixbuf->addPixel(x, y,
+ (unsigned char)(colour.red * 255.0),
+ (unsigned char)(colour.green * 255.0),
+ (unsigned char)(colour.blue * 255.0),
+ (unsigned char)(colour.alpha * 255 * c));
+}
-#define SWAP(x, y) { int tmp = x; x = y; y = tmp; }
-void GUI::Painter::drawLine(int x0, int y0, int x1, int y1)
+static inline double fpart(double x)
{
- bool steep = abs(y1 - y0) > abs(x1 - x0);
-
- if(steep) {
- SWAP(x0, y0);
- SWAP(x1, y1);
- }
- if(x0 > x1) {
- SWAP(x0, x1);
- SWAP(y0, y1);
- }
-
- double dx = x1 - x0;
- double dy = y1 - y0;
- double gradient = dy / dx;
-
- // Handle first endpoint:
- double xend = round(x0);
- double yend = y0 + gradient * (xend - x0);
- //double xgap = rfpart(x0 + 0.5);
- double xpxl1 = xend; //this will be used in the main loop
- double ypxl1 = ipart(yend);
-
- if(steep) {
- plot(ypxl1, xpxl1, 1);
- //plot(ypxl1, xpxl1, rfpart(yend) * xgap);
- //plot(ypxl1+1, xpxl1, fpart(yend) * xgap);
- } else {
- plot(xpxl1, ypxl1, 1);
- //plot(xpxl1, ypxl1 , rfpart(yend) * xgap);
- //plot(xpxl1, ypxl1+1, fpart(yend) * xgap);
- }
-
- double intery = yend + gradient; // first y-intersection for the main loop
-
- // Handle second endpoint:
- xend = round(x1);
- yend = y1 + gradient * (xend - x1);
- //xgap = fpart(x1 + 0.5);
- double xpxl2 = xend; //this will be used in the main loop
- double ypxl2 = ipart(yend);
-
- if(steep) {
- plot(ypxl2, xpxl2, 1);
- //plot(ypxl2 , xpxl2, rfpart(yend) * xgap);
- //plot(ypxl2+1, xpxl2, fpart(yend) * xgap);
- } else {
- plot(xpxl2, ypxl2, 1);
- //plot(xpxl2, ypxl2, rfpart(yend) * xgap);
- //plot(xpxl2, ypxl2+1, fpart(yend) * xgap);
- }
-
- // main loop
- for(int x = xpxl1 + 1; x <= xpxl2 - 1; x++) {
- if(steep) {
- plot(ipart(intery) , x, rfpart(intery));
- plot(ipart(intery)+1, x, fpart(intery));
- } else {
- plot(x, ipart (intery), rfpart(intery));
- plot(x, ipart (intery)+1, fpart(intery));
- }
- intery += gradient;
- }
+ return x - std::floor(x);// fractional part of x
}
-void GUI::Painter::drawRectangle(int x1, int y1, int x2, int y2)
+static inline double rfpart(double x)
{
- drawLine(x1, y1, x2 - 1, y1);
- drawLine(x2, y1, x2, y2 - 1);
- drawLine(x1 + 1, y2, x2, y2);
- drawLine(x1, y1 + 1, x1, y2);
+ return 1 - fpart(x); // reverse fractional part of x
}
-void GUI::Painter::drawFilledRectangle(int x1, int y1, int x2, int y2)
+void Painter::drawLine(int x0, int y0, int x1, int y1)
{
- for(int y = y1; y < y2; y++) {
- drawLine(x1, y, x2, y);
- }
+ 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)
+ {
+ plot(pixbuf, colour, ypxl1, xpxl1, 1);
+ }
+ else
+ {
+ plot(pixbuf, colour, xpxl1, ypxl1, 1);
+ }
+
+ 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)
+ {
+ plot(pixbuf, colour, ypxl2, xpxl2, 1);
+ }
+ else
+ {
+ plot(pixbuf, colour, xpxl2, ypxl2, 1);
+ }
+
+ // 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 GUI::Painter::clear()
+void Painter::drawRectangle(int x1, int y1, int x2, int y2)
{
- for(int x = 0; x < (int)pixbuf->width; x++) {
- for(int y = 0; y < (int)pixbuf->height; y++) {
- pixbuf->setPixel(x, y, 0, 0, 0, 0);
- }
- }
+ 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 GUI::Painter::drawText(int x0, int y0, GUI::Font &font, std::string text,
- bool nocolour)
+void Painter::drawFilledRectangle(int x1, int y1, int x2, int y2)
{
- PixelBufferAlpha *textbuf = font.render(text);
- if(nocolour) {
- for(size_t x = 0; x < textbuf->width; x++) {
- for(size_t y = 0; y < textbuf->height; y++) {
- unsigned char r,g,b,a;
- textbuf->pixel(x, y, &r, &g, &b, &a);
- pixbuf->addPixel(x + x0, y + y0 - textbuf->height, r,g,b,a);
- }
- }
- } else {
- for(size_t x = 0; x < textbuf->width; x++) {
- for(size_t y = 0; y < textbuf->height; y++) {
- unsigned char r,g,b,a;
- textbuf->pixel(x, y, &r, &g, &b, &a);
- pixbuf->addPixel(x + x0, y + y0 - textbuf->height,
- colour.red * 255,
- colour.green * 255,
- colour.blue * 255,
- colour.alpha * a);
- }
- }
- }
-
- delete textbuf;
+ for(int y = y1; y < y2; ++y)
+ {
+ drawLine(x1, y, x2, y);
+ }
}
-#include <stdio.h>
-void GUI::Painter::drawPoint(int x, int y)
+void Painter::clear()
{
- pixbuf->setPixel(x, y,
- (unsigned char)(colour.red * 255.0),
- (unsigned char)(colour.green * 255.0),
- (unsigned char)(colour.blue * 255.0),
- (unsigned char)(colour.alpha * 255.0));
+ for(int x = 0; x < (int)pixbuf->width; ++x)
+ {
+ for(int y = 0; y < (int)pixbuf->height; ++y)
+ {
+ pixbuf->setPixel(x, y, 0, 0, 0, 0);
+ }
+ }
}
-#if 0
-static double distance(double r, double y)
+void Painter::drawText(int x0, int y0, const Font& font,
+ const std::string& text, bool nocolour)
{
- double real_point = sqrt(pow(r, 2) - pow(y, 2));
- return ceil(real_point) - real_point;
+ PixelBufferAlpha* textbuf = font.render(text);
+
+ 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 = 0; y < renderHeight; ++y)
+ {
+ for(int x = 0; x < renderWidth; ++x)
+ {
+ unsigned char r, g, b, a;
+ textbuf->pixel(x, y, &r, &g, &b, &a);
+ pixbuf->addPixel(x + x0, y + y0, r, g, b, a);
+ }
+ }
+ }
+ else
+ {
+ for(int y = 0; y < renderHeight; ++y)
+ {
+ for(int x = 0; x < renderWidth; ++x)
+ {
+ unsigned char r,g,b,a;
+ textbuf->pixel(x, y, &r, &g, &b, &a);
+ pixbuf->addPixel(x + x0, y + y0,
+ colour.red * 255,
+ colour.green * 255,
+ colour.blue * 255,
+ colour.alpha * a);
+ }
+ }
+ }
+
+ delete textbuf;
}
-double new_color(double i) {
- return i * 127;
+void Painter::drawPoint(int x, int y)
+{
+ pixbuf->setPixel(x, y,
+ (unsigned char)(colour.red * 255.0),
+ (unsigned char)(colour.green * 255.0),
+ (unsigned char)(colour.blue * 255.0),
+ (unsigned char)(colour.alpha * 255.0));
}
-void GUI::Painter::drawCircle(int cx, int cy, double radius)
+static void plot4points(Painter *p, int cx, int cy, int x, int y)
{
- // wu_circle($image, $r, $color, $offset_x = null, $offset_y = null) {
- //$red = $color["red"];
- //$green = $color["green"];
- //$blue = $color["blue"];
- int offset_x = cx;
- int offset_y = cy;
- int x = radius;
- // int xx = radius;
- int y = -1;
- // int yy = -1;
- double t = 0;
- //$color = imagecolorallocate($image, $red, $green, $blue);
- while(x > y) {
- y++;
- double current_distance = distance(radius, y);
- if(current_distance < t) {
- x--;
- }
-
- double trasparency = new_color(current_distance);
- double alpha = trasparency;
- double alpha2 = 127.0 - trasparency;
-
- double color = 1;
-
- plot(x + offset_x, y + offset_y, color);
- plot(x + offset_x - 1, y + offset_y, alpha2 );
- plot(x + offset_x + 1, y + offset_y, alpha );
-
- plot(y + offset_x, x + offset_y, color);
- plot(y + offset_x, x + offset_y - 1, alpha2);
- plot(y + offset_x, x + offset_y + 1, alpha);
-
- plot(offset_x - x , y + offset_y, color);
- plot(offset_x - x + 1, y + offset_y, alpha2);
- plot(offset_x - x - 1, y + offset_y, alpha);
-
- plot(offset_x - y, x + offset_y, color);
- plot(offset_x - y, x + offset_y - 1, alpha2);
- plot(offset_x - y, x + offset_y + 1, alpha);
-
- plot(x + offset_x, offset_y - y, color);
- plot(x + offset_x - 1, offset_y - y, alpha2);
- plot(x + offset_x + 1, offset_y - y, alpha);
-
- plot(y + offset_x, offset_y - x, color);
- plot(y + offset_x, offset_y - x - 1, alpha);
- plot(y + offset_x, offset_y - x + 1, alpha2);
-
- plot(offset_x - y, offset_y - x, color);
- plot(offset_x - y, offset_y - x - 1, alpha);
- plot(offset_x - y, offset_y - x + 1, alpha2);
-
- plot(offset_x - x, offset_y - y, color);
- plot(offset_x - x - 1, offset_y - y, alpha);
- plot(offset_x - x + 1, offset_y - y, alpha2);
-
- t = current_distance;
- }
+ 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);
+ }
}
-#else
-static void plot4points(GUI::Painter *p, int cx, int cy, int x, int y)
+
+void Painter::drawCircle(int cx, int cy, double radius)
{
- 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);
+ 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;
+ }
+ }
}
-void GUI::Painter::drawCircle(int cx, int cy, double radius)
+static void plot4lines(Painter *p, int cx, int cy, int x, int y)
{
- 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;
- }
- }
+ 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);
+ }
}
-#endif
-static void plot4lines(GUI::Painter *p, int cx, int cy, int x, int y)
+void Painter::drawFilledCircle(int cx, int cy, int radius)
{
- 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);
+ 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 GUI::Painter::drawFilledCircle(int cx, int cy, int radius)
+void Painter::drawImage(int x0, int y0, const Image& image)
{
- 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;
- }
- }
+ size_t fw = image.width();
+ size_t fh = image.height();
+
+ // Make sure we don't try to draw outside the pixbuf.
+ if(fw > (pixbuf->width - x0))
+ {
+ fw = (pixbuf->width - x0);
+ }
+
+ if(fh > (pixbuf->height - y0))
+ {
+ fh = (pixbuf->height - y0);
+ }
+
+ for(size_t y = 0; y < fh; ++y)
+ {
+ for(size_t x = 0; x < fw; ++x)
+ {
+ Colour c = image.getPixel(x, y);
+ pixbuf->addPixel(x0 + x, y0 + y, c);
+ }
+ }
}
-void GUI::Painter::drawImage(int x0, int y0, GUI::Image *image)
+void Painter::drawImageStretched(int x0, int y0, const Image& image,
+ int width, int height)
{
- size_t fw = image->width();
- size_t fh = image->height();
-
- for(size_t x = 0; x < fw; x++) {
- for(size_t y = 0; y < fh; y++) {
- GUI::Colour c = image->getPixel(x, y);
- pixbuf->addPixel(x0 + x, y0 + y, c);
- }
- }
+ if((width < 1) || (height < 1))
+ {
+ return;
+ }
+
+ 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;
+ }
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; ++x)
+ {
+ int lx = ((float)x / (float)width) * fw;
+ int ly = ((float)y / (float)height) * fh;
+ Colour c = image.getPixel(lx, ly);
+ pixbuf->addPixel(x0 + x, y0 + y, c);
+ }
+ }
}
-void GUI::Painter::drawImageStretched(int x0, int y0, GUI::Image *image,
- int w, int h)
+void Painter::drawBox(int x, int y, const Box& box, int width, int height)
{
- if(w < 1 || h < 1) return;
-
- float fw = image->width();
- float fh = image->height();
-
- for(int x = 0; x < w; x++) {
- for(int y = 0; y < h; y++) {
- int lx = ((float)x/(float)w)*fw;
- int ly = ((float)y/(float)h)*fh;
- GUI::Colour c = image->getPixel(lx, ly);
- pixbuf->addPixel(x0 + x, y0 + y, c);
- }
- }
+ 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 GUI::Painter::drawBox(int x, int y, Box *box, int width, int height)
+void Painter::drawBar(int x, int y, const Bar& bar, 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;
+ if(width < ((int)bar.left->width() + (int)bar.right->width() + 1))
+ {
+ width = bar.left->width() + bar.right->width() + 1;
+ }
- drawImage(dx, dy, box->topRight);
+ drawImageStretched(x, y, *bar.left, bar.left->width(), height);
- // Center
- dy = y + box->topLeft->height();
- dx = x + box->left->width();
- if(dx < 0 || dy < 0) return;
+ drawImageStretched(x + bar.left->width(), y, *bar.center,
+ width - bar.left->width() - bar.right->width(), height);
- 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 GUI::Painter::drawBar(int x, int y, 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);
+ drawImageStretched(x + width - bar.left->width(), y, *bar.right,
+ bar.right->width(), height);
}
-void GUI::Painter::flush()
+void Painter::flush()
{
#ifdef X11
- // Send the "DrawLine" request to the server
- //XFlush(gctx->display);
+ // Send the "DrawLine" request to the server
+ //XFlush(gctx->display);
#endif/*X11*/
}
-#ifdef TEST_PAINTER
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_PAINTER*/
+} // GUI::
diff --git a/plugingui/painter.h b/plugingui/painter.h
index 0a93f50..78f1560 100644
--- a/plugingui/painter.h
+++ b/plugingui/painter.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_PAINTER_H__
-#define __DRUMGIZMO_PAINTER_H__
+#pragma once
#include <string>
@@ -39,59 +38,51 @@ namespace GUI {
class Painter {
public:
- Painter(Widget *widget);
- ~Painter();
+ Painter(Widget& widget);
+ ~Painter();
- void flush();
+ void flush();
- void setColour(Colour colour);
+ void setColour(const Colour& colour);
- void drawLine(int x1, int y1, int x2, int y2);
- void drawText(int x, int y, Font &font, std::string text,
- bool nocolour = 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, Image *image);
- void drawImageStretched(int x0, int y0, GUI::Image *image,
- int width, int height);
+ 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);
+ 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 Image& image);
+ void drawImageStretched(int x, int y, const Image& image,
+ int width, int height);
- 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, Box *box, int width, int height);
+ 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, Bar *bar, 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();
+ void clear();
private:
- void plot(int x, int y, double c);
- double ipart(double x);
- double round(double x);
- double fpart(double x);
- double rfpart(double x);
-
- Widget *widget;
- PixelBufferAlpha *pixbuf;
- Colour colour;
-};
-
+ Widget& widget;
+ PixelBufferAlpha* pixbuf;
+ Colour colour;
};
-#endif/*__DRUMGIZMO_PAINTER_H__*/
+} // GUI::
diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc
index 2a6bf6f..962091e 100644
--- a/plugingui/pixelbuffer.cc
+++ b/plugingui/pixelbuffer.cc
@@ -26,155 +26,140 @@
*/
#include "pixelbuffer.h"
-#include <stdio.h>
+#include <cassert>
-GUI::PixelBuffer::PixelBuffer(size_t width, size_t height)
+namespace GUI {
+
+PixelBuffer::PixelBuffer(size_t width, size_t height)
+ : buf(nullptr)
{
- buf = NULL;
- realloc(width, height);
+ realloc(width, height);
}
-GUI::PixelBuffer::~PixelBuffer()
+PixelBuffer::~PixelBuffer()
{
- if(buf) free(buf);
+ free(buf);
}
-void GUI::PixelBuffer::realloc(size_t width, size_t height)
+void PixelBuffer::realloc(size_t width, size_t height)
{
- if(buf) free(buf);
- buf = (unsigned char *)calloc(width * height, 3);
- this->width = width;
- this->height = height;
+ free(buf);
+ buf = (unsigned char *)calloc(width * height, 3);
+ this->width = width;
+ this->height = height;
}
-#define PX(k) (x + y * width) * 3 + k
-void GUI::PixelBuffer::setPixel(size_t x, size_t y,
- unsigned char red,
- unsigned char green,
- unsigned char blue,
- unsigned char alpha)
+#define PX(k) ((x + y * width) * 3 + k)
+void PixelBuffer::setPixel(size_t x, size_t y,
+ unsigned char red,
+ unsigned char green,
+ unsigned char blue,
+ unsigned char alpha)
{
- if(x >= width || y >= height) return;
- /*
- float a,b;
- getAlpha(alpha, 255, a, b);
-
- buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b);
- buf[PX(0)] /= (a + b);
- buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b);
- buf[PX(1)] /= (a + b);
- buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b);
- buf[PX(2)] /= (a + b);
- */
- unsigned int a = alpha;
- unsigned int b = 255 - alpha;
-
- buf[PX(0)] = (unsigned char)(((int)red * a + (int)buf[PX(0)] * b) / 255);
- buf[PX(1)] = (unsigned char)(((int)green * a + (int)buf[PX(1)] * b) / 255);
- buf[PX(2)] = (unsigned char)(((int)blue * a + (int)buf[PX(2)] * b) / 255);
+ assert(x < width);
+ assert(y < height);
+
+ unsigned int a = alpha;
+ unsigned int b = 255 - alpha;
+
+ buf[PX(0)] = (unsigned char)(((int)red * a + (int)buf[PX(0)] * b) / 255);
+ buf[PX(1)] = (unsigned char)(((int)green * a + (int)buf[PX(1)] * b) / 255);
+ buf[PX(2)] = (unsigned char)(((int)blue * a + (int)buf[PX(2)] * b) / 255);
}
-static int idx = 0;
-GUI::PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height)
+PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height)
+ : buf(nullptr)
+ , x(0)
+ , y(0)
{
- this->idx = ::idx++;
- buf = NULL;
- x = y = 10;
- realloc(width, height);
+ realloc(width, height);
}
-GUI::PixelBufferAlpha::~PixelBufferAlpha()
+PixelBufferAlpha::~PixelBufferAlpha()
{
- if(buf) free(buf);
+ free(buf);
}
-void GUI::PixelBufferAlpha::realloc(size_t width, size_t height)
+void PixelBufferAlpha::realloc(size_t width, size_t height)
{
- if(buf) free(buf);
- buf = (unsigned char *)calloc(width * height, 4);
- this->width = width;
- this->height = height;
+ free(buf);
+ buf = (unsigned char *)calloc(width * height, 4);
+ this->width = width;
+ this->height = height;
}
#undef PX
-#define PX(k) (x + y * width) * 4 + k
-void GUI::PixelBufferAlpha::setPixel(size_t x, size_t y,
- unsigned char red,
- unsigned char green,
- unsigned char blue,
- unsigned char alpha)
+#define PX(k) ((x + y * width) * 4 + k)
+void PixelBufferAlpha::setPixel(size_t x, size_t y,
+ unsigned char red,
+ unsigned char green,
+ unsigned char blue,
+ unsigned char alpha)
{
- if(x >= width || y >= height) return;
+ assert(x < width);
+ assert(y < height);
- buf[PX(0)] = red;
- buf[PX(1)] = green;
- buf[PX(2)] = blue;
- buf[PX(3)] = alpha;
+ buf[PX(0)] = red;
+ buf[PX(1)] = green;
+ buf[PX(2)] = blue;
+ buf[PX(3)] = alpha;
}
// http://en.wikipedia.org/wiki/Alpha_compositing
-static void getAlpha(unsigned char _a, unsigned char _b, float &a, float &b)
+static inline void getAlpha(unsigned char _a, unsigned char _b,
+ float &a, float &b)
{
- a = _a / 255.0;
- b = _b / 255.0;
- b *= (1-a);
+ a = _a / 255.0;
+ b = _b / 255.0;
+ b *= (1 - a);
}
-void GUI::PixelBufferAlpha::addPixel(size_t x, size_t y,
- unsigned char red,
- unsigned char green,
- unsigned char blue,
- unsigned char alpha)
+void PixelBufferAlpha::addPixel(size_t x, size_t y,
+ unsigned char red,
+ unsigned char green,
+ unsigned char blue,
+ unsigned char alpha)
{
- if(x >= width || y >= height) return;
+ assert(x < width);
+ assert(y < height);
- if(alpha == 0) return;
+ if(alpha == 0)
+ {
+ return;
+ }
- float a,b;
- getAlpha(alpha, buf[PX(3)], a, b);
+ float a, b;
+ getAlpha(alpha, buf[PX(3)], a, b);
- buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b);
- buf[PX(0)] /= (a + b);
- buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b);
- buf[PX(1)] /= (a + b);
- buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b);
- buf[PX(2)] /= (a + b);
+ buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b);
+ buf[PX(0)] /= (a + b);
+ buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b);
+ buf[PX(1)] /= (a + b);
+ buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b);
+ buf[PX(2)] /= (a + b);
- buf[PX(3)] = (a + b) * 255;
+ buf[PX(3)] = (a + b) * 255;
}
-void GUI::PixelBufferAlpha::addPixel(size_t x, size_t y, GUI::Colour c)
+void PixelBufferAlpha::addPixel(size_t x, size_t y, Colour c)
{
- addPixel(x, y, c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255);
+ addPixel(x, y, c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255);
}
-void GUI::PixelBufferAlpha::pixel(size_t x, size_t y,
- unsigned char *red,
- unsigned char *green,
- unsigned char *blue,
- unsigned char *alpha)
+void PixelBufferAlpha::pixel(size_t x, size_t y,
+ unsigned char* red,
+ unsigned char* green,
+ unsigned char* blue,
+ unsigned char* alpha)
{
- if(x >= width || y >= height) return;
- *red = buf[PX(0)];
- *green = buf[PX(1)];
- *blue = buf[PX(2)];
- *alpha = buf[PX(3)];
-}
-
-#ifdef TEST_PIXELBUFFER
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
+ assert(x < width);
+ assert(y < height);
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
+ *red = buf[PX(0)];
+ *green = buf[PX(1)];
+ *blue = buf[PX(2)];
+ *alpha = buf[PX(3)];
+}
-#endif/*TEST_PIXELBUFFER*/
+} // GUI::
diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h
index 2785eb1..d955c1a 100644
--- a/plugingui/pixelbuffer.h
+++ b/plugingui/pixelbuffer.h
@@ -24,68 +24,64 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_PIXELBUFFER_H__
-#define __DRUMGIZMO_PIXELBUFFER_H__
-
-#include <stdlib.h>
+#pragma once
#include "colour.h"
+#include <stdlib.h>
+
namespace GUI {
class PixelBuffer {
public:
- PixelBuffer(size_t width, size_t height);
- ~PixelBuffer();
+ PixelBuffer(size_t width, size_t height);
+ ~PixelBuffer();
- void realloc(size_t width, size_t height);
+ void realloc(size_t width, size_t height);
- void setPixel(size_t x, size_t y,
- unsigned char red,
- unsigned char green,
- unsigned char blue,
- unsigned char alpha);
+ void setPixel(size_t x, size_t y,
+ unsigned char red,
+ unsigned char green,
+ unsigned char blue,
+ unsigned char alpha);
- unsigned char *buf;
- size_t width;
- size_t height;
+ unsigned char* buf;
+ size_t width;
+ size_t height;
};
class PixelBufferAlpha {
public:
- PixelBufferAlpha(size_t width, size_t height);
- ~PixelBufferAlpha();
-
- int idx;
- size_t x, y;
-
- void realloc(size_t width, size_t height);
-
- void setPixel(size_t x, size_t y,
- unsigned char red,
- unsigned char green,
- unsigned char blue,
- unsigned char alpha);
-
- void addPixel(size_t x, size_t y,
- unsigned char red,
- unsigned char green,
- unsigned char blue,
- unsigned char alpha);
-
- void addPixel(size_t x, size_t y, Colour c);
-
- void pixel(size_t x, size_t y,
- unsigned char *red,
- unsigned char *green,
- unsigned char *blue,
- unsigned char *alpha);
-
- unsigned char *buf;
- size_t width;
- size_t height;
-};
-
+ PixelBufferAlpha(size_t width, size_t height);
+ ~PixelBufferAlpha();
+
+ void realloc(size_t width, size_t height);
+
+ void setPixel(size_t x, size_t y,
+ unsigned char red,
+ unsigned char green,
+ unsigned char blue,
+ unsigned char alpha);
+
+ void addPixel(size_t x, size_t y,
+ unsigned char red,
+ unsigned char green,
+ unsigned char blue,
+ unsigned char alpha);
+
+ void addPixel(size_t x, size_t y, Colour c);
+
+ void pixel(size_t x, size_t y,
+ unsigned char* red,
+ unsigned char* green,
+ unsigned char* blue,
+ unsigned char* alpha);
+
+ unsigned char* buf;
+ size_t width;
+ size_t height;
+ size_t x;
+ size_t y;
};
-#endif/*__DRUMGIZMO_PIXELBUFFER_H__*/
+} // GUI::
diff --git a/plugingui/pluginconfig.cc b/plugingui/pluginconfig.cc
index d4c4477..77cb4ba 100644
--- a/plugingui/pluginconfig.cc
+++ b/plugingui/pluginconfig.cc
@@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
- * config.cc
+ * pluginconfig.cc
*
* Tue Jun 3 13:54:05 CEST 2014
* Copyright 2014 Jonas Suhr Christensen
@@ -27,11 +27,13 @@
#include "pluginconfig.h"
#include <hugin.hpp>
-
+
#define CONFIGFILENAME "plugingui.conf"
+namespace GUI {
+
Config::Config()
- : ConfigFile(CONFIGFILENAME)
+ : ConfigFile(CONFIGFILENAME)
{
}
@@ -41,23 +43,26 @@ Config::~Config()
bool Config::load()
{
- lastkit.clear();
- lastmidimap.clear();
+ lastkit.clear();
+ lastmidimap.clear();
- if(!ConfigFile::load()) {
- return false;
- }
+ if(!ConfigFile::load())
+ {
+ return false;
+ }
- lastkit = getValue("lastkit");
- lastmidimap = getValue("lastmidimap");
+ lastkit = getValue("lastkit");
+ lastmidimap = getValue("lastmidimap");
- return true;
+ return true;
}
bool Config::save()
{
- setValue("lastkit", lastkit);
- setValue("lastmidimap", lastmidimap);
+ setValue("lastkit", lastkit);
+ setValue("lastmidimap", lastmidimap);
- return ConfigFile::save();
+ return ConfigFile::save();
}
+
+} // GUI::
diff --git a/plugingui/pluginconfig.h b/plugingui/pluginconfig.h
index 9bef1f0..a249eb2 100644
--- a/plugingui/pluginconfig.h
+++ b/plugingui/pluginconfig.h
@@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
- * config.h
+ * pluginconfig.h
*
* Tue Jun 3 13:51:29 CEST 2014
* Copyright 2014 Jonas Suhr Christensen
@@ -24,21 +24,22 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_CONFIG_H__
-#define __DRUMGIZMO_CONFIG_H__
+#pragma once
#include <configfile.h>
+namespace GUI {
+
class Config : public ConfigFile {
public:
- Config();
- ~Config();
+ Config();
+ ~Config();
- bool load();
- bool save();
+ bool load();
+ bool save();
- std::string lastkit;
- std::string lastmidimap;
+ std::string lastkit;
+ std::string lastmidimap;
};
-#endif/*__DRUMGIZMO_CONFIG_H__*/
+} // GUI::
diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc
index 170f4f9..a56818c 100644
--- a/plugingui/plugingui.cc
+++ b/plugingui/plugingui.cc
@@ -27,533 +27,222 @@
#include "plugingui.h"
#include <hugin.hpp>
-#include <stdio.h>
-
-#include "knob.h"
-#include "verticalline.h"
-#include "../version.h"
#include "pluginconfig.h"
#include "messagehandler.h"
-static void checkClick(void *ptr)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
-
- ChangeSettingMessage *msg =
- new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier,
- gui->check->checked());
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
-}
-
-static void knobChange(void *ptr)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
-
- ChangeSettingMessage *msg =
- new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight,
- gui->knob->value());
-
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
-
-#ifdef STANDALONE
- int i = gui->knob->value() * 4;
- switch(i) {
- case 0: gui->progress->setState(GUI::ProgressBar::off); break;
- case 1: gui->progress->setState(GUI::ProgressBar::blue); break;
- case 2: gui->progress->setState(GUI::ProgressBar::green); break;
- case 3: gui->progress->setState(GUI::ProgressBar::red); break;
- default: break;
- }
-#endif
-}
-
-static void knobChange2(void *ptr)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
-
- ChangeSettingMessage *msg =
- new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff,
- gui->knob2->value());
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
-
-#ifdef STANDALONE
- gui->progress->setProgress(gui->knob2->value());
-#endif
-}
-
-//static void quit(void *ptr) {
-// PluginGUI *gui = (PluginGUI*)ptr;
-//
-// gui->stopThread();
-//}
-
-GUI::FileBrowser *fb;
-static void selectKitFile(void *ptr, std::string filename)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
-
- gui->lineedit->setText(filename);
-
- fb->hide();
-
- std::string drumkit = gui->lineedit->text();
-
- gui->config->lastkit = drumkit;
- gui->config->save();
-
- gui->progress->setProgress(0);
- gui->progress->setState(GUI::ProgressBar::blue);
-
- LoadDrumKitMessage *msg = new LoadDrumKitMessage();
- msg->drumkitfile = drumkit;
-
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
-}
-
-static void kitBrowseClick(void *ptr)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
-
- std::string path = gui->lineedit->text();
- if(path == "") path = gui->config->lastkit;
- if(path == "") path = gui->lineedit2->text();
-
- fb->setPath(path);
- fb->registerFileSelectHandler(selectKitFile, gui);
- fb->show();
-}
-
-static void selectMapFile(void *ptr, std::string filename)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
-
- gui->lineedit2->setText(filename);
- fb->hide();
-
- std::string midimap = gui->lineedit2->text();
-
- gui->config->lastmidimap = midimap;
- gui->config->save();
-
- LoadMidimapMessage *msg = new LoadMidimapMessage();
- msg->midimapfile = midimap;
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
-
- /*
- if(gui->changeMidimapHandler)
- gui->changeMidimapHandler(gui->changeMidimapPtr, midimap.c_str());
- gui->progress2->setState(GUI::ProgressBar::green);
- */
-}
-
-static void midimapBrowseClick(void *ptr)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
-
- std::string path = gui->lineedit2->text();
- if(path == "") path = gui->config->lastmidimap;
- if(path == "") path = gui->lineedit->text();
-
- fb->setPath(path);
- fb->registerFileSelectHandler(selectMapFile, gui);
- fb->show();
-}
-
-/*
-void closeClick(void *ptr)
-{
- PluginGUI *gui = (PluginGUI*)ptr;
- if(gui->windowClosedHandler) gui->windowClosedHandler(gui->windowClosedPtr);
-}
-*/
+namespace GUI {
PluginGUI::PluginGUI()
- : MessageReceiver(MSGRCV_UI)
- , initialised(false)
- , sem("plugingui")
+ : MessageReceiver(MSGRCV_UI)
{
- windowClosedHandler = NULL;
- changeMidimapHandler = NULL;
-
- window = NULL;
-
- running = true;
- closing = false;
-
#ifdef USE_THREAD
- run();
+ run();
#else
- init();
+ init();
#endif/*USE_THREAD*/
- sem.wait();
+ sem.wait();
}
PluginGUI::~PluginGUI()
{
- stopThread();
+ stopThread();
}
-void PluginGUI::stopThread()
-{
- if(running) {
- running = false;
- wait_stop();
- }
-}
-
-
void PluginGUI::handleMessage(Message *msg)
{
- GUI::Painter p(window);// Make sure we only redraw buffer one time.
-
- switch(msg->type()) {
- case Message::LoadStatus:
- {
- LoadStatusMessage *ls = (LoadStatusMessage*)msg;
- progress->setProgress((float)ls->numer_of_files_loaded /
- (float)ls->number_of_files);
- if(ls->numer_of_files_loaded == ls->number_of_files) {
- progress->setState(GUI::ProgressBar::green);
- }
- }
- break;
- case Message::LoadStatusMidimap:
- {
- LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg;
- progress2->setProgress(1);
- if(ls->success) {
- progress2->setState(GUI::ProgressBar::green);
- } else {
- progress2->setState(GUI::ProgressBar::red);
- }
- }
- break;
- case Message::EngineSettingsMessage:
- {
- EngineSettingsMessage *settings = (EngineSettingsMessage *)msg;
- lineedit->setText(settings->drumkitfile);
- if(settings->drumkit_loaded) {
- progress->setProgress(1);
- progress->setState(GUI::ProgressBar::green);
- } else {
- progress->setProgress(0);
- progress->setState(GUI::ProgressBar::blue);
- }
- lineedit2->setText(settings->midimapfile);
- if(settings->midimap_loaded) {
- progress2->setProgress(1);
- progress2->setState(GUI::ProgressBar::green);
- } else {
- progress2->setProgress(0);
- progress2->setState(GUI::ProgressBar::blue);
- }
- check->setChecked(settings->enable_velocity_modifier);
- knob->setValue(settings->velocity_modifier_weight);
- knob2->setValue(settings->velocity_modifier_falloff);
-
- }
- default:
- break;
- }
+ Painter p(*window);// Make sure we only redraw buffer once (set refcount to 1)
+
+ switch(msg->type()) {
+ case Message::LoadStatus:
+ {
+ LoadStatusMessage *ls = (LoadStatusMessage*)msg;
+ window->drumkitFileProgress->setProgress((float)ls->numer_of_files_loaded /
+ (float)ls->number_of_files);
+ if(ls->numer_of_files_loaded == ls->number_of_files)
+ {
+ window->drumkitFileProgress->setState(ProgressBarState::Green);
+ }
+ }
+ break;
+ case Message::LoadStatusMidimap:
+ {
+ LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg;
+ window->midimapFileProgress->setProgress(1);
+ if(ls->success)
+ {
+ window->midimapFileProgress->setState(ProgressBarState::Green);
+ }
+ else
+ {
+ window->midimapFileProgress->setState(ProgressBarState::Red);
+ }
+ }
+ break;
+ case Message::EngineSettingsMessage:
+ {
+ EngineSettingsMessage *settings = (EngineSettingsMessage *)msg;
+ window->lineedit->setText(settings->drumkitfile);
+ if(settings->drumkit_loaded)
+ {
+ window->drumkitFileProgress->setProgress(1);
+ window->drumkitFileProgress->setState(ProgressBarState::Green);
+ }
+ else
+ {
+ window->drumkitFileProgress->setProgress(0);
+ window->drumkitFileProgress->setState(ProgressBarState::Blue);
+ }
+ window->lineedit2->setText(settings->midimapfile);
+ if(settings->midimap_loaded)
+ {
+ window->midimapFileProgress->setProgress(1);
+ window->midimapFileProgress->setState(ProgressBarState::Green);
+ }
+ else
+ {
+ window->midimapFileProgress->setProgress(0);
+ window->midimapFileProgress->setState(ProgressBarState::Blue);
+ }
+ window->velocityCheck->setChecked(settings->enable_velocity_modifier);
+ window->attackKnob->setValue(settings->velocity_modifier_weight);
+ window->falloffKnob->setValue(settings->velocity_modifier_falloff);
+ }
+ default:
+ break;
+ }
}
void PluginGUI::thread_main()
{
- init();
+ init();
- { // Request all engine settings
- EngineSettingsMessage *msg = new EngineSettingsMessage();
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
- }
+ { // Request all engine settings
+ EngineSettingsMessage *msg = new EngineSettingsMessage();
+ msghandler.sendMessage(MSGRCV_ENGINE, msg);
+ }
- while(running) {
+ while(processEvents())
+ {
#ifdef WIN32
- SleepEx(50, FALSE);
+ SleepEx(50, FALSE);
#else
- usleep(50000);
+ usleep(50000);
#endif/*WIN32*/
+ }
- // DEBUG(gui, "loop");
-
- window->eventHandler()->processEvents();
- handleMessages();
- }
-
- deinit();
+ deinit();
}
-void PluginGUI::deinit()
+bool PluginGUI::processEvents()
{
- if(config) {
- config->save();
- delete config;
- }
- if(window) delete window;
+ if(!initialised)
+ {
+ return running;
+ }
+
+ window->eventHandler()->processEvents();
+ handleMessages();
+
+ if(closing)
+ {
+ closeNotifier();
+ closing = false;
+ return false;
+ }
+
+ return running;
}
-void closeEventHandler(void *ptr)
+void PluginGUI::stopThread()
{
- volatile bool *closing = (volatile bool*)ptr;
- *closing = true;
+ if(running)
+ {
+ running = false;
+ wait_stop();
+ }
}
void PluginGUI::init()
{
- DEBUG(gui, "init");
-
- config = new Config();
- config->load();
-
- window = new GUI::Window();
- window->eventHandler()->registerCloseHandler(closeEventHandler,
- (void*)&closing);
-
- window->setFixedSize(370, 330);
- window->setCaption("DrumGizmo v" VERSION);
-
- GUI::Label *lbl_title = new GUI::Label(window);
- lbl_title->setText("DrumGizmo");
- lbl_title->move(127, 7);
- lbl_title->resize(200, 20);
-
- GUI::VerticalLine *l1 = new GUI::VerticalLine(window);
- l1->move(20, 30);
- l1->resize(window->width() - 40, 2);
-
-#define OFFSET1 17
-#define OFFSET2 38
-#define OFFSET3 20
-
-#define XOFFSET 20
- // Drumkit file
- {
- int y = 37;
- GUI::Label *lbl = new GUI::Label(window);
- lbl->setText("Drumkit file:");
- lbl->move(XOFFSET - 4, y);
- lbl->resize(100, 20);
-
- y += OFFSET1;
- lineedit = new GUI::LineEdit(window);
- lineedit->move(XOFFSET, y);
- lineedit->resize(243, 29);
- lineedit->setReadOnly(true);
-
- GUI::Button *btn_brw = new GUI::Button(window);
- btn_brw->setText("Browse...");
- btn_brw->move(266, y - 6 + 4);
- btn_brw->resize(85, 35 + 6 - 4);
- btn_brw->registerClickHandler(kitBrowseClick, this);
-
- y += OFFSET2;
- progress = new GUI::ProgressBar(window);
- progress->move(XOFFSET, y);
- progress->resize(window->width() - 2*XOFFSET, 11);
-
- y += OFFSET3;
- GUI::VerticalLine *l = new GUI::VerticalLine(window);
- l->move(XOFFSET, y);
- l->resize(window->width() - 2*XOFFSET, 2);
- }
-
- // Midimap file
- {
- int y = 120;
- lbl2 = new GUI::Label(window);
- lbl2->setText("Midimap file:");
- lbl2->move(XOFFSET - 4, y);
- lbl2->resize(100, 20);
-
- y += OFFSET1;
- lineedit2 = new GUI::LineEdit(window);
- lineedit2->move(XOFFSET, y);
- lineedit2->resize(243, 29);
- lineedit2->setReadOnly(true);
-
- GUI::Button *btn_brw = new GUI::Button(window);
- btn_brw->setText("Browse...");
- btn_brw->move(266, y - 6 + 4);
- btn_brw->resize(85, 35 + 6 - 4);
- btn_brw->registerClickHandler(midimapBrowseClick, this);
-
- y += OFFSET2;
- progress2 = new GUI::ProgressBar(window);
- progress2->move(XOFFSET, y);
- progress2->resize(window->width() - 2*XOFFSET, 11);
-
- y += OFFSET3;
- GUI::VerticalLine *l = new GUI::VerticalLine(window);
- l->move(XOFFSET, y);
- l->resize(window->width() - 2*XOFFSET, 2);
- }
-
- {
- int y = 203;
-#define OFFSET4 21
-
- // Enable Velocity
- GUI::Label *lbl_velocity = new GUI::Label(window);
- lbl_velocity->resize(78 ,20);
- lbl_velocity->move(16, y);
- lbl_velocity->setText("Humanizer");
-
- check = new GUI::CheckBox(window);
- //check->setText("Enable Velocity Modifier");
- check->move(26, y + OFFSET4);
- check->resize(59,38);
- check->registerClickHandler(checkClick, this);
-
- // Velocity Weight Modifier:
- {
- GUI::Label *lbl_weight = new GUI::Label(window);
- lbl_weight->setText("Attack");
- lbl_weight->move(107, y);
- lbl_weight->resize(100, 20);
-
- knob = new GUI::Knob(window);
- knob->move(109, y + OFFSET4 - 4);
- knob->resize(57, 57);
- knob->registerClickHandler(knobChange, this);
- }
-
- // Velocity Falloff Modifier:
- {
- GUI::Label *lbl_falloff = new GUI::Label(window);
- lbl_falloff->setText("Release");
- lbl_falloff->move(202 - 17 - 7, y);
- lbl_falloff->resize(100, 20);
-
- knob2 = new GUI::Knob(window);
- knob2->move(202 - 13 - 5, y + OFFSET4 - 4);
- knob2->resize(57, 57);
- knob2->registerClickHandler(knobChange2, this);
- }
- }
-
- GUI::VerticalLine *l2 = new GUI::VerticalLine(window);
- l2->move(20, 310 - 15 - 9);
- l2->resize(window->width() - 40, 2);
-
- GUI::Label *lbl_version = new GUI::Label(window);
- lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. GPLv3 .::.");
- lbl_version->move(16, 300);
- lbl_version->resize(window->width(), 20);
- /*
- {
- GUI::ComboBox *cmb = new GUI::ComboBox(window);
- cmb->addItem("Foo", "Bar");
- cmb->addItem("Hello", "World");
- cmb->move(10,10);
- cmb->resize(70, 30);
- }
- */
- // Create filebrowser
- filebrowser = new GUI::FileBrowser(window);
- filebrowser->move(0, 0);
- filebrowser->resize(window->width() - 1, window->height() - 1);
- filebrowser->hide();
- fb = filebrowser;
-
- // Enable quit button
-// GUI::Button *btn_quit = new GUI::Button(window);
-// btn_quit->setText("Quit");
-// btn_quit->move(50,280);
-// btn_quit->resize(80,80);
-// btn_quit->registerClickHandler(quit, this);
-
- window->show();
-
- sem.post();
-
- initialised = true;
-}
+ DEBUG(gui, "init");
-void PluginGUI::show()
-{
- while(!initialised) usleep(10000);
+ config = new Config();
+ config->load();
+
+ window = new DGWindow(msghandler, *config);
- if(!window) init();
+ auto eventHandler = window->eventHandler();
+ CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler);
- window->show();
+ window->show();
+
+ sem.post();
+
+ initialised = true;
}
-void PluginGUI::hide()
+void PluginGUI::deinit()
{
- while(!initialised) usleep(10000);
+ if(config)
+ {
+ config->save();
+ delete config;
+ }
- if(window) window->hide();
+ if(window)
+ {
+ delete window;
+ }
}
-void PluginGUI::processEvents()
+void PluginGUI::show()
{
- if(!initialised) return;
+ while(!initialised)
+ {
+ usleep(10000);
+ }
- if(closing) {
- if(windowClosedHandler) windowClosedHandler(windowClosedPtr);
- closing = false;
- }
+ if(!window)
+ {
+ init();
+ }
-#ifndef USE_THREAD
- window->eventHandler()->processEvents(window);
-#endif/*USE_THREAD*/
+ if(window)
+ {
+ window->show();
+ }
}
-void PluginGUI::setWindowClosedCallback(void (*handler)(void *), void *ptr)
+void PluginGUI::hide()
{
- windowClosedHandler = handler;
- windowClosedPtr = ptr;
-}
-
-#ifdef STANDALONE
-
-class Engine : public MessageHandler {
-public:
- void handleMessage(Message *msg) {}
-};
+ while(!initialised)
+ {
+ usleep(10000);
+ }
+ if(window)
+ {
+ window->hide();
+ }
+}
-void stop(void *ptr)
+void PluginGUI::setWindowClosedCallback(void (*handler)(void *), void* ptr)
{
- DEBUG(stop, "Stopping...\n");
- bool *running = (bool*)ptr;
- *running = false;
+ windowClosedHandler = handler;
+ windowClosedPtr = ptr;
}
-int main()
+void PluginGUI::closeEventHandler()
{
-/*
- hug_status_t status = hug_init(HUG_FLAG_OUTPUT_TO_SYSLOG,
- HUG_OPTION_SYSLOG_HOST, "192.168.0.10",
- HUG_OPTION_SYSLOG_PORT, 514,
- HUG_OPTION_END);
-
- if(status != HUG_STATUS_OK) {
- printf("Error: %d\n", status);
- return 1;
- }
-*/
- INFO(example, "We are up and running");
-
- bool running = true;
-
- PluginGUI gui;
- gui.setWindowClosedCallback(stop, &running);
-
- // gui.show();
-
- while(running) {
- // gui.processEvents();
-#ifdef WIN32
- SleepEx(1000, FALSE);
-#else
- // usleep(10000);
- sleep(1);
-#endif
- }
-
- return 0;
+ closing = true;
+ closeNotifier();
+ // Call old-style notifier if one is registered.
+ if(windowClosedHandler)
+ {
+ windowClosedHandler(windowClosedPtr);
+ }
}
-#endif/*STANDALONE*/
+} // GUI::
diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h
index 39643e1..b57855a 100644
--- a/plugingui/plugingui.h
+++ b/plugingui/plugingui.h
@@ -24,77 +24,67 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_PLUGINGUI_H__
-#define __DRUMGIZMO_PLUGINGUI_H__
+#pragma once
-#include "window.h"
+#include "dgwindow.h"
#include "eventhandler.h"
-#include "label.h"
-#include "lineedit.h"
-#include "checkbox.h"
-#include "button.h"
-#include "knob.h"
-#include "progressbar.h"
#include "pluginconfig.h"
-#include "filebrowser.h"
#include "thread.h"
#include "semaphore.h"
#include "messagereceiver.h"
+#include "notifier.h"
-class PluginGUI : public Thread, public MessageReceiver {
+namespace GUI {
+
+class PluginGUI : public Thread, public MessageReceiver, public Listener {
public:
- PluginGUI();
- virtual ~PluginGUI();
+ PluginGUI();
+ virtual ~PluginGUI();
- void thread_main();
- void stopThread();
+ void thread_main();
- void init();
- void deinit();
+ //! Process all events and messages in queue
+ //! \return true if not closing, returns false if closing.
+ bool processEvents();
- void show();
- void hide();
- void processEvents();
- void setWindowClosedCallback(void (*handler)(void *), void *ptr);
+ void stopThread();
- void handleMessage(Message *msg);
+ void init();
+ void deinit();
- //private:
- GUI::Window *window;
- GUI::EventHandler *eventhandler;
+ void show();
+ void hide();
- GUI::FileBrowser *filebrowser;
- GUI::CheckBox *check;
- GUI::Knob *knob;
- GUI::Knob *knob2;
+ void handleMessage(Message* msg);
- GUI::Label *lbl;
- GUI::LineEdit *lineedit;
- GUI::ProgressBar *progress;
+ DGWindow* window{nullptr};
+ EventHandler* eventhandler{nullptr};
- GUI::Label *lbl2;
- GUI::LineEdit *lineedit2;
- GUI::ProgressBar *progress2;
- Config *config;
+ Config* config{nullptr};
- void (*windowClosedHandler)(void *);
- void *windowClosedPtr;
+ Notifier<> closeNotifier;
- void (*changeMidimapHandler)(void *, const char *);
- void *changeMidimapPtr;
+ // Support old interface a little while longer..
+ void setWindowClosedCallback(void (*handler)(void*), void* ptr);
private:
- volatile bool running;
- volatile bool closing;
- volatile bool initialised;
+ void closeEventHandler();
+
+ volatile bool running{true};
+ volatile bool closing{false};
+ volatile bool initialised{false};
+
+ Semaphore sem{"plugingui"};
- Semaphore sem;
+ // For the old-style notifier.
+ void (*windowClosedHandler)(void *){nullptr};
+ void *windowClosedPtr{nullptr};
};
-#endif/*__DRUMGIZMO_PLUGINGUI_H__*/
+} // GUI::
diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc
index 3b821bb..6882789 100644
--- a/plugingui/progressbar.cc
+++ b/plugingui/progressbar.cc
@@ -26,83 +26,101 @@
*/
#include "progressbar.h"
-#include "painter.h"
+namespace GUI {
-GUI::ProgressBar::ProgressBar(GUI::Widget *parent) : GUI::Widget(parent)
+ProgressBar::ProgressBar(Widget *parent)
+ : Widget(parent)
{
- bar_bg.left = new Image(":progress_back_l.png");
- bar_bg.right = new Image(":progress_back_r.png");
- bar_bg.center = new Image(":progress_back_c.png");
+ bar_bg.left = new Image(":progress_back_l.png");
+ bar_bg.right = new Image(":progress_back_r.png");
+ bar_bg.center = new Image(":progress_back_c.png");
- bar_blue.left = new Image(":progress_front_blue_l.png");
- bar_blue.right = new Image(":progress_front_blue_r.png");
- bar_blue.center = new Image(":progress_front_blue_c.png");
+ bar_blue.left = new Image(":progress_front_blue_l.png");
+ bar_blue.right = new Image(":progress_front_blue_r.png");
+ bar_blue.center = new Image(":progress_front_blue_c.png");
- bar_red.left = new Image(":progress_front_red_l.png");
- bar_red.right = new Image(":progress_front_red_r.png");
- bar_red.center = new Image(":progress_front_red_c.png");
+ bar_red.left = new Image(":progress_front_red_l.png");
+ bar_red.right = new Image(":progress_front_red_r.png");
+ bar_red.center = new Image(":progress_front_red_c.png");
- bar_green.left = new Image(":progress_front_green_l.png");
- bar_green.right = new Image(":progress_front_green_r.png");
- bar_green.center = new Image(":progress_front_green_c.png");
+ bar_green.left = new Image(":progress_front_green_l.png");
+ bar_green.right = new Image(":progress_front_green_r.png");
+ bar_green.center = new Image(":progress_front_green_c.png");
- state = blue;
- _progress = .5;
+ state = ProgressBarState::Blue;
+ _progress = .5;
}
-void GUI::ProgressBar::setState(GUI::ProgressBar::state_t state)
+ProgressBar::~ProgressBar()
{
- if(this->state != state) {
- this->state = state;
- repaintEvent(NULL);
- }
+ delete bar_bg.left;
+ delete bar_bg.right;
+ delete bar_bg.center;
+
+ delete bar_blue.left;
+ delete bar_blue.right;
+ delete bar_blue.center;
+
+ delete bar_red.left;
+ delete bar_red.right;
+ delete bar_red.center;
+
+ delete bar_green.left;
+ delete bar_green.right;
+ delete bar_green.center;
}
-float GUI::ProgressBar::progress()
+void ProgressBar::setState(ProgressBarState state)
{
- return _progress;
+ if(this->state != state)
+ {
+ this->state = state;
+ repaintEvent(nullptr);
+ }
}
-void GUI::ProgressBar::setProgress(float progress)
+float ProgressBar::progress()
{
- _progress = progress;
- repaintEvent(NULL);
+ return _progress;
}
-void GUI::ProgressBar::repaintEvent(GUI::RepaintEvent *e)
+void ProgressBar::setProgress(float progress)
{
- Painter p(this);
-
- int max = width() * _progress;
-
- p.clear();
-
- int brd = 4;
- p.drawBar(0, 0, &bar_bg, width(), height());
-
- GUI::Painter::Bar *b = NULL;
- switch(state) {
- case red: b = &bar_red; break;
- case green: b = &bar_green; break;
- case blue: b = &bar_blue; break;
- default: break;
- }
- if(b) p.drawBar(brd, 0, b, max - 2*brd, height());
+ _progress = progress;
+ repaintEvent(nullptr);
}
-#ifdef TEST_PROGRESSBAR
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
+void ProgressBar::repaintEvent(RepaintEvent* repaintEvent)
+{
+ Painter p(*this);
+
+ int max = width() * _progress;
+
+ p.clear();
+
+ int brd = 4;
+ p.drawBar(0, 0, bar_bg, width(), height());
+
+ Painter::Bar* bar = nullptr;
+ switch(state) {
+ case ProgressBarState::Red:
+ bar = &bar_red;
+ break;
+ case ProgressBarState::Green:
+ bar = &bar_green;
+ break;
+ case ProgressBarState::Blue:
+ bar = &bar_blue;
+ break;
+ case ProgressBarState::Off:
+ bar = nullptr;
+ break;
+ }
+
+ if(bar)
+ {
+ p.drawBar(brd, 0, *bar, max - 2 * brd, height());
+ }
+}
-#endif/*TEST_PROGRESSBAR*/
+} // GUI::
diff --git a/plugingui/progressbar.h b/plugingui/progressbar.h
index 9d08a9e..26fbbea 100644
--- a/plugingui/progressbar.h
+++ b/plugingui/progressbar.h
@@ -24,48 +24,47 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_PROGRESSBAR_H__
-#define __DRUMGIZMO_PROGRESSBAR_H__
+#pragma once
#include "widget.h"
-#include <string>
-
#include "guievent.h"
#include "painter.h"
namespace GUI {
+enum class ProgressBarState
+{
+ Red,
+ Green,
+ Blue,
+ Off
+};
+
class ProgressBar : public Widget {
public:
- ProgressBar(Widget *parent);
+ ProgressBar(Widget *parent);
+ ~ProgressBar();
- float progress();
- void setProgress(float progress);
+ float progress();
+ void setProgress(float progress);
- typedef enum {
- red,
- green,
- blue,
- off
- } state_t;
- void setState(state_t state);
+ void setState(ProgressBarState state);
- //protected:
- virtual void repaintEvent(RepaintEvent *e);
+protected:
+ // From Widget:
+ virtual void repaintEvent(RepaintEvent* repaintEvent) override;
private:
- state_t state;
+ ProgressBarState state;
- Painter::Bar bar_bg;
+ Painter::Bar bar_bg;
- Painter::Bar bar_green;
- Painter::Bar bar_blue;
- Painter::Bar bar_red;
-
- float _progress;
-};
+ Painter::Bar bar_green;
+ Painter::Bar bar_blue;
+ Painter::Bar bar_red;
+ float _progress;
};
-#endif/*__DRUMGIZMO_PROGRESSBAR_H__*/
+} // GUI::
diff --git a/plugingui/resource.cc b/plugingui/resource.cc
index 80bd51e..c0248c3 100644
--- a/plugingui/resource.cc
+++ b/plugingui/resource.cc
@@ -26,94 +26,119 @@
*/
#include "resource.h"
-#include <stdio.h>
#include <hugin.hpp>
+#include <cstdio>
+
+// rcgen generated file containing rc_data declaration.
#include "resource_data.h"
-GUI::Resource::Resource(std::string name)
+namespace GUI {
+
+// Internal resources start with a colon.
+static bool nameIsInternal(const std::string& name)
+{
+ return name.size() && (name[0] == ':');
+}
+
+Resource::Resource(const std::string& name)
{
- is_valid = false;
- is_internal = false;
-
- if(name.length() == 0) return;
- if(name[0] == ':') {
- i_data = NULL;
- i_size = 0;
-
- // Use internal resource:
- const rc_data_t *p = rc_data;
- while(p->name[0] == ':') {
- if(std::string(p->name) == name) {
- i_data = p->data;
- i_size = p->size;
- break;
- }
- p++;
- }
-
- // We did not find the named resource.
- if(i_data == NULL) {
- ERR(rc, "Could not find '%s'\n", name.c_str());
- return;
- }
-
- is_internal = true;
- } else {
- // Read from file:
- FILE *fp = fopen(name.c_str(), "r");
- if(!fp) return;
- char buf[32];
- while(!feof(fp)) {
- size_t sz = fread(buf, 1, sizeof(buf), fp);
- e_data.append(buf, sz);
- }
- fclose(fp);
- is_internal = 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
+ {
+ // Read from file:
+ std::FILE *fp = std::fopen(name.c_str(), "rb");
+ if(!fp)
+ {
+ return;
+ }
+
+ // Get the file size
+ std::fseek(fp, 0, SEEK_END);
+ size_t filesize = ftell(fp);
+
+ // 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;
}
- is_valid = true;
+ isValid = true;
}
-const char *GUI::Resource::data()
+const char *Resource::data()
{
- if(is_valid == false) return NULL;
- if(is_internal) {
- return i_data;
- } else {
- return e_data.data();
- }
- return NULL;
+ if(isValid == false)
+ {
+ return nullptr;
+ }
+
+ if(isInternal)
+ {
+ return internalData;
+ }
+ else
+ {
+ return externalData.data();
+ }
}
-size_t GUI::Resource::size()
+size_t Resource::size()
{
- if(is_valid == false) return 0;
- if(is_internal) {
- return i_size;
- } else {
- return e_data.length();
- }
- return 0;
+ if(isValid == false)
+ {
+ return 0;
+ }
+
+ if(isInternal)
+ {
+ return internalSize;
+ }
+ else
+ {
+ return externalData.length();
+ }
}
-bool GUI::Resource::valid()
+bool Resource::valid()
{
- return is_valid;
+ return isValid;
}
-#ifdef TEST_RESOURCE
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_RESOURCE*/
+} // GUI::
diff --git a/plugingui/resource.h b/plugingui/resource.h
index 4b494f7..2246271 100644
--- a/plugingui/resource.h
+++ b/plugingui/resource.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_RESOURCE_H__
-#define __DRUMGIZMO_RESOURCE_H__
+#pragma once
#include <string>
@@ -33,21 +32,19 @@ namespace GUI {
class Resource {
public:
- Resource(std::string name);
+ Resource(const std::string& name);
- const char *data();
- size_t size();
+ const char* data();
+ size_t size();
- bool valid();
+ bool valid();
-private:
- std::string e_data;
- bool is_valid;
- bool is_internal;
- const char *i_data;
- size_t i_size;
+protected:
+ std::string externalData;
+ bool isValid{false};
+ bool isInternal{false};
+ const char *internalData{nullptr};
+ size_t internalSize{0};
};
-};
-
-#endif/*__DRUMGIZMO_RESOURCE_H__*/
+} // GUI::
diff --git a/plugingui/resource_data.h b/plugingui/resource_data.h
index c81c6cc..5d6392f 100644
--- a/plugingui/resource_data.h
+++ b/plugingui/resource_data.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_RESOURCE_DATA_H__
-#define __DRUMGIZMO_RESOURCE_DATA_H__
+#pragma once
typedef struct {
const char *name;
@@ -34,5 +33,3 @@ typedef struct {
} rc_data_t;
extern const rc_data_t rc_data[];
-
-#endif/*__DRUMGIZMO_RESOURCE_DATA_H__*/
diff --git a/plugingui/scrollbar.cc b/plugingui/scrollbar.cc
index 07dc36b..2a9d3fd 100644
--- a/plugingui/scrollbar.cc
+++ b/plugingui/scrollbar.cc
@@ -30,156 +30,180 @@
#include "painter.h"
-GUI::ScrollBar::ScrollBar(GUI::Widget *parent)
- : GUI::Widget(parent), bg_img(":widget_c.png")
+namespace GUI {
+
+ScrollBar::ScrollBar(Widget *parent)
+ : Widget(parent)
+ , bg_img(":widget_c.png")
{
- handler = NULL;
- ptr = NULL;
}
-void GUI::ScrollBar::setRange(int r)
+void ScrollBar::setRange(int r)
{
- DEBUG(scroll, "%d\n", r);
- ran = r;
- setValue(value());
- repaintEvent(NULL);
+ rangeValue = r;
+ setValue(value());
+ repaintEvent(nullptr);
}
-int GUI::ScrollBar::range()
+int ScrollBar::range()
{
- return ran;
+ return rangeValue;
}
-void GUI::ScrollBar::setMaximum(int m)
+void ScrollBar::setMaximum(int m)
{
- DEBUG(scroll, "%d\n", m);
- max = m;
- if(max < ran) ran = max;
- setValue(value());
- repaintEvent(NULL);
+ maxValue = m;
+ if(maxValue < rangeValue)
+ {
+ rangeValue = maxValue;
+ }
+ setValue(value());
+ repaintEvent(nullptr);
}
-int GUI::ScrollBar::maximum()
+int ScrollBar::maximum()
{
- return max;
+ return maxValue;
}
-void GUI::ScrollBar::setValue(int value)
+void ScrollBar::addValue(int delta)
{
- val = value;
- if(val > max - ran) val = max - ran;
- if(val < 0) val = 0;
-
- if(handler) handler(ptr);
-
- repaintEvent(NULL);
+ setValue(value() + delta);
}
-int GUI::ScrollBar::value()
+void ScrollBar::setValue(int value)
{
- return val;
+ if(value > (maxValue - rangeValue))
+ {
+ value = maxValue - rangeValue;
+ }
+
+ if(value < 0)
+ {
+ value = 0;
+ }
+
+ if(currentValue == value)
+ {
+ return;
+ }
+
+ currentValue = value;
+
+ valueChangeNotifier(value);
+
+ repaintEvent(nullptr);
}
-void GUI::ScrollBar::registerValueChangeHandler(void (*handler)(void *),
- void *ptr)
+int ScrollBar::value()
{
- this->handler = handler;
- this->ptr = ptr;
+ return currentValue;
}
-static void drawArrow(GUI::Painter &p, int x, int y, int w, int h)
+//! 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;
+ if(h < 0)
+ {
+ y -= h;
+ }
- p.drawLine(x, y, x+(w/2), y+h);
- p.drawLine(x+(w/2), y+h, x+w, y);
+ 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);
+ ++y;
+ p.drawLine(x, y, x + (w / 2), y + h);
+ p.drawLine(x + (w / 2), y + h, x + w, y);
}
-void GUI::ScrollBar::repaintEvent(RepaintEvent *e)
+void ScrollBar::repaintEvent(RepaintEvent* repaintEvent)
{
- GUI::Painter p(this);
+ Painter p(*this);
- p.clear();
+ p.clear();
- p.drawImageStretched(0, 0, &bg_img, width(), height());
+ p.drawImageStretched(0, 0, bg_img, width(), height());
- p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
- if(!max) return;
+ p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1));
+ if(!maxValue)
+ {
+ return;
+ }
- {
- int h = height() - 2 * width() - 3;
- int offset = width() + 2;
+ {
+ int h = height() - 2 * width() - 3;
+ int offset = width() + 2;
- int y_val1 = (val * h) / max;
- int y_val2 = ((val + ran) * h) / max;
+ int y_val1 = (currentValue * h) / maxValue;
+ int y_val2 = ((currentValue + rangeValue) * h) / maxValue;
- p.drawFilledRectangle(2, y_val1 + offset, width() - 1, y_val2 + offset);
- }
+ p.drawFilledRectangle(2, y_val1 + offset, width() - 1, y_val2 + offset);
+ }
- p.drawLine(0, 0, 0, height());
+ 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, 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());
+ drawArrow(p, width()/4, height() - width() + width()/4, width()/2, width()/3);
+ p.drawLine(0, height() - width(), width(), height() - width());
}
-void GUI::ScrollBar::scrollEvent(ScrollEvent *e)
+void ScrollBar::scrollEvent(ScrollEvent* scrollEvent)
{
- setValue(value() + e->delta);
+ setValue(value() + scrollEvent->delta);
}
-void GUI::ScrollBar::mouseMoveEvent(MouseMoveEvent *e)
+void ScrollBar::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent)
{
- if(!dragging) return;
+ if(!dragging)
+ {
+ return;
+ }
- float delta = yoffset - e->y;
+ float delta = yOffset - mouseMoveEvent->y;
- int h = height() - 2 * width() - 3;
- delta /= (float)h / (float)max;
+ int h = height() - 2 * width() - 3;
+ delta /= (float)h / (float)maxValue;
- int newval = value_offset - delta;
- if(newval != value()) setValue(newval);
+ int newval = valueOffset - delta;
+ if(newval != value())
+ {
+ setValue(newval);
+ }
}
-void GUI::ScrollBar::buttonEvent(ButtonEvent *e)
+void ScrollBar::buttonEvent(ButtonEvent* buttonEvent)
{
- if(e->y < (int)width() && e->y > 0) {
- if(e->direction == -1) setValue(value() - 1);
- return;
- }
-
- if(e->y > (int)height() - (int)width() && e->y < (int)height()) {
- if(e->direction == -1) setValue(value() + 1);
- return;
- }
-
- if(e->direction == 1) {
- yoffset = e->y;
- value_offset = value();
- }
-
- dragging = (e->direction == 1);
+ 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);
}
-#ifdef TEST_SCROLLBAR
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_SCROLLBAR*/
+} // GUI::
diff --git a/plugingui/scrollbar.h b/plugingui/scrollbar.h
index 52acf9d..99f8377 100644
--- a/plugingui/scrollbar.h
+++ b/plugingui/scrollbar.h
@@ -24,52 +24,51 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_SCROLLBAR_H__
-#define __DRUMGIZMO_SCROLLBAR_H__
+#pragma once
+
+#include <limits>
#include "widget.h"
#include "image.h"
+#include "notifier.h"
namespace GUI {
class ScrollBar : public Widget {
+ friend class ListBoxBasic;
public:
- ScrollBar(Widget *parent);
-
- bool catchMouse() { return true; }
+ ScrollBar(Widget *parent);
- void setRange(int range);
- int range();
+ void setRange(int range);
+ int range();
- void setMaximum(int max);
- int maximum();
+ void setMaximum(int max);
+ int maximum();
- void setValue(int value);
- int value();
+ void addValue(int delta);
+ void setValue(int value);
+ int value();
- void registerValueChangeHandler(void (*handler)(void *), void *ptr);
+ Notifier<int> valueChangeNotifier; // (int value)
- void repaintEvent(RepaintEvent *e);
- void scrollEvent(ScrollEvent *e);
- void buttonEvent(ButtonEvent *e);
- void mouseMoveEvent(MouseMoveEvent *e);
+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 max;
- int val;
- int ran;
-
- int yoffset;
- int value_offset;
- bool dragging;
+ int maxValue{100};
+ int currentValue{0};
+ int rangeValue{10};
- Image bg_img;
+ int yOffset{0};
+ int valueOffset{0};
+ bool dragging{false};
- void (*handler)(void *);
- void *ptr;
+ Image bg_img;
};
-};
-
-
-#endif/*__DRUMGIZMO_SCROLLBAR_H__*/
+} // GUI::
diff --git a/plugingui/slider.cc b/plugingui/slider.cc
index 953c8e6..a3c10f9 100644
--- a/plugingui/slider.cc
+++ b/plugingui/slider.cc
@@ -31,128 +31,132 @@
#include <hugin.hpp>
#include <stdio.h>
-GUI::Slider::Slider(Widget *parent)
- : GUI::Widget(parent)
-{
- state = up;
+namespace GUI {
- val = 0.0;
- maximum = 1.0;
- minimum = 0.0;
+Slider::Slider(Widget *parent)
+ : Widget(parent)
+{
+ state = State::up;
- handler = NULL;
- ptr = NULL;
+ currentValue = 0.0;
+ maximum = 1.0;
+ minimum = 0.0;
}
-void GUI::Slider::setValue(float v)
+void Slider::setValue(float newValue)
{
- val = v;
- if(handler) handler(ptr);
- repaintEvent(NULL);
+ currentValue = newValue;
+ repaintEvent(nullptr);
+ clickNotifier();
}
-float GUI::Slider::value()
+float Slider::value()
{
- return val;
+ return currentValue;
}
-void GUI::Slider::registerClickHandler(void (*handler)(void *), void *ptr)
+void Slider::repaintEvent(RepaintEvent* repaintEvent)
{
- this->handler = handler;
- this->ptr = ptr;
+ Painter p(*this);
+
+ float alpha = 0.8;
+
+ int xpos = (int)((currentValue / maximum) * (float)(width() - 1));
+
+ if(hasKeyboardFocus())
+ {
+ p.setColour(Colour(0.6, alpha));
+ }
+ else
+ {
+ p.setColour(Colour(0.5, alpha));
+ }
+
+ p.drawFilledRectangle(0,0,width(),height());
+
+ //p.setColour(Colour(0.1, alpha));
+ //p.drawRectangle(0,0,width()-1,height() - 1);
+
+ p.setColour(Colour(1, 0, 0, alpha));
+ p.drawLine(xpos, 0, xpos, height() - 1);
+
+ //p.setColour(Colour(0.8, alpha));
+ //switch(state) {
+ //case State::up:
+ // p.drawLine(0, 0, 0, height() - 1);
+ // p.drawLine(0, 0, width() - 1, 0);
+ // break;
+ //case State::down:
+ // p.drawLine(width() - 1, 0, width() - 1, height() - 1);
+ // p.drawLine(width() - 1, height() - 1, 0, height() - 1);
+ // break;
+ //}
+
+ p.setColour(Colour(0.3, alpha));
+ p.drawPoint(0, height() - 1);
+ p.drawPoint(width() - 1, 0);
}
-void GUI::Slider::mouseMoveEvent(MouseMoveEvent *e)
+void Slider::buttonEvent(ButtonEvent* buttonEvent)
{
- if(state == down) {
- val = maximum / (float)width() * (float)e->x;
-
- if(val < 0) val = 0;
- if(val > 1) val = 1;
-
- if(handler) handler(ptr);
- repaintEvent(NULL);
- }
+ if(buttonEvent->direction == Direction::down)
+ {
+ state = State::down;
+ currentValue = maximum / (float)width() * (float)buttonEvent->x;
+
+ if(currentValue < 0)
+ {
+ currentValue = 0;
+ }
+
+ if(currentValue > 1)
+ {
+ currentValue = 1;
+ }
+
+ repaintEvent(nullptr);
+ clickNotifier();
+ }
+
+ if(buttonEvent->direction == Direction::up)
+ {
+ state = State::up;
+ currentValue = maximum / (float)width() * (float)buttonEvent->x;
+
+ if(currentValue < 0)
+ {
+ currentValue = 0;
+ }
+
+ if(currentValue > 1)
+ {
+ currentValue = 1;
+ }
+
+ repaintEvent(nullptr);
+ clickNotifier();
+ }
}
-void GUI::Slider::buttonEvent(ButtonEvent *e)
+void Slider::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent)
{
- if(e->direction == 1) {
- state = down;
- val = maximum / (float)width() * (float)e->x;
-
- if(val < 0) val = 0;
- if(val > 1) val = 1;
-
- if(handler) handler(ptr);
- repaintEvent(NULL);
- }
- if(e->direction == -1) {
- state = up;
- val = maximum / (float)width() * (float)e->x;
-
- if(val < 0) val = 0;
- if(val > 1) val = 1;
-
- repaintEvent(NULL);
- clicked();
- if(handler) handler(ptr);
- }
+ if(state == State::down)
+ {
+ currentValue = maximum / (float)width() * (float)mouseMoveEvent->x;
+
+ if(currentValue < 0)
+ {
+ currentValue = 0;
+ }
+
+ if(currentValue > 1)
+ {
+ currentValue = 1;
+ }
+
+ repaintEvent(nullptr);
+ clickNotifier();
+ }
}
-void GUI::Slider::repaintEvent(GUI::RepaintEvent *e)
-{
- //DEBUG(slider, "Slider::repaintEvent (%f)\n", val);
-
- Painter p(this);
-
- float alpha = 0.8;
-
- int xpos = (int)((val / maximum) * (float)(width() - 1));
-
- if(hasKeyboardFocus()) {
- p.setColour(Colour(0.6, alpha));
- } else {
- p.setColour(Colour(0.5, alpha));
- }
- p.drawFilledRectangle(0,0,width(),height());
- /*
- p.setColour(Colour(0.1, alpha));
- p.drawRectangle(0,0,width()-1,height()-1);
- */
- p.setColour(Colour(1, 0, 0, alpha));
- p.drawLine(xpos, 0, xpos, height()-1);
- /*
- p.setColour(Colour(0.8, alpha));
- switch(state) {
- case up:
- p.drawLine(0,0,0,height()-1);
- p.drawLine(0,0,width()-1,0);
- break;
- case down:
- p.drawLine(width()-1,0, width()-1,height()-1);
- p.drawLine(width()-1,height()-1,0, height()-1);
- break;
- }
- */
- p.setColour(Colour(0.3, alpha));
- p.drawPoint(0,height()-1);
- p.drawPoint(width()-1,0);
-}
-
-#ifdef TEST_SLIDER
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif/*TEST_SLIDER*/
+} // GUI::
diff --git a/plugingui/slider.h b/plugingui/slider.h
index f07ccff..01cbd54 100644
--- a/plugingui/slider.h
+++ b/plugingui/slider.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_SLIDER_H__
-#define __DRUMGIZMO_SLIDER_H__
+#pragma once
#include "widget.h"
@@ -33,38 +32,32 @@ namespace GUI {
class Slider : public Widget {
public:
- Slider(Widget *parent);
+ Slider(Widget* parent);
- bool catchMouse() { return true; }
+ // From Widget:
+ bool catchMouse() override { return true; }
- void setValue(float value);
- float value();
+ void setValue(float value);
+ float value();
- void registerClickHandler(void (*handler)(void *), void *ptr);
+ Notifier<> clickNotifier;
- //protected:
- virtual void clicked() {}
-
- virtual void repaintEvent(RepaintEvent *e);
- virtual void buttonEvent(ButtonEvent *e);
- virtual void mouseMoveEvent(MouseMoveEvent *e);
+protected:
+ virtual void repaintEvent(RepaintEvent* repaintEvent) override;
+ virtual void buttonEvent(ButtonEvent* buttonEvent) override;
+ virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override;
private:
- typedef enum {
- up,
- down
- } state_t;
-
- float val;
- float maximum;
- float minimum;
+ enum class State {
+ up,
+ down
+ };
- state_t state;
-
- void (*handler)(void *);
- void *ptr;
-};
+ float currentValue;
+ float maximum;
+ float minimum;
+ State state;
};
-#endif/*__DRUMGIZMO_SLIDER_H__*/
+} // GUI::
diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc
new file mode 100644
index 0000000..7b1bfec
--- /dev/null
+++ b/plugingui/testmain.cc
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * testmain.cc
+ *
+ * Sun Nov 22 20:06:42 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 "plugingui.h"
+
+#include <hugin.hpp>
+
+// Dummy Engine class.
+class Engine : public MessageHandler {
+public:
+ void handleMessage(Message *msg) {}
+};
+
+class TestMain : public GUI::Listener {
+public:
+ TestMain()
+ {
+ CONNECT(&gui, closeNotifier, this, &TestMain::stop);
+ }
+
+ void stop()
+ {
+ DEBUG(stop, "Stopping...\n");
+ running = false;
+ }
+
+ void run()
+ {
+ while(running)
+ {
+#ifdef WIN32
+ SleepEx(1000, FALSE);
+#else
+ sleep(1);
+#endif
+ }
+ }
+
+ bool running = true;
+
+ GUI::PluginGUI gui;
+};
+
+int main()
+{
+ INFO(example, "We are up and running");
+
+ TestMain testMain;
+ testMain.run();
+
+ return 0;
+}
diff --git a/plugingui/textedit.cc b/plugingui/textedit.cc
new file mode 100644
index 0000000..7342421
--- /dev/null
+++ b/plugingui/textedit.cc
@@ -0,0 +1,214 @@
+/* -*- 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 "textedit.h"
+
+#include "window.h"
+
+#include <assert.h>
+#include <list>
+#include <hugin.hpp>
+#include <stdio.h>
+
+#define BORDER 10
+
+namespace GUI {
+
+TextEdit::TextEdit(Widget *parent)
+ : Widget(parent)
+ , scroll(this)
+{
+ setReadOnly(true);
+
+ scroll.move(width() - 5, 1);
+ scroll.resize(20, 100);
+ CONNECT(&scroll, valueChangeNotifier, this, &TextEdit::scrolled);
+
+ box.topLeft = new Image(":widget_tl.png");
+ box.top = new Image(":widget_t.png");
+ box.topRight = new Image(":widget_tr.png");
+ box.left = new Image(":widget_l.png");
+ box.right = new Image(":widget_r.png");
+ box.bottomLeft = new Image(":widget_bl.png");
+ box.bottom = new Image(":widget_b.png");
+ box.bottomRight = new Image(":widget_br.png");
+ box.center = new Image(":widget_c.png");
+}
+
+TextEdit::~TextEdit()
+{
+ delete box.topLeft;
+ delete box.top;
+ delete box.topRight;
+ delete box.left;
+ delete box.right;
+ delete box.bottomLeft;
+ delete box.bottom;
+ delete box.bottomRight;
+ delete box.center;
+}
+
+void TextEdit::resize(int height, int width)
+{
+ Widget::resize(height, width);
+ scroll.resize(scroll.width(), height-10);
+ scroll.move(width-30,7);
+}
+
+void TextEdit::setReadOnly(bool readonly)
+{
+ this->readonly = readonly;
+}
+
+bool TextEdit::readOnly()
+{
+ return readonly;
+}
+
+void TextEdit::setText(const std::string& text)
+{
+ _text = text;
+
+ preprocessText();
+
+ int ran = height() / font.textHeight();
+
+ DEBUG(textedit, "Setting range and max of scrollbar to '%d' and '%d'\n",
+ ran, (int)preprocessedtext.size());
+
+ scroll.setRange(ran);
+ scroll.setMaximum(preprocessedtext.size());
+
+ repaintEvent(nullptr);
+
+ textChangedNotifier();
+}
+
+std::string TextEdit::text()
+{
+ return _text;
+}
+
+void TextEdit::preprocessText()
+{
+ preprocessedtext.clear();
+ std::string text = _text;
+
+ { // Handle tab characters
+ for(size_t i = 0; i < text.length(); ++i)
+ {
+ char ch = text.at(i);
+ if(ch == '\t')
+ {
+ text.erase(i, 1);
+ text.insert(i, 4, ' ');
+ }
+ }
+ }
+
+ std::list<std::string> lines;
+ { // Handle new line characters
+ 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
+ std::list<std::string>::iterator it;
+ for(it = lines.begin(); it != lines.end(); ++it)
+ {
+ std::string line = *it;
+
+ for(size_t i = 0; i < line.length(); ++i)
+ {
+ size_t linewidth = font.textWidth(line.substr(0, i));
+ if(linewidth >= width() - BORDER - 4 + 3 - 10 - scroll.width()) {
+ preprocessedtext.push_back(line.substr(0, i));
+ line = line.substr(i);
+ i = 0;
+ }
+ }
+ preprocessedtext.push_back(line);
+ }
+ }
+}
+
+void TextEdit::repaintEvent(RepaintEvent* repaintEvent)
+{
+ Painter p(*this);
+
+ p.clear();
+
+ int w = width();
+ int h = height();
+ if((w == 0) || (h == 0))
+ {
+ return;
+ }
+
+ p.drawBox(0, 0, box, w, h);
+
+ p.setColour(Colour(183.0 / 255.0, 219.0 / 255.0 , 255.0 / 255.0, 1));
+
+ int skip = scroll.value();
+
+ int ypos = font.textHeight() + 5 + 1 + 1 + 1;
+ std::list<std::string>::iterator it;
+ it = preprocessedtext.begin();
+
+ int c = 0;
+ for( ; c < skip; c++)
+ {
+ ++it;
+ }
+
+ c = 0;
+ for( ; it != preprocessedtext.end(); it++)
+ {
+ if((c * font.textHeight()) >= (height() - 8 - font.textHeight()))
+ {
+ break;
+ }
+
+ std::string line = *it;
+ p.drawText(BORDER - 4 + 3, ypos, font, line);
+ ypos += font.textHeight();
+ ++c;
+ }
+}
+
+void TextEdit::scrolled(int value)
+{
+ (void)value;
+ repaintEvent(nullptr);
+}
+
+} // GUI::
diff --git a/plugingui/textedit.h b/plugingui/textedit.h
new file mode 100644
index 0000000..d1b4a01
--- /dev/null
+++ b/plugingui/textedit.h
@@ -0,0 +1,79 @@
+/* -*- 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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.
+ */
+#pragma once
+
+#include <string>
+#include <list>
+
+#include "widget.h"
+#include "font.h"
+#include "painter.h"
+#include "scrollbar.h"
+
+#include "notifier.h"
+
+namespace GUI {
+
+class TextEdit : public Widget {
+public:
+ TextEdit(Widget *parent);
+ ~TextEdit();
+
+ // From Widget
+ bool isFocusable() override { return true; }
+ void resize(int width, int height) override;
+
+ std::string text();
+ 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;
+
+private:
+ void scrolled(int value);
+
+ Painter::Box box;
+ ScrollBar scroll;
+ Font font;
+
+ std::string _text;
+ size_t pos{0};
+
+ bool readonly{true};
+
+ std::list< std::string > preprocessedtext;
+};
+
+} // GUI::
diff --git a/plugingui/verticalline.cc b/plugingui/verticalline.cc
index 53d82a6..5bf4afd 100644
--- a/plugingui/verticalline.cc
+++ b/plugingui/verticalline.cc
@@ -28,14 +28,24 @@
#include "painter.h"
-GUI::VerticalLine::VerticalLine(GUI::Widget *parent)
- : Widget(parent), vline(":vertline.png")
+namespace GUI {
+
+VerticalLine::VerticalLine(Widget *parent)
+ : Widget(parent)
+ , vline(":vertline.png")
{
}
-void GUI::VerticalLine::repaintEvent(RepaintEvent *e)
+void VerticalLine::repaintEvent(RepaintEvent* repaintEvent)
{
- (void)e;
- GUI::Painter p(this);
- p.drawImageStretched(0, 0, &vline, width(), height());
+ 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
index 7c1bc27..1d05eac 100644
--- a/plugingui/verticalline.h
+++ b/plugingui/verticalline.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_VERTICALLINE_H__
-#define __DRUMGIZMO_VERTICALLINE_H__
+#pragma once
#include "widget.h"
#include "image.h"
@@ -34,15 +33,14 @@ namespace GUI {
class VerticalLine : public Widget {
public:
- VerticalLine(Widget *parent);
+ VerticalLine(Widget* parent);
- //protected:
- virtual void repaintEvent(RepaintEvent *e);
+protected:
+ // From Widget:
+ virtual void repaintEvent(RepaintEvent* repaintEvent) override;
private:
- Image vline;
+ Image vline;
};
-};
-
-#endif/*__DRUMGIZMO_VERTICALLINE_H__*/
+} // GUI::
diff --git a/plugingui/widget.cc b/plugingui/widget.cc
index b3e3cc8..5c8ff46 100644
--- a/plugingui/widget.cc
+++ b/plugingui/widget.cc
@@ -31,188 +31,191 @@
#include <stdio.h>
-GUI::Widget::Widget(Widget *parent)
- : pixbuf(1, 1)
+namespace GUI {
+
+Widget::Widget(Widget* parent)
+ : parent(parent)
{
- _width = _height = 10;
+ if(parent)
+ {
+ parent->addChild(this);
+ _window = parent->window();
+ }
- this->parent = parent;
- if(parent) {
- parent->addChild(this);
- _window = parent->window();
- }
- _width = _height = 0;
- _visible = true;
+ _width = _height = 0;
+ _visible = true;
}
-GUI::Widget::~Widget()
+Widget::~Widget()
{
- if(parent) parent->removeChild(this);
+ if(parent)
+ {
+ parent->removeChild(this);
+ }
}
-void GUI::Widget::show()
+void Widget::show()
{
- setVisible(true);
+ setVisible(true);
}
-void GUI::Widget::hide()
+void Widget::hide()
{
- setVisible(false);
+ setVisible(false);
}
-void GUI::Widget::setVisible(bool v)
+void Widget::setVisible(bool visible)
{
- _visible = v;
- repaintEvent(NULL);
+ _visible = visible;
+ repaintEvent(nullptr);
}
-bool GUI::Widget::visible()
+bool Widget::visible()
{
- return _visible;
+ return _visible;
}
-void GUI::Widget::addChild(GUI::Widget *widget)
+void Widget::addChild(Widget* widget)
{
- children.push_back(widget);
+ children.push_back(widget);
}
-void GUI::Widget::removeChild(GUI::Widget *widget)
+void Widget::removeChild(Widget* widget)
{
- std::vector<Widget *>::iterator i = children.begin();
- while(i != children.end()) {
- if(*i == widget) {
- children.erase(i);
- return;
- }
- i++;
- }
+ for(auto i = children.begin(); i != children.end(); ++i)
+ {
+ if(*i == widget)
+ {
+ children.erase(i);
+ return;
+ }
+ }
}
-void GUI::Widget::resize(int width, int height)
+void Widget::resize(int width, int height)
{
- if(width < 1 || height < 1) return;
- _width = width;
- _height = height;
- pixbuf.realloc(width, height);
+ if((width < 1) || (height < 1) ||
+ (((size_t)width == _width) && ((size_t)height == _height)))
+ {
+ return;
+ }
+
+ _width = width;
+ _height = height;
+ pixbuf.realloc(width, height);
+
+ sizeChangeNotifier(width, height);
}
-void GUI::Widget::move(size_t x, size_t y)
+void Widget::move(size_t x, size_t y)
{
- _x = x;
- _y = y;
+ _x = x;
+ _y = y;
}
-size_t GUI::Widget::x() { return _x; }
-size_t GUI::Widget::y() { return _y; }
-size_t GUI::Widget::width() { return _width; }
-size_t GUI::Widget::height() { return _height; }
-
-size_t GUI::Widget::windowX()
+int Widget::x()
{
- size_t window_x = x();
- if(parent) window_x += parent->windowX();
- return window_x;
+ return _x;
}
-size_t GUI::Widget::windowY()
+int Widget::y()
{
- size_t window_y = y();
- if(parent) window_y += parent->windowY();
- return window_y;
+ return _y;
}
-GUI::Widget *GUI::Widget::find(size_t x, size_t y)
+size_t Widget::width()
{
- std::vector<Widget*>::reverse_iterator i = children.rbegin();
- while(i != children.rend()) {
- Widget *w = *i;
- if(w->visible()) {
- if(w->x() <= x && (w->x() + w->width()) >= x &&
- w->y() <= y && w->y() + w->height() >= y)
- return w->find(x - w->x(), y - w->y());
- }
- i++;
- }
-
- if(x > width() /*|| x < 0*/ || y > height() /*|| y < 0*/) return NULL;
- return this;
+ return _width;
}
-GUI::Window *GUI::Widget::window()
+size_t Widget::height()
{
- return _window;
+ return _height;
}
-void GUI::Widget::repaint_r(GUI::RepaintEvent *e)
+size_t Widget::windowX()
{
- Painter p(this); // make sure pixbuf refcount is incremented.
+ size_t window_x = x();
- repaintEvent(e);
+ if(parent)
+ {
+ window_x += parent->windowX();
+ }
- std::vector<Widget*>::iterator i = children.begin();
- while(i != children.end()) {
- Widget *w = *i;
- w->repaint_r(e);
- i++;
- }
+ return window_x;
}
-std::vector<GUI::PixelBufferAlpha *> GUI::Widget::getPixelBuffers()
+size_t Widget::windowY()
{
- std::vector<PixelBufferAlpha *> pbs;
-
- pixbuf.x = windowX();
- pixbuf.y = windowY();
+ size_t window_y = y();
+ if(parent)
+ {
+ window_y += parent->windowY();
+ }
- pbs.push_back(&pixbuf);
+ return window_y;
+}
- std::vector<Widget*>::iterator i = children.begin();
- while(i != children.end()) {
- Widget *w = *i;
- if(w->visible()) {
- std::vector<PixelBufferAlpha *> pbs0 = w->getPixelBuffers();
- pbs.insert(pbs.end(), pbs0.begin(), pbs0.end());
- }
- i++;
- }
+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 pbs;
+ return this;
}
-bool GUI::Widget::hasKeyboardFocus()
+Window* Widget::window()
{
- return window()->keyboardFocus() == this;
+ return _window;
}
-#ifdef TEST_WIDGET
-//deps: window.cc globalcontext.cc
-//cflags:
-//libs:
-#include "test.h"
+std::vector<PixelBufferAlpha*> Widget::getPixelBuffers()
+{
+ std::vector<PixelBufferAlpha*> pixelBuffers;
-#include "window.h"
+ pixbuf.x = windowX();
+ pixbuf.y = windowY();
-TEST_BEGIN;
+ pixelBuffers.push_back(&pixbuf);
-GUI::Window w1(NULL);
-w1.move(0,0);
-w1.resize(100, 100);
+ for(auto child : children)
+ {
+ if(child->visible())
+ {
+ auto childPixelBuffers = child->getPixelBuffers();
+ pixelBuffers.insert(pixelBuffers.end(),
+ childPixelBuffers.begin(), childPixelBuffers.end());
+ }
+ }
+
+ return pixelBuffers;
+}
-GUI::Widget w2(&w1);
-w2.resize(40,40);
-w2.move(10,10);
+bool Widget::hasKeyboardFocus()
+{
+ return window()->keyboardFocus() == this;
+}
-GUI::Widget w3(&w2);
-w3.resize(20,20);
-w3.move(10,10);
+void Widget::repaintChildren(RepaintEvent* repaintEvent)
+{
+ Painter p(*this); // make sure pixbuf refcount is incremented.
-TEST_EQUAL_PTR(w1.find(101,0), NULL, "Miss?");
-TEST_EQUAL_PTR(w1.find(0,0), &w1, "Hit w1?");
-TEST_EQUAL_PTR(w1.find(100,100), &w1, "Hit w1?");
-TEST_EQUAL_PTR(w1.find(0,0), &w1, "Hit w1?");
-TEST_EQUAL_PTR(w1.find(11,11), &w2, "Hit w2?");
-TEST_EQUAL_PTR(w1.find(22,22), &w3, "Hit w3?");
+ this->repaintEvent(repaintEvent);
-TEST_END;
+ for(auto child : children)
+ {
+ child->repaintChildren(repaintEvent);
+ }
+}
-#endif/*TEST_WIDGET*/
+} // GUI::
diff --git a/plugingui/widget.h b/plugingui/widget.h
index 47c374e..6bfffb5 100644
--- a/plugingui/widget.h
+++ b/plugingui/widget.h
@@ -24,11 +24,12 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_WIDGET_H__
-#define __DRUMGIZMO_WIDGET_H__
+#pragma once
#include "guievent.h"
#include "pixelbuffer.h"
+#include "notifier.h"
+#include "layout.h"
#include <vector>
@@ -36,64 +37,69 @@ namespace GUI {
class Window;
-class Widget {
+class Widget : public Listener, public LayoutItem {
+ friend class Painter;
public:
- Widget(Widget *parent);
- virtual ~Widget();
+ Widget(Widget* parent);
+ virtual ~Widget();
- virtual void show();
- virtual void hide();
+ virtual void show();
+ virtual void hide();
- virtual void resize(int width, int height);
- virtual void move(size_t x, size_t y);
+ // From LayoutItem
+ virtual void resize(int width, int height) override;
+ virtual void move(size_t x, size_t y) override;
+ virtual int x() override;
+ virtual int y() override;
+ virtual size_t width() override;
+ virtual size_t height() override;
- virtual size_t x();
- virtual size_t y();
- virtual size_t windowX();
- virtual size_t windowY();
- virtual size_t width();
- virtual size_t height();
+ virtual size_t windowX();
+ virtual size_t windowY();
- virtual bool isFocusable() { return false; }
- virtual bool catchMouse() { return false; }
+ virtual bool isFocusable() { return false; }
+ virtual bool catchMouse() { return false; }
- void addChild(Widget *widget);
- void removeChild(Widget *widget);
+ void addChild(Widget* widget);
+ void removeChild(Widget* widget);
- virtual void repaintEvent(RepaintEvent *e) {}
- virtual void mouseMoveEvent(MouseMoveEvent *e) {}
- virtual void buttonEvent(ButtonEvent *e) {}
- virtual void scrollEvent(ScrollEvent *e) {}
- virtual void keyEvent(KeyEvent *e) {}
+ 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 void mouseLeaveEvent() {}
- virtual void mouseEnterEvent() {}
+ Widget* find(int x, int y);
- Widget *find(size_t x, size_t y);
+ virtual Window* window();
- virtual Window *window();
+ std::vector<PixelBufferAlpha*> getPixelBuffers();
- void repaint_r(RepaintEvent *e);
+ bool hasKeyboardFocus();
- PixelBufferAlpha pixbuf;
- std::vector<PixelBufferAlpha *> getPixelBuffers();
+ bool visible();
+ void setVisible(bool visible);
- bool hasKeyboardFocus();
+ Notifier<int, int> sizeChangeNotifier; // (int, width, int height)
- Widget *parent;
+protected:
+ void repaintChildren(RepaintEvent* repaintEvent);
- bool visible();
- void setVisible(bool visible);
+ PixelBufferAlpha pixbuf{0,0};
-protected:
- std::vector<Widget*> children;
- Window *_window;
- size_t _x, _y, _width, _height;
+ std::vector<Widget*> children;
-private:
- bool _visible;
-};
+ Widget* parent = nullptr;
+ Window* _window = nullptr;
+
+ int _x{0};
+ int _y{0};
+ size_t _width{0};
+ size_t _height{0};
+ bool _visible = true;
};
-#endif/*__DRUMGIZMO_WIDGET_H__*/
+} // GUI::
diff --git a/plugingui/window.cc b/plugingui/window.cc
index 8337533..9263128 100644
--- a/plugingui/window.cc
+++ b/plugingui/window.cc
@@ -26,13 +26,8 @@
*/
#include "window.h"
-#include "painter.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <string.h>
#include <hugin.hpp>
+#include "painter.h"
#ifndef PUGL
#ifdef X11
@@ -45,201 +40,230 @@
#include "nativewindow_pugl.h"
#endif
-GUI::Window::Window()
- : Widget(NULL), wpixbuf(100, 100), back(":bg.png"), logo(":logo.png")
-{
- _x = _y = 100;
- _width = wpixbuf.width;
- _height = wpixbuf.height;
+namespace GUI {
- refcount = 0;
- max_refcount = 0;
- _keyboardFocus = this;
- _buttonDownFocus = NULL;
- _mouseFocus = NULL;
+Window::Window()
+ : Widget(nullptr)
+ , wpixbuf(100, 100)
+{
+ // Make sure we have a valid size when initialising the NativeWindow
+ _width = wpixbuf.width;
+ _height = wpixbuf.height;
#ifndef PUGL
#ifdef X11
- native = new NativeWindowX11(this);
+ native = new NativeWindowX11(*this);
#endif/*X11*/
#ifdef WIN32
- native = new NativeWindowWin32(this);
+ native = new NativeWindowWin32(*this);
#endif/*WIN32*/
#else/*Use pugl*/
- native = new NativeWindowPugl(this);
+ native = new NativeWindowPugl(this);
#endif
- eventhandler = new GUI::EventHandler(native, this);
+ eventhandler = new EventHandler(*native, *this);
}
-GUI::Window::~Window()
+Window::~Window()
{
- delete native;
- delete eventhandler;
+ delete native;
+ delete eventhandler;
}
-GUI::EventHandler *GUI::Window::eventHandler()
+void Window::setFixedSize(int w, int h)
{
- return eventhandler;
+ native->setFixedSize(w, h);
+ resize(w,h);
}
-void GUI::Window::setCaption(std::string caption)
+void Window::setCaption(const std::string& caption)
{
- native->setCaption(caption);
+ native->setCaption(caption);
}
-void GUI::Window::repaintEvent(GUI::RepaintEvent *e)
+void Window::resize(int width, int height)
{
- if(!visible()) return;
-
- Painter p(this);
- p.drawImageStretched(0,0, &back, width(), height());
- p.drawImage(width() - logo.width(),
- height() - logo.height(), &logo);
+ if((width < 1) || (height < 1))
+ {
+ return;
+ }
+
+ resized(width, height);
+ Widget::resize(width, height);
+ native->resize(width, height);
}
-void GUI::Window::setFixedSize(int w, int h)
+void Window::move(size_t x, size_t y)
{
- native->setFixedSize(w, h);
- resize(w,h);
+ native->move(x, y);
+
+ // Make sure widget corrdinates are updated.
+ Widget::move(x, y);
}
-void GUI::Window::resize(int width, int height)
+size_t Window::windowX()
{
- if(width < 1 || height < 1) return;
-
- // This needs to be done on all platoforms when setFixedSize is introduced.
- //#ifdef WIN32
- // Fix to force buffer size reallocation
- // FIXME: This should've been done indirectly through a WM_SIZE message in the
- // EventHandler...
- resized(width, height);
- //#endif
-
- Widget::resize(width, height);
- native->resize(width, height);
+ return 0;
}
-void GUI::Window::move(size_t x, size_t y)
+size_t Window::windowY()
{
- native->move(x, y);
-
- // Make sure widget corrds are updated.
- Widget::move(x, y);
+ return 0;
}
-size_t GUI::Window::x() { return _x; }
-size_t GUI::Window::y() { return _y; }
-size_t GUI::Window::width() { return _width; }
-size_t GUI::Window::height() { return _height; }
-size_t GUI::Window::windowX() { return 0; }
-size_t GUI::Window::windowY() { return 0; }
-
-void GUI::Window::show()
+void Window::show()
{
- repaint_r(NULL);
- native->show();
+ repaintChildren(nullptr);
+ native->show();
}
-void GUI::Window::hide()
+void Window::hide()
{
- native->hide();
+ native->hide();
}
-GUI::Window *GUI::Window::window()
+Window* Window::window()
{
- return this;
+ return this;
}
-void GUI::Window::beginPaint()
+EventHandler* Window::eventHandler()
{
- refcount++;
- if(refcount > max_refcount) max_refcount = refcount;
+ return eventhandler;
}
-void GUI::Window::endPaint()
+Widget* Window::keyboardFocus()
{
- if(refcount) refcount--;
-
- if(!refcount) {
- if(max_refcount > 1) { // Did we go deep enough for a buffer update?
- updateBuffer();
- redraw();
- }
- max_refcount = 0;
- }
+ return _keyboardFocus;
}
-void GUI::Window::updateBuffer()
+void Window::setKeyboardFocus(Widget* widget)
{
- DEBUG(window, "Updating buffer\n");
- memset(wpixbuf.buf, 0, wpixbuf.width * wpixbuf.height * 3);
-
- std::vector<PixelBufferAlpha *> pl = getPixelBuffers();
- std::vector<PixelBufferAlpha *>::iterator pli = pl.begin();
- while(pli != pl.end()) {
- PixelBufferAlpha *pb = *pli;
- for(size_t x = 0; x < pb->width; x++) {
- for(size_t y = 0; y < pb->height; y++) {
- unsigned char r,g,b,a;
- pb->pixel(x,y,&r,&g,&b,&a);
- wpixbuf.setPixel(x + pb->x, y + pb->y, r, g, b, a);
- }
- }
- pli++;
- }
- native->handleBuffer();
+ auto oldFocusWidget = _keyboardFocus;
+ _keyboardFocus = widget;
+
+ if(oldFocusWidget)
+ {
+ oldFocusWidget->repaintEvent(nullptr);
+ }
+
+ if(_keyboardFocus)
+ {
+ _keyboardFocus->repaintEvent(nullptr);
+ }
}
-void GUI::Window::resized(size_t w, size_t h)
+Widget* Window::buttonDownFocus()
{
- if(_width == w && _height == h) return;
-
- _width = w;
- _height = h;
- wpixbuf.realloc(w, h);
- updateBuffer();
-
- pixbuf.realloc(w, h);
- repaintEvent(NULL);
+ return _buttonDownFocus;
}
-void GUI::Window::redraw()
+void Window::setButtonDownFocus(Widget* widget)
{
- native->redraw();
+ _buttonDownFocus = widget;
+ native->grabMouse(widget != nullptr);
}
-GUI::Widget *GUI::Window::keyboardFocus()
+Widget* Window::mouseFocus()
{
- return _keyboardFocus;
+ return _mouseFocus;
}
-void GUI::Window::setKeyboardFocus(GUI::Widget *widget)
+void Window::setMouseFocus(Widget* widget)
{
- GUI::Widget *old_focus = _keyboardFocus;
- _keyboardFocus = widget;
+ _mouseFocus = widget;
+
+}
- if(old_focus) old_focus->repaintEvent(NULL);
- if(_keyboardFocus) _keyboardFocus->repaintEvent(NULL);
+void Window::redraw()
+{
+ native->redraw();
}
-GUI::Widget *GUI::Window::buttonDownFocus()
+void Window::resized(size_t width, size_t height)
{
- return _buttonDownFocus;
+ if((_width == width) && (_height == height))
+ {
+ return;
+ }
+
+ _width = width;
+ _height = height;
+
+ wpixbuf.realloc(width, height);
+ updateBuffer();
+
+ pixbuf.realloc(width, height);
+ repaintEvent(nullptr);
+
+ // Notify Widget
+ sizeChangeNotifier(width, height);
}
-void GUI::Window::setButtonDownFocus(GUI::Widget *widget)
+void Window::updateBuffer()
{
- _buttonDownFocus = widget;
- native->grabMouse(widget != NULL);
+ //DEBUG(window, "Updating buffer\n");
+ for(auto pixelBuffer : getPixelBuffers())
+ {
+ size_t updateWidth = pixelBuffer->width;
+ size_t updateHeight = pixelBuffer->height;
+
+ // Skip buffer if not inside window.
+ if((wpixbuf.width < pixelBuffer->x) || (wpixbuf.height < pixelBuffer->y))
+ {
+ continue;
+ }
+
+ if(updateWidth > (wpixbuf.width - pixelBuffer->x))
+ {
+ updateWidth = (wpixbuf.width - pixelBuffer->x);
+ }
+
+ if(updateHeight > (wpixbuf.height - pixelBuffer->y))
+ {
+ updateHeight = (wpixbuf.height - pixelBuffer->y);
+ }
+
+ unsigned char r,g,b,a;
+ for(size_t y = 0; y < updateHeight; y++)
+ {
+ for(size_t x = 0; x < updateWidth; x++)
+ {
+ pixelBuffer->pixel(x, y, &r, &g, &b, &a);
+ wpixbuf.setPixel(x + pixelBuffer->x, y + pixelBuffer->y, r, g, b, a);
+ }
+ }
+ }
+
+ native->handleBuffer();
}
-GUI::Widget *GUI::Window::mouseFocus()
+void Window::beginPaint()
{
- return _mouseFocus;
+ ++refcount;
+ if(refcount > maxRefcount)
+ {
+ maxRefcount = refcount;
+ }
}
-void GUI::Window::setMouseFocus(GUI::Widget *widget)
+void Window::endPaint()
{
- _mouseFocus = widget;
+ if(refcount)
+ {
+ --refcount;
+ }
+
+ if(!refcount)
+ {
+ // Did we go deep enough for a buffer update?
+ if(maxRefcount > 1)
+ {
+ updateBuffer();
+ redraw();
+ }
+ maxRefcount = 0;
+ }
}
+
+} // GUI::
diff --git a/plugingui/window.h b/plugingui/window.h
index f8deef0..1fffbb6 100644
--- a/plugingui/window.h
+++ b/plugingui/window.h
@@ -24,8 +24,7 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __DRUMGIZMO_WINDOW_H__
-#define __DRUMGIZMO_WINDOW_H__
+#pragma once
#include "widget.h"
@@ -38,68 +37,60 @@ namespace GUI {
class Window : public Widget {
public:
- Window();
- ~Window();
+ Window();
+ ~Window();
- void show();
- void hide();
+ void setFixedSize(int width, int height);
+ void setCaption(const std::string& caption);
- void setFixedSize(int width, int height);
- void resize(int width, int height);
- void move(size_t x, size_t y);
+ // From Widget:
+ void resize(int width, int height) override;
+ void move(size_t x, size_t y) override;
+ size_t windowX() override;
+ size_t windowY() override;
+ void show() override;
+ void hide() override;
+ Window* window() override;
- size_t x();
- size_t y();
- size_t windowX();
- size_t windowY();
- size_t width();
- size_t height();
+ EventHandler* eventHandler();
- void setCaption(std::string caption);
+ Widget* keyboardFocus();
+ void setKeyboardFocus(Widget* widget);
- void addChild(Widget *widget);
+ Widget* buttonDownFocus();
+ void setButtonDownFocus(Widget* widget);
- void repaintEvent(GUI::RepaintEvent *e);
-
- void beginPaint();
- void endPaint();
-
- Window *window();
-
- EventHandler *eventHandler();
-
- // handlers
- virtual void redraw();
- void resized(size_t w, size_t h);
-
- Widget *keyboardFocus();
- void setKeyboardFocus(Widget *widget);
-
- Widget *buttonDownFocus();
- void setButtonDownFocus(Widget *widget);
-
- Widget *mouseFocus();
- void setMouseFocus(Widget *widget);
-
- PixelBuffer wpixbuf;
- void updateBuffer();
+ Widget* mouseFocus();
+ void setMouseFocus(Widget* widget);
protected:
- size_t refcount;
+ // For the EventHandler
+ friend class EventHandler;
+ void redraw();
+ void resized(size_t w, size_t h);
+ void updateBuffer();
- Widget *_keyboardFocus;
- Widget *_buttonDownFocus;
- Widget *_mouseFocus;
+ // For the Painter
+ friend class Painter;
+ void beginPaint();
+ void endPaint();
- NativeWindow *native;
- EventHandler *eventhandler;
+ // For the NativeWindow
+ friend class NativeWindowX11;
+ friend class NativeWindowWin32;
+ friend class NativeWindowPugl;
+ PixelBuffer wpixbuf;
- Image back;
- Image logo;
+ size_t refcount{0};
- size_t max_refcount;
-};
+ Widget* _keyboardFocus{nullptr};
+ Widget* _buttonDownFocus{nullptr};
+ Widget* _mouseFocus{nullptr};
+
+ NativeWindow* native{nullptr};
+ EventHandler* eventhandler{nullptr};
+ size_t maxRefcount{0};
};
-#endif/*__DRUMGIZMO_WINDOW_H__*/
+} // GUI::