diff options
Diffstat (limited to 'plugingui')
69 files changed, 5935 insertions, 4756 deletions
| 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:: | 
