diff options
78 files changed, 6030 insertions, 4767 deletions
diff --git a/configure.ac b/configure.ac index 7934cc2..5c8c155 100644 --- a/configure.ac +++ b/configure.ac @@ -124,6 +124,8 @@ AC_SUBST(GUI_CFLAGS) AC_SUBST(GUI_LIBS) AM_CONDITIONAL([ENABLE_PUGL], [test "x$enable_gui" = "xpugl"]) +AM_CONDITIONAL([ENABLE_WIN32], [test "x$enable_gui" = "xwin32"]) +AM_CONDITIONAL([ENABLE_X11], [test "x$enable_gui" = "xx11"]) dnl ====================== dnl Compile unit tests @@ -228,7 +230,7 @@ AS_IF( [AC_MSG_RESULT([*** input dummy plugin disabled per user request ***]) have_input_dummy=no] ) - + dnl *** Test AC_ARG_ENABLE([input_test], AS_HELP_STRING([--disable-input-test], [Disable input test plugin [default=enabled]]),, diff --git a/lv2/lv2_gui.cc b/lv2/lv2_gui.cc index 7b56c5b..858e097 100644 --- a/lv2/lv2_gui.cc +++ b/lv2/lv2_gui.cc @@ -114,7 +114,7 @@ struct DG_GUI { DrumGizmo *instance; LV2UI_Controller controller; - PluginGUI *gui; + GUI::PluginGUI *gui; struct lv2_external_ui_host *ui_host_ptr; }; @@ -190,7 +190,7 @@ static LV2UI_Handle ui_instantiate(const struct _LV2UI_Descriptor * descriptor, pt->virt.run = ui_run; pt->virt.show = ui_show; pt->virt.hide = ui_hide; - pt->gui = new PluginGUI(); + pt->gui = new GUI::PluginGUI(); pt->gui->setWindowClosedCallback(closeHandler, pt); *widget = (LV2UI_Widget)pt; diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index 00b0881..e93ffa0 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 \ @@ -57,5 +55,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..62ddd19 100644 --- a/plugingui/Makefile.am.plugingui +++ b/plugingui/Makefile.am.plugingui @@ -1,12 +1,6 @@ - -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/plugingui.cc \ $(top_srcdir)/plugingui/label.cc \ $(top_srcdir)/plugingui/eventhandler.cc \ @@ -22,6 +16,7 @@ PLUGIN_GUI_SOURCES = \ $(top_srcdir)/plugingui/checkbox.cc \ $(top_srcdir)/plugingui/slider.cc \ $(top_srcdir)/plugingui/scrollbar.cc \ + $(top_srcdir)/plugingui/layout.cc \ $(top_srcdir)/plugingui/listbox.cc \ $(top_srcdir)/plugingui/listboxthin.cc \ $(top_srcdir)/plugingui/listboxbasic.cc \ @@ -41,9 +36,23 @@ PLUGIN_GUI_LIBS = $(GUI_LIBS) $(PTHREAD_LIBS) $(ZLIB_LIBS) PLUGIN_GUI_CFLAGS = $(GUI_CFLAGS) $(ZLIB_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..98f2408 100644 --- a/plugingui/Makefile.mingw32 +++ b/plugingui/Makefile.mingw32 @@ -1,67 +1,59 @@ -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 = \ + 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 \ + 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/directory.cc b/plugingui/directory.cc index 1465c86..c7a17b2 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); + } + + + 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 828286c..bcaa027 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) -{ - points = 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 letterSpacing) { - 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 = letterSpacing; } -#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..72e0598 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,328 @@ 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; + } + else + { + delete buttonEvent; + break; // unknown direction + } + + 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..6330f86 100644 --- a/plugingui/nativewindow_x11.cc +++ b/plugingui/nativewindow_x11.cc @@ -26,105 +26,146 @@ */ #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); + 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 +176,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 NativeWindowX11::handleBuffer() +{ + if(buffer) + { + XDestroyImage(buffer); + } + + buffer = createImageFromBuffer(window.wpixbuf.buf, + window.wpixbuf.width, + window.wpixbuf.height); +} -void GUI::NativeWindowX11::handleBuffer() +void NativeWindowX11::redraw() { - if(buffer) XDestroyImage(buffer); - buffer = - create_image_from_buffer(display, DefaultScreen(display), - window->wpixbuf.buf, - window->wpixbuf.width, - window->wpixbuf.height); + 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 GUI::NativeWindowX11::redraw() +void NativeWindowX11::setCaption(const std::string &caption) { - // 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; + } + + 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..d7b3902 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; + GC gc; + XImage* buffer; - int last_click; + Window& window; - Display *display; - Atom wmDeleteMessage; -}; + int last_click; + Display* display; + int screen; + Atom wmDeleteMessage; }; -#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..a1c3f93 100644 --- a/plugingui/painter.cc +++ b/plugingui/painter.cc @@ -28,461 +28,493 @@ #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)) + { + 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..5de74fb 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -36,129 +36,7 @@ #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(); -} +namespace GUI { /* void closeClick(void *ptr) @@ -206,7 +84,7 @@ void PluginGUI::stopThread() void PluginGUI::handleMessage(Message *msg) { - GUI::Painter p(window);// Make sure we only redraw buffer one time. + Painter p(*window);// Make sure we only redraw buffer one time. switch(msg->type()) { case Message::LoadStatus: @@ -215,7 +93,7 @@ void PluginGUI::handleMessage(Message *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); + progress->setState(ProgressBarState::Green); } } break; @@ -224,9 +102,9 @@ void PluginGUI::handleMessage(Message *msg) LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; progress2->setProgress(1); if(ls->success) { - progress2->setState(GUI::ProgressBar::green); + progress2->setState(ProgressBarState::Green); } else { - progress2->setState(GUI::ProgressBar::red); + progress2->setState(ProgressBarState::Red); } } break; @@ -236,22 +114,22 @@ void PluginGUI::handleMessage(Message *msg) lineedit->setText(settings->drumkitfile); if(settings->drumkit_loaded) { progress->setProgress(1); - progress->setState(GUI::ProgressBar::green); + progress->setState(ProgressBarState::Green); } else { progress->setProgress(0); - progress->setState(GUI::ProgressBar::blue); + progress->setState(ProgressBarState::Blue); } lineedit2->setText(settings->midimapfile); if(settings->midimap_loaded) { progress2->setProgress(1); - progress2->setState(GUI::ProgressBar::green); + progress2->setState(ProgressBarState::Green); } else { progress2->setProgress(0); - progress2->setState(GUI::ProgressBar::blue); + progress2->setState(ProgressBarState::Blue); } - check->setChecked(settings->enable_velocity_modifier); - knob->setValue(settings->velocity_modifier_weight); - knob2->setValue(settings->velocity_modifier_falloff); + velocityCheck->setChecked(settings->enable_velocity_modifier); + attackKnob->setValue(settings->velocity_modifier_weight); + falloffKnob->setValue(settings->velocity_modifier_falloff); } default: @@ -279,6 +157,13 @@ void PluginGUI::thread_main() window->eventHandler()->processEvents(); handleMessages(); + +#ifdef STANDALONE + if(closing) { + if(windowClosedHandler) windowClosedHandler(windowClosedPtr); + break; + } +#endif } deinit(); @@ -293,10 +178,50 @@ void PluginGUI::deinit() if(window) delete window; } -void closeEventHandler(void *ptr) +void PluginGUI::closeEventHandler() { - volatile bool *closing = (volatile bool*)ptr; - *closing = true; + closing = true; +} + +void PluginGUI::selectKitFile(const std::string& filename) +{ + lineedit->setText(filename); + + fileBrowser->hide(); + + std::string drumkit = lineedit->text(); + + config->lastkit = drumkit; + config->save(); + + progress->setProgress(0); + progress->setState(ProgressBarState::Blue); + + LoadDrumKitMessage *msg = new LoadDrumKitMessage(); + msg->drumkitfile = drumkit; + + msghandler.sendMessage(MSGRCV_ENGINE, msg); +} + +void PluginGUI::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; + msghandler.sendMessage(MSGRCV_ENGINE, msg); + + /* + if(gui->changeMidimapHandler) + gui->changeMidimapHandler(gui->changeMidimapPtr, midimap.c_str()); + gui->progress2->setState(ProgressBarState::Green); + */ } void PluginGUI::init() @@ -306,19 +231,19 @@ void PluginGUI::init() config = new Config(); config->load(); - window = new GUI::Window(); - window->eventHandler()->registerCloseHandler(closeEventHandler, - (void*)&closing); + window = new Window(); + auto eventHandler = window->eventHandler(); + CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler); window->setFixedSize(370, 330); window->setCaption("DrumGizmo v" VERSION); - GUI::Label *lbl_title = new GUI::Label(window); + Label *lbl_title = new Label(window); lbl_title->setText("DrumGizmo"); lbl_title->move(127, 7); lbl_title->resize(200, 20); - GUI::VerticalLine *l1 = new GUI::VerticalLine(window); + VerticalLine *l1 = new VerticalLine(window); l1->move(20, 30); l1->resize(window->width() - 40, 2); @@ -330,30 +255,31 @@ void PluginGUI::init() // Drumkit file { int y = 37; - GUI::Label *lbl = new GUI::Label(window); + Label *lbl = new Label(window); lbl->setText("Drumkit file:"); lbl->move(XOFFSET - 4, y); lbl->resize(100, 20); y += OFFSET1; - lineedit = new GUI::LineEdit(window); + lineedit = new LineEdit(window); lineedit->move(XOFFSET, y); lineedit->resize(243, 29); lineedit->setReadOnly(true); - GUI::Button *btn_brw = new GUI::Button(window); + Button *btn_brw = new 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); +// btn_brw->registerClickHandler(kitBrowseClick, this); + CONNECT(btn_brw, clickNotifier, this, &PluginGUI::kitBrowseClick); y += OFFSET2; - progress = new GUI::ProgressBar(window); + progress = new ProgressBar(window); progress->move(XOFFSET, y); progress->resize(window->width() - 2*XOFFSET, 11); y += OFFSET3; - GUI::VerticalLine *l = new GUI::VerticalLine(window); + VerticalLine *l = new VerticalLine(window); l->move(XOFFSET, y); l->resize(window->width() - 2*XOFFSET, 2); } @@ -361,30 +287,30 @@ void PluginGUI::init() // Midimap file { int y = 120; - lbl2 = new GUI::Label(window); + lbl2 = new Label(window); lbl2->setText("Midimap file:"); lbl2->move(XOFFSET - 4, y); lbl2->resize(100, 20); y += OFFSET1; - lineedit2 = new GUI::LineEdit(window); + lineedit2 = new LineEdit(window); lineedit2->move(XOFFSET, y); lineedit2->resize(243, 29); lineedit2->setReadOnly(true); - GUI::Button *btn_brw = new GUI::Button(window); + Button *btn_brw = new 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); + CONNECT(btn_brw, clickNotifier, this, &PluginGUI::midimapBrowseClick); y += OFFSET2; - progress2 = new GUI::ProgressBar(window); + progress2 = new ProgressBar(window); progress2->move(XOFFSET, y); progress2->resize(window->width() - 2*XOFFSET, 11); y += OFFSET3; - GUI::VerticalLine *l = new GUI::VerticalLine(window); + VerticalLine *l = new VerticalLine(window); l->move(XOFFSET, y); l->resize(window->width() - 2*XOFFSET, 2); } @@ -394,70 +320,69 @@ void PluginGUI::init() #define OFFSET4 21 // Enable Velocity - GUI::Label *lbl_velocity = new GUI::Label(window); + Label *lbl_velocity = new 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); + velocityCheck = new CheckBox(window); + //velocityCheck->setText("Enable Velocity Modifier"); + velocityCheck->move(26, y + OFFSET4); + velocityCheck->resize(59,38); + CONNECT(velocityCheck, stateChangedNotifier, this, &PluginGUI::velocityCheckClick); // Velocity Weight Modifier: { - GUI::Label *lbl_weight = new GUI::Label(window); + Label *lbl_weight = new 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); + attackKnob = new Knob(window); + attackKnob->move(109, y + OFFSET4 - 4); + attackKnob->resize(57, 57); + CONNECT(attackKnob, valueChangedNotifier, this, &PluginGUI::attackValueChanged); } // Velocity Falloff Modifier: { - GUI::Label *lbl_falloff = new GUI::Label(window); + Label *lbl_falloff = new 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); + falloffKnob = new Knob(window); + falloffKnob->move(202 - 13 - 5, y + OFFSET4 - 4); + falloffKnob->resize(57, 57); + CONNECT(falloffKnob, valueChangedNotifier, this, &PluginGUI::falloffValueChanged); } } - GUI::VerticalLine *l2 = new GUI::VerticalLine(window); + VerticalLine *l2 = new VerticalLine(window); l2->move(20, 310 - 15 - 9); l2->resize(window->width() - 40, 2); - GUI::Label *lbl_version = new GUI::Label(window); + Label *lbl_version = new 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); + ComboBox *cmb = new 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; + // Create file browser + fileBrowser = new FileBrowser(window); + fileBrowser->move(0, 0); + fileBrowser->resize(window->width() - 1, window->height() - 1); + fileBrowser->hide(); // Enable quit button -// GUI::Button *btn_quit = new GUI::Button(window); +// Button *btn_quit = new Button(window); // btn_quit->setText("Quit"); // btn_quit->move(50,280); // btn_quit->resize(80,80); @@ -506,6 +431,84 @@ void PluginGUI::setWindowClosedCallback(void (*handler)(void *), void *ptr) windowClosedPtr = ptr; } +void PluginGUI::attackValueChanged(float value) +{ + ChangeSettingMessage *msg = + new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, + value); + + msghandler.sendMessage(MSGRCV_ENGINE, msg); + +#ifdef STANDALONE + int i = value * 4; + switch(i) { + case 0: progress->setState(ProgressBarState::Off); break; + case 1: progress->setState(ProgressBarState::Blue); break; + case 2: progress->setState(ProgressBarState::Green); break; + case 3: progress->setState(ProgressBarState::Red); break; + default: break; + } +#endif +} + +void PluginGUI::falloffValueChanged(float value) +{ + ChangeSettingMessage *msg = + new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, + value); + msghandler.sendMessage(MSGRCV_ENGINE, msg); + +#ifdef STANDALONE + progress->setProgress(value); +#endif +} + +void PluginGUI::velocityCheckClick(bool checked) +{ + ChangeSettingMessage *msg = + new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, + checked); + msghandler.sendMessage(MSGRCV_ENGINE, msg); +} + +void PluginGUI::kitBrowseClick() +{ + std::string path = lineedit->text(); + if(path == "") + { + path = config->lastkit; + } + + if(path == "") + { + path = lineedit2->text(); + } + + fileBrowser->setPath(path); + CONNECT(fileBrowser, fileSelectNotifier, this, &PluginGUI::selectKitFile); + fileBrowser->show(); +} + +void PluginGUI::midimapBrowseClick() +{ + std::string path = lineedit2->text(); + if(path == "") + { + path = config->lastmidimap; + } + + if(path == "") + { + path = lineedit->text(); + } + + fileBrowser->setPath(path); + CONNECT(fileBrowser, fileSelectNotifier, this, &PluginGUI::selectMapFile); + fileBrowser->show(); +} + +} // GUI:: + #ifdef STANDALONE class Engine : public MessageHandler { @@ -513,7 +516,6 @@ public: void handleMessage(Message *msg) {} }; - void stop(void *ptr) { DEBUG(stop, "Stopping...\n"); @@ -523,32 +525,19 @@ void stop(void *ptr) int main() { -/* - 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::PluginGUI gui; gui.setWindowClosedCallback(stop, &running); // gui.show(); while(running) { - // gui.processEvents(); #ifdef WIN32 SleepEx(1000, FALSE); #else - // usleep(10000); sleep(1); #endif } diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index 39643e1..5e617dc 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.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_PLUGINGUI_H__ -#define __DRUMGIZMO_PLUGINGUI_H__ +#pragma once #include "window.h" #include "eventhandler.h" @@ -44,8 +43,11 @@ #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(); @@ -63,23 +65,16 @@ public: void handleMessage(Message *msg); - //private: - GUI::Window *window; - GUI::EventHandler *eventhandler; - - GUI::FileBrowser *filebrowser; - - GUI::CheckBox *check; - GUI::Knob *knob; - GUI::Knob *knob2; + Window *window; + EventHandler *eventhandler; - GUI::Label *lbl; - GUI::LineEdit *lineedit; - GUI::ProgressBar *progress; + Label *lbl; + LineEdit *lineedit; + ProgressBar *progress; - GUI::Label *lbl2; - GUI::LineEdit *lineedit2; - GUI::ProgressBar *progress2; + Label *lbl2; + LineEdit *lineedit2; + ProgressBar *progress2; Config *config; @@ -90,6 +85,21 @@ public: void *changeMidimapPtr; private: + void attackValueChanged(float value); + void falloffValueChanged(float value); + void velocityCheckClick(bool checked); + void kitBrowseClick(); + void midimapBrowseClick(); + void closeEventHandler(); + void selectKitFile(const std::string& filename); + void selectMapFile(const std::string& filename); + + // Humanized velocity controls: + CheckBox* velocityCheck; + Knob* attackKnob; + Knob* falloffKnob; + FileBrowser* fileBrowser; + volatile bool running; volatile bool closing; volatile bool initialised; @@ -97,4 +107,5 @@ private: Semaphore sem; }; -#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/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 05966aa..4b92e65 100644 --- a/plugingui/widget.cc +++ b/plugingui/widget.cc @@ -31,188 +31,190 @@ #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(); + if(parent) + { + window_x += parent->windowX(); + } - repaintEvent(e); - - 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:: diff --git a/src/configfile.cc b/src/configfile.cc index 6b0d14f..8447d9a 100644 --- a/src/configfile.cc +++ b/src/configfile.cc @@ -30,6 +30,7 @@ #include <errno.h> #include <string.h> #include <stdlib.h> +#include <unistd.h> #include <sys/stat.h> #include <sys/types.h> @@ -65,7 +66,7 @@ static std::string configPath() configpath = szPath; } #else - std::string configpath = strdup(getenv("HOME")); + std::string configpath = getenv("HOME"); #endif configpath += SEP; configpath += CONFIGDIRNAME; diff --git a/test/Makefile.am b/test/Makefile.am index 90373e1..08dba3b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,10 +1,20 @@ # Rules for the test code (use `make check` to execute) include $(top_srcdir)/src/Makefile.am.drumgizmo -TESTS = engine gui resampler lv2 configfile +TESTS = resource engine gui resampler lv2 configfile check_PROGRAMS = $(TESTS) +resource_CXXFLAGS = -DOUTPUT=\"resource\" $(CPPUNIT_CFLAGS) \ + -I$(top_srcdir)/hugin +resource_LDFLAGS = $(CPPUNIT_LIBS) +resource_SOURCES = \ + $(top_srcdir)/plugingui/resource.cc \ + $(top_srcdir)/plugingui/resource_data.cc \ + $(top_srcdir)/hugin/hugin.c \ + test.cc \ + resource_test.cc + engine_CXXFLAGS = -DOUTPUT=\"engine\" $(CPPUNIT_CFLAGS) \ -I$(top_srcdir)/src -I$(top_srcdir)/include \ -I$(top_srcdir)/hugin -DDISABLE_HUGIN diff --git a/test/resource_test.cc b/test/resource_test.cc new file mode 100644 index 0000000..7fc632a --- /dev/null +++ b/test/resource_test.cc @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * resource_test.cc + * + * Fri Nov 13 18:50:52 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 <cppunit/extensions/HelperMacros.h> + +#include "../plugingui/resource.h" + +class ResourceTester : public GUI::Resource { +public: + ResourceTester(const std::string& name) + : Resource(name) + {} + + bool probeIsInternal() + { + return isInternal; + } +}; + +class ResourceTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ResourceTest); + CPPUNIT_TEST(externalReadTest); + CPPUNIT_TEST(internalReadTest); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp() {} + void tearDown() {} + + void externalReadTest() + { + ResourceTester rc("kit/0000.wav"); + CPPUNIT_ASSERT(!rc.probeIsInternal()); + CPPUNIT_ASSERT(rc.valid()); + CPPUNIT_ASSERT_EQUAL((size_t)46, rc.size()); + } + + void internalReadTest() + { + ResourceTester rc(":bg.png"); + CPPUNIT_ASSERT(rc.probeIsInternal()); + CPPUNIT_ASSERT(rc.valid()); + CPPUNIT_ASSERT_EQUAL((size_t)1123, rc.size()); + } +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(ResourceTest); diff --git a/vst/Makefile.am b/vst/Makefile.am index 7bb7214..d6c5c9e 100644 --- a/vst/Makefile.am +++ b/vst/Makefile.am @@ -40,7 +40,7 @@ libdg_la_CXXFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/plugingui \ -DUSE_THREAD $(SAMPLERATE_CFLAGS) nodist_libdrumgizmo_vst_la_SOURCES = \ - $(VST_SOURCES) + $(VST_SOURCES) libdrumgizmo_vst_la_SOURCES = \ drumgizmo_vst.cc \ @@ -50,5 +50,4 @@ libdrumgizmo_vst_la_SOURCES = \ libdrumgizmo_vst_la_LDFLAGS = -no-undefined -shared libdrumgizmo_vst_la_LIBADD = libdg.la libdrumgizmo_vst_la_CXXFLAGS = -w $(VST_CPPFLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_srcdir)/plugingui - + -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_srcdir)/plugingui
\ No newline at end of file diff --git a/vst/Makefile.mingw32.in b/vst/Makefile.mingw32.in index 54c42e0..1a6a3e7 100644 --- a/vst/Makefile.mingw32.in +++ b/vst/Makefile.mingw32.in @@ -38,7 +38,6 @@ DG_SRC = \ DG_CFLAGS = -I.. -I../include -I../src -DSSE -msse -msse2 -DDISABLE_HUGIN GUI_SRC = \ - @top_srcdir@/plugingui/nativewindow_x11.cc \ @top_srcdir@/plugingui/nativewindow_win32.cc \ @top_srcdir@/plugingui/plugingui.cc \ @top_srcdir@/plugingui/pluginconfig.cc \ @@ -53,6 +52,7 @@ GUI_SRC = \ @top_srcdir@/plugingui/pixelbuffer.cc \ @top_srcdir@/plugingui/lineedit.cc \ @top_srcdir@/plugingui/led.cc \ + @top_srcdir@/plugingui/layout.cc \ @top_srcdir@/plugingui/checkbox.cc \ @top_srcdir@/plugingui/slider.cc \ @top_srcdir@/plugingui/scrollbar.cc \ diff --git a/vst/drumgizmo_vst.cc b/vst/drumgizmo_vst.cc index 6aec4f2..d9cb975 100644 --- a/vst/drumgizmo_vst.cc +++ b/vst/drumgizmo_vst.cc @@ -49,7 +49,7 @@ bool DGEditor::open(void* ptr) DEBUG(dgeditor, "open GUI (new PluginGUI)\n"); if(plugingui) delete plugingui; - plugingui = new PluginGUI(); + plugingui = new GUI::PluginGUI(); // plugingui->setChangeMidimapCallback(midimapHandler, dgeff); // plugingui->show(); diff --git a/vst/drumgizmo_vst.h b/vst/drumgizmo_vst.h index 4497c48..b15122c 100644 --- a/vst/drumgizmo_vst.h +++ b/vst/drumgizmo_vst.h @@ -112,7 +112,7 @@ public: private: DrumGizmoVst* dgeff; - PluginGUI *plugingui; + GUI::PluginGUI *plugingui; DrumGizmo *drumgizmo; }; |