diff options
108 files changed, 7324 insertions, 5503 deletions
@@ -34,8 +34,10 @@ test/result_*.xml test/resampler test/engine test/gui +test/lv2 +test/resource drumgizmo-*.tar.gz tst vst/Makefile.mingw32 test/*.log -test/*.trs
\ No newline at end of file +test/*.trs @@ -1,41 +1,71 @@ Installation Instructions ************************* +NOTE1: Certain audio-centric Linux distros such as KxStudio has DrumGizmo +included in the repository. To install it on such systems, use the distros +package manager, search for it and install it. Please refer to each distro's +documentation for detailed instructions on how to do this. -Compiling and installing the LV2 plugin +NOTE2: Be aware that if you are planning on running the LV2 plugin from within +one of the binary releases of Ardour, you must make sure that drumgizmo is using +the same version of libpng, pthread and expat as Ardour was compiled with (or +at least versions matching the ABI), otherwise the plugin will show strange +behaviour or even crash upon load. + +Compiling and Installing on linux (LV2) ======================================= -If you extracted the code from a tar-ball skip to the "Configuring" section. - -Preparing code from git ------------------------ -If you cloned the repository from git, make sure to run the following commands -in order to obtain the hugin debug code: - git submodule init - git submodule update - -After that you need to run ./autogen.sh - -Configuring ------------ -Run ./configure --enable-lv2 --prefix=/usr -Then run 'make && make install' and the plugin should be installed in -/usr/lib/lv2/drumgizmo.lv2 +This guide will show you how to unpack, compile and install the lv2 version +of the drumgizmo plugin. It will also show how to make it usable for the LV2 +host Ardour3. + +Prerequisites +------------- +* lv2-devel package >= 1.0 +* libsndfile-devel >= 1.0.21 +* zita-resampler-devel (no minimal version specified) +* libexpat-devel (no minimal version specified) +* pkg-config >= 0.23 +* Xlib >= 1.0 +* libpng >= 1.2 +* libsmf (no minimal version specified) +* pthread (no minimal version specified) +* libcppunit-dev (only necessary when compiling from git sources) + +Compiling source tarball +------------------------ +$ tar xvzf drumgizmo-[version].tar.gz (you probably already did this) +$ cd drumgizmo-[version] +$ ./configure --prefix=$PWD/install --enable-lv2 +$ make +$ make install + +Compiling from git sources +-------------------------- +$ git clone http://git.drumgizmo.org/drumgizmo.git +$ git submodule init +$ git submodule update +$ ./autogen.sh +$ ./configure --prefix=$PWD/install --enable-lv2 + If you want to compile only the LV2 parts of the plugin use '--disable-editor --disable-cli' as additional parameters to the configure script. -The LV2 plugin requires the following dependencies: -pkg-config >= 0.23 -lv2 >= 1.0 -Xlib >= 1.0 -sndfile >= 1.0.21 -libpng >= 1.2 -pthread (no minimal version specified) -expat (no minimal version specified) - -Be aware that if you are planning on running the LV2 plugin from within one -of the binary releases of Ardour, you must make sure that drumgizmo is using -the same version of libpng, pthread and expat as Ardour was compiled with (or -at least versions matching the ABI), otherwise the plugin will show strange -behaviour or even crash upon load. +Now compile and install +$ make +$ make install + +Installing for use with Ardour3 +------------------------------- +When the make install step has been successfully performed the source directory +will contain a folder named install. In this folder the: + + install/lib/lv2/drumgizmo.lv2 + +... is located. This folder contain all the files needed for the plugin to run. +In order to make it work with Ardour3, either copy this directory to the lv2 +plugin dir (usually /usr/lib/lv2) or create a symbolic link to the directory +$ ln -s [dg path]/install/lib/lv2/drumgizmo.lv2 /usr/lib/lv2/drumgizmo.lv2 +You need to be root to do this. Keep in mind that the lv2 directory differs from +distro to distro, so do a search for it in order to verify the correct location.
\ No newline at end of file diff --git a/configure.ac b/configure.ac index 7934cc2..823f93d 100644 --- a/configure.ac +++ b/configure.ac @@ -124,6 +124,8 @@ AC_SUBST(GUI_CFLAGS) AC_SUBST(GUI_LIBS) AM_CONDITIONAL([ENABLE_PUGL], [test "x$enable_gui" = "xpugl"]) +AM_CONDITIONAL([ENABLE_WIN32], [test "x$enable_gui" = "xwin32"]) +AM_CONDITIONAL([ENABLE_X11], [test "x$enable_gui" = "xx11"]) dnl ====================== dnl Compile unit tests @@ -228,7 +230,7 @@ AS_IF( [AC_MSG_RESULT([*** input dummy plugin disabled per user request ***]) have_input_dummy=no] ) - + dnl *** Test AC_ARG_ENABLE([input_test], AS_HELP_STRING([--disable-input-test], [Disable input test plugin [default=enabled]]),, @@ -444,11 +446,6 @@ AS_IF([test x$enable_resampler == xsrc], )] ) -#dnl ====================== -#dnl Check for zlib -#dnl ====================== -PKG_CHECK_MODULES(ZLIB, zlib >= 1.2.3) - dnl ====================== dnl Check for the pthread library dnl ====================== diff --git a/drumgizmo/audioinputenginedl.cc b/drumgizmo/audioinputenginedl.cc index 7feac55..e13bdd1 100644 --- a/drumgizmo/audioinputenginedl.cc +++ b/drumgizmo/audioinputenginedl.cc @@ -41,7 +41,7 @@ AudioInputEngineDL::AudioInputEngineDL(std::string name) is_jack_plugin = strstr(name.c_str(), "jack"); std::string plugin = INPUT_PLUGIN_DIR"/" + name + ".so"; - void *lib = dlopen(plugin.c_str(), RTLD_LAZY); + lib = dlopen(plugin.c_str(), RTLD_LAZY); if(!lib) { printf("Cannot load device: %s\n", dlerror()); return; @@ -124,6 +124,8 @@ AudioInputEngineDL::~AudioInputEngineDL() { i_destroy(ptr); if(is_jack_plugin) close_jack_client(); + dlclose(lib); + lib = nullptr; } bool AudioInputEngineDL::init(Instruments &instruments) diff --git a/drumgizmo/audioinputenginedl.h b/drumgizmo/audioinputenginedl.h index 7178f75..1cf2c1d 100644 --- a/drumgizmo/audioinputenginedl.h +++ b/drumgizmo/audioinputenginedl.h @@ -61,19 +61,21 @@ public: void setEngine(DrumGizmo* drumgizmo); private: - void *ptr; - input_create_func_t i_create; - input_destroy_func_t i_destroy; - input_init_func_t i_init; - input_setparm_func_t i_setparm; - input_start_func_t i_start; - input_stop_func_t i_stop; - input_pre_func_t i_pre; - input_run_func_t i_run; - input_post_func_t i_post; + void *ptr{nullptr}; + input_create_func_t i_create{nullptr}; + input_destroy_func_t i_destroy{nullptr}; + input_init_func_t i_init{nullptr}; + input_setparm_func_t i_setparm{nullptr}; + input_start_func_t i_start{nullptr}; + input_stop_func_t i_stop{nullptr}; + input_pre_func_t i_pre{nullptr}; + input_run_func_t i_run{nullptr}; + input_post_func_t i_post{nullptr}; bool is_jack_plugin; - JackClient *jackclient; + JackClient *jackclient{nullptr}; + + void *lib{nullptr}; }; #endif/*__DRUMGIZMO_AUDIOINPUTENGINEDL_H__*/ diff --git a/drumgizmo/audiooutputenginedl.cc b/drumgizmo/audiooutputenginedl.cc index fc887df..2e573cd 100644 --- a/drumgizmo/audiooutputenginedl.cc +++ b/drumgizmo/audiooutputenginedl.cc @@ -36,7 +36,7 @@ AudioOutputEngineDL::AudioOutputEngineDL(std::string name) is_jack_plugin = strstr(name.c_str(), "jack"); std::string plugin = OUTPUT_PLUGIN_DIR"/" + name + ".so"; - void *lib = dlopen(plugin.c_str(), RTLD_LAZY); + lib = dlopen(plugin.c_str(), RTLD_LAZY); if(!lib) { printf("Cannot load device: %s\n", dlerror()); return; @@ -132,6 +132,8 @@ AudioOutputEngineDL::~AudioOutputEngineDL() { o_destroy(ptr); if(is_jack_plugin) close_jack_client(); + dlclose(lib); + lib = nullptr; } bool AudioOutputEngineDL::init(Channels channels) diff --git a/drumgizmo/audiooutputenginedl.h b/drumgizmo/audiooutputenginedl.h index 62d94f8..39525fa 100644 --- a/drumgizmo/audiooutputenginedl.h +++ b/drumgizmo/audiooutputenginedl.h @@ -72,21 +72,23 @@ public: void setEngine(DrumGizmo* drumgizmo); private: - void *ptr; - output_create_func_t o_create; - output_destroy_func_t o_destroy; - output_init_func_t o_init; - output_setparm_func_t o_setparm; - output_start_func_t o_start; - output_stop_func_t o_stop; - output_pre_func_t o_pre; - output_run_func_t o_run; - output_post_func_t o_post; - output_bufsize_func_t o_bufsize; - output_samplerate_func_t o_samplerate; + void *ptr{nullptr}; + output_create_func_t o_create{nullptr}; + output_destroy_func_t o_destroy{nullptr}; + output_init_func_t o_init{nullptr}; + output_setparm_func_t o_setparm{nullptr}; + output_start_func_t o_start{nullptr}; + output_stop_func_t o_stop{nullptr}; + output_pre_func_t o_pre{nullptr}; + output_run_func_t o_run{nullptr}; + output_post_func_t o_post{nullptr}; + output_bufsize_func_t o_bufsize{nullptr}; + output_samplerate_func_t o_samplerate{nullptr}; bool is_jack_plugin; - JackClient *jackclient; + JackClient *jackclient{nullptr}; + + void* lib{nullptr}; }; #endif/*__DRUMGIZMO_AUDIOOUTPUTENGINEDL_H__*/ diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 708528c..8983aa3 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -34,10 +34,6 @@ #include <hugin.hpp> -#ifndef HUG_FLAG_OUTPUT_TO_STDOUT -#define HUG_FLAG_OUTPUT_TO_STDOUT 0 -#endif - #include "drumgizmo.h" #include "drumgizmoc.h" @@ -122,9 +118,10 @@ int CliMain::run(int argc, char *argv[]) { int c; + std::string hugin_filter; + unsigned int hugin_flags = 0; #ifndef DISABLE_HUGIN - const char *hugin_filter = "+all"; - unsigned int hugin_flags = HUG_FLAG_OUTPUT_TO_STDOUT; + hugin_flags = HUG_FLAG_DEFAULT; #endif/*DISABLE_HUGIN*/ std::string outputengine; @@ -150,7 +147,7 @@ int CliMain::run(int argc, char *argv[]) {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; - + c = getopt_long(argc, argv, "hvpo:O:i:I:e:a" #ifndef DISABLE_HUGIN "D:" @@ -217,13 +214,15 @@ int CliMain::run(int argc, char *argv[]) } hug_status_t status = hug_init(hugin_flags, - HUG_OPTION_FILTER, hugin_filter, + HUG_OPTION_FILTER, hugin_filter.c_str(), HUG_OPTION_END); if(status != HUG_STATUS_OK) { printf("Error: %d\n", status); return 1; } + DEBUG(drumgizmo, "Debug enabled."); + if(inputengine == "") { printf("Missing input engine\n"); return 1; @@ -265,6 +264,7 @@ int CliMain::run(int argc, char *argv[]) if(outputengine == "") { printf("Missing output engine\n"); + delete ie; return 1; } @@ -309,6 +309,8 @@ int CliMain::run(int argc, char *argv[]) if(kitfile != "") { printf("Can only handle a single kitfile.\n"); printf(usage_str, argv[0]); + delete ie; + delete oe; return 1; } kitfile = argv[optind++]; @@ -317,6 +319,8 @@ int CliMain::run(int argc, char *argv[]) } else { printf("Missing kitfile.\n"); printf(usage_str, argv[0]); + delete ie; + delete oe; return 1; } @@ -352,6 +356,8 @@ int CliMain::run(int argc, char *argv[]) if(!gizmo.init()) { printf("Failed init engine.\n"); + delete ie; + delete oe; return 1; } diff --git a/drumgizmo/input/jackmidi/Makefile.am b/drumgizmo/input/jackmidi/Makefile.am index fd63944..d392f19 100644 --- a/drumgizmo/input/jackmidi/Makefile.am +++ b/drumgizmo/input/jackmidi/Makefile.am @@ -26,7 +26,8 @@ libdir = $(INPUT_PLUGIN_DIR) AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src -I$(top_srcdir)/hugin jackmidi_la_LDFLAGS = -module -avoid-version -shared -jackmidi_la_LIBADD = +jackmidi_la_LIBADD = $(EXPAT_LIBS) +jackmidi_la_CXXFLAGS = $(EXPAT_CFLAGS) jackmidi_la_SOURCES = $(jackmidibuildsources) install-exec-hook: diff --git a/drumgizmo/input/jackmidi/jackmidi.cc b/drumgizmo/input/jackmidi/jackmidi.cc index 5496195..a6b49b7 100644 --- a/drumgizmo/input/jackmidi/jackmidi.cc +++ b/drumgizmo/input/jackmidi/jackmidi.cc @@ -60,8 +60,8 @@ public: private: void loadMap(std::string map) {} - JackClient *jackclient; - jack_port_t *midi_port; + JackClient *jackclient{nullptr}; + jack_port_t *midi_port{nullptr}; size_t pos; diff --git a/drumgizmo/input/midifile/Makefile.am b/drumgizmo/input/midifile/Makefile.am index f95a289..9ade475 100644 --- a/drumgizmo/input/midifile/Makefile.am +++ b/drumgizmo/input/midifile/Makefile.am @@ -27,8 +27,9 @@ libdir = $(INPUT_PLUGIN_DIR) AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include $(SMF_CFLAGS) \ $(EXPAT_CFLAGS) -I$(top_srcdir)/hugin -DWITH_HUG_MUTEX -midifile_la_LDFLAGS = $(SMF_LIBS) $(EXPAT_LIBS) -module -avoid-version -shared -midifile_la_LIBADD = +midifile_la_LDFLAGS = -module -avoid-version -shared +midifile_la_LIBADD = $(EXPAT_LIBS) $(SMF_LIBS) +midifile_la_CXXFLAGS =$(EXPAT_CFLAGS) midifile_la_SOURCES = $(midifilebuildsources) install-exec-hook: diff --git a/drumgizmo/output/alsa/alsa.cc b/drumgizmo/output/alsa/alsa.cc index 0de3cdb..f9a2068 100644 --- a/drumgizmo/output/alsa/alsa.cc +++ b/drumgizmo/output/alsa/alsa.cc @@ -53,15 +53,15 @@ public: size_t samplerate(); private: - snd_pcm_t *handle; - snd_pcm_hw_params_t *params; - sample_t *data; - size_t channels; + snd_pcm_t *handle{nullptr}; + snd_pcm_hw_params_t *params{nullptr}; + sample_t *data{nullptr}; + size_t channels{0}; // Parameters std::string device; - unsigned int srate; - snd_pcm_uframes_t frames; + unsigned int srate{0}; + snd_pcm_uframes_t frames{0}; }; Alsa::Alsa() diff --git a/drumgizmo/output/jackaudio/jackaudio.cc b/drumgizmo/output/jackaudio/jackaudio.cc index 7e795ef..e027742 100644 --- a/drumgizmo/output/jackaudio/jackaudio.cc +++ b/drumgizmo/output/jackaudio/jackaudio.cc @@ -57,10 +57,10 @@ public: size_t samplerate(); private: - JackClient *jackclient; - jack_port_t *output_port[64]; - size_t nchannels; - sample_t **channels; + JackClient *jackclient{nullptr}; + jack_port_t *output_port[64] = {}; + size_t nchannels{0}; + sample_t **channels{nullptr}; Semaphore sem; }; diff --git a/drumgizmo/output/wavfile/wavfile.cc b/drumgizmo/output/wavfile/wavfile.cc index fa4128e..8401f80 100644 --- a/drumgizmo/output/wavfile/wavfile.cc +++ b/drumgizmo/output/wavfile/wavfile.cc @@ -28,6 +28,7 @@ #include <audiotypes.h> #include <string> +#include <memory.h> #include <sndfile.h> @@ -48,8 +49,8 @@ public: private: SF_INFO sf_info; - SNDFILE **fh; - size_t channels; + SNDFILE **fh{nullptr}; + size_t channels{0}; // Parameters std::string filename; @@ -60,6 +61,7 @@ WavFile::WavFile() fh = NULL; filename = "output"; + memset(&sf_info, 0, sizeof(sf_info)); sf_info.channels = 1;//channels; sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; sf_info.samplerate = 44100; diff --git a/hugin b/hugin -Subproject 7e734710be0098ea77ca2d3f54fb626b65bbf47 +Subproject bb7388b685ed043b4a3030da86f7f1e49141477 diff --git a/lv2/input_lv2.h b/lv2/input_lv2.h index 32e2fd8..3e3ef31 100644 --- a/lv2/input_lv2.h +++ b/lv2/input_lv2.h @@ -47,10 +47,10 @@ public: event_t *run(size_t pos, size_t len, size_t *nevents); void post(); - LV2_Atom_Sequence *eventPort; + LV2_Atom_Sequence *eventPort{nullptr}; private: - Instruments *instruments; + Instruments *instruments{nullptr}; }; #endif/*__DRUMGIZMO_INPUT_LV2_H__*/ diff --git a/lv2/lv2_gui.cc b/lv2/lv2_gui.cc index 7b56c5b..858e097 100644 --- a/lv2/lv2_gui.cc +++ b/lv2/lv2_gui.cc @@ -114,7 +114,7 @@ struct DG_GUI { DrumGizmo *instance; LV2UI_Controller controller; - PluginGUI *gui; + GUI::PluginGUI *gui; struct lv2_external_ui_host *ui_host_ptr; }; @@ -190,7 +190,7 @@ static LV2UI_Handle ui_instantiate(const struct _LV2UI_Descriptor * descriptor, pt->virt.run = ui_run; pt->virt.show = ui_show; pt->virt.hide = ui_hide; - pt->gui = new PluginGUI(); + pt->gui = new GUI::PluginGUI(); pt->gui->setWindowClosedCallback(closeHandler, pt); *widget = (LV2UI_Widget)pt; diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index 00b0881..bc90f09 100644 --- a/plugingui/Makefile.am +++ b/plugingui/Makefile.am @@ -1,10 +1,8 @@ noinst_PROGRAMS = plugingui rcgen include Makefile.am.plugingui -#include $(top_srcdir)/src/Makefile.am.drumgizmo -plugingui_LDADD = $(SNDFILE_LIBS) $(PTHREAD_LIBS) $(EXPAT_LIBS) \ - -ldl $(PLUGIN_GUI_LIBS) +plugingui_LDADD = $(PLUGIN_GUI_LIBS) plugingui_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS) \ -I$(top_srcdir)/include $(PLUGIN_GUI_CFLAGS) -I$(top_srcdir)/src \ @@ -13,6 +11,7 @@ plugingui_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS) \ plugingui_CFLAGS = $(plugingui_CXXFLAGS) plugingui_SOURCES = \ + testmain.cc \ $(PLUGIN_GUI_SOURCES) \ $(top_srcdir)/src/configfile.cc \ $(top_srcdir)/src/thread.cc \ @@ -57,5 +56,4 @@ EXTRA_DIST = \ verticalline.h \ widget.h \ window.h \ - lodepng/lodepng.h - + lodepng/lodepng.h
\ No newline at end of file diff --git a/plugingui/Makefile.am.plugingui b/plugingui/Makefile.am.plugingui index b1698e4..f4c0a55 100644 --- a/plugingui/Makefile.am.plugingui +++ b/plugingui/Makefile.am.plugingui @@ -1,12 +1,7 @@ - -puglsources = - PLUGIN_GUI_SOURCES = \ $(top_srcdir)/hugin/hugin.c \ $(top_srcdir)/hugin/hugin_syslog.c \ - $(puglsources) \ - $(top_srcdir)/plugingui/nativewindow_x11.cc \ - $(top_srcdir)/plugingui/nativewindow_win32.cc \ + $(top_srcdir)/plugingui/dgwindow.cc \ $(top_srcdir)/plugingui/plugingui.cc \ $(top_srcdir)/plugingui/label.cc \ $(top_srcdir)/plugingui/eventhandler.cc \ @@ -22,6 +17,8 @@ PLUGIN_GUI_SOURCES = \ $(top_srcdir)/plugingui/checkbox.cc \ $(top_srcdir)/plugingui/slider.cc \ $(top_srcdir)/plugingui/scrollbar.cc \ + $(top_srcdir)/plugingui/textedit.cc \ + $(top_srcdir)/plugingui/layout.cc \ $(top_srcdir)/plugingui/listbox.cc \ $(top_srcdir)/plugingui/listboxthin.cc \ $(top_srcdir)/plugingui/listboxbasic.cc \ @@ -37,13 +34,27 @@ PLUGIN_GUI_SOURCES = \ $(top_srcdir)/plugingui/resource_data.cc \ $(top_srcdir)/plugingui/lodepng/lodepng.cpp -PLUGIN_GUI_LIBS = $(GUI_LIBS) $(PTHREAD_LIBS) $(ZLIB_LIBS) +PLUGIN_GUI_LIBS = $(GUI_LIBS) $(PTHREAD_LIBS) -PLUGIN_GUI_CFLAGS = $(GUI_CFLAGS) $(ZLIB_CFLAGS) -I$(top_srcdir)/hugin \ +PLUGIN_GUI_CFLAGS = $(GUI_CFLAGS) -I$(top_srcdir)/hugin \ -DWITH_HUG_SYSLOG -DWITH_HUG_MUTEX $(PTHREAD_CFLAGS) \ - -I$(top_srcdir)/pugl/pugl \ -DLODEPNG_NO_COMPILE_ENCODER \ -DLODEPNG_NO_COMPILE_DISK \ -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS \ -DLODEPNG_NO_COMPILE_ERROR_TEXT \ -DLODEPNG_NO_COMPILE_CPP + +if ENABLE_X11 +PLUGIN_GUI_SOURCES += $(top_srcdir)/plugingui/nativewindow_x11.cc +endif + +if ENABLE_WIN32 +PLUGIN_GUI_SOURCES += $(top_srcdir)/plugingui/nativewindow_win32.cc +endif + +if ENABLE_PUGL +PLUGIN_GUI_SOURCES += \ + $(top_srcdir)/plugingui/nativewindow_pugl.cc \ + $(top_srcdir)/pugl/pugl/pugl_x11.c +PLUGIN_GUI_CFLAGS += -I$(top_srcdir)/pugl/pugl +endif diff --git a/plugingui/Makefile.mingw32 b/plugingui/Makefile.mingw32 index b16535b..3f52e8a 100644 --- a/plugingui/Makefile.mingw32 +++ b/plugingui/Makefile.mingw32 @@ -1,67 +1,62 @@ -top_srcdir=.. -include Makefile.am.plugingui - -CFLAGS=-DSTANDALONE -DWIN32 -DUSE_THREAD ${PLUGIN_GUI_CFLAGS} \ - -I$(top_srcdir)/src -I/local/include -LDFLAGS=-mconsole -lgdi32 -lsetupapi -lws2_32 -L/local/lib -lz -pthread - -C_SOURCES = \ - $(top_srcdir)/hugin/hugin.c \ - $(top_srcdir)/hugin/hugin_syslog.c - -CXX_SOURCES = \ - $(top_srcdir)/plugingui/nativewindow_x11.cc \ - $(top_srcdir)/plugingui/nativewindow_win32.cc \ - $(top_srcdir)/plugingui/plugingui.cc \ - $(top_srcdir)/plugingui/pluginconfig.cc \ - $(top_srcdir)/plugingui/label.cc \ - $(top_srcdir)/plugingui/eventhandler.cc \ - $(top_srcdir)/plugingui/font.cc \ - $(top_srcdir)/plugingui/window.cc \ - $(top_srcdir)/plugingui/widget.cc \ - $(top_srcdir)/plugingui/colour.cc \ - $(top_srcdir)/plugingui/painter.cc \ - $(top_srcdir)/plugingui/button.cc \ - $(top_srcdir)/plugingui/pixelbuffer.cc \ - $(top_srcdir)/plugingui/lineedit.cc \ - $(top_srcdir)/plugingui/led.cc \ - $(top_srcdir)/plugingui/checkbox.cc \ - $(top_srcdir)/plugingui/slider.cc \ - $(top_srcdir)/plugingui/listbox.cc \ - $(top_srcdir)/plugingui/verticalline.cc \ - $(top_srcdir)/plugingui/listboxthin.cc \ - $(top_srcdir)/plugingui/listboxbasic.cc \ - $(top_srcdir)/plugingui/filebrowser.cc \ - $(top_srcdir)/plugingui/directory.cc \ - $(top_srcdir)/plugingui/knob.cc \ - $(top_srcdir)/plugingui/combobox.cc \ - $(top_srcdir)/plugingui/image.cc \ - $(top_srcdir)/plugingui/scrollbar.cc \ - $(top_srcdir)/plugingui/progressbar.cc \ - $(top_srcdir)/plugingui/resource.cc \ - $(top_srcdir)/plugingui/resource_data.cc \ - $(top_srcdir)/plugingui/lodepng/lodepng.cpp \ - $(top_srcdir)/src/thread.cc \ - $(top_srcdir)/src/semaphore.cc \ - $(top_srcdir)/src/mutex.cc \ - $(top_srcdir)/src/messagehandler.cc \ - $(top_srcdir)/src/messagereceiver.cc - -OBJECTS=$(CXX_SOURCES:.cc=.o) $(C_SOURCES:.c=.o) -#OBJECTS=$(PLUGIN_GUI_SOURCES:.cc=.o) - -#$(PLUGIN_GUI_SOURCES:.c=.o) - -all: $(CXX_SOURCES) $(C_SOURCES) plugingui.exe - -plugingui.exe: $(OBJECTS) - g++ -static -static-libgcc $(OBJECTS) $(LDFLAGS) $(CFLAGS) -o $@ - -%.o: %.cc - g++ -g -static -static-libgcc -O2 -c $(CFLAGS) $< -o $@ - -%.o: %.c - gcc -g -static -static-libgcc -O2 -c $(CFLAGS) $< -o $@ +DG_SRC = \ + ../src/configfile.cc \ + ../src/thread.cc \ + ../src/semaphore.cc \ + ../src/mutex.cc \ + ../src/messagehandler.cc \ + ../src/messagereceiver.cc + +DG_CFLAGS = -I.. -I../include -I../src -DSSE -msse -msse2 -DDISABLE_HUGIN + +GUI_SRC = \ + testmain.cc \ + dgwindow.cc \ + nativewindow_win32.cc \ + plugingui.cc \ + pluginconfig.cc \ + label.cc \ + eventhandler.cc \ + font.cc \ + window.cc \ + widget.cc \ + colour.cc \ + painter.cc \ + button.cc \ + pixelbuffer.cc \ + lineedit.cc \ + led.cc \ + layout.cc \ + checkbox.cc \ + slider.cc \ + scrollbar.cc \ + textedit.cc \ + listbox.cc \ + listboxthin.cc \ + listboxbasic.cc \ + knob.cc \ + filebrowser.cc \ + directory.cc \ + image.cc \ + combobox.cc \ + progressbar.cc \ + verticalline.cc \ + resource.cc \ + resource_data.cc \ + lodepng/lodepng.cpp + +GUI_CFLAGS=-DUSE_THREAD -DWIN32 -DSTANDALONE +GUI_LIBS=-lgdi32 -lsetupapi -lws2_32 + +DBG_SRC = \ + ../hugin/hugin.c \ + ../hugin/hugin_syslog.c + +DBG_CFLAGS=-I../hugin -DWITH_HUG_SYSLOG -DWITH_HUG_MUTEX -DDISABLE_HUGIN + +all: + gcc $(DBG_CFLAGS) ../hugin/hugin.c -c + gcc $(DBG_CFLAGS) ../hugin/hugin_syslog.c -c + g++ -std=c++11 -static -static-libgcc -O2 -g -Wall $(DBG_CFLAGS) $(DG_CFLAGS) $(DG_LIBS) hugin.o hugin_syslog.o $(DG_SRC) ${GUI_SRC} ${GUI_CFLAGS} $(GUI_LIBS) -o plugingui.exe clean: - rm -rf $(OBJECTS) plugingui.exe + del -f drumgizmo_vst.dll libdrumgizmo_vst.a diff --git a/plugingui/button.cc b/plugingui/button.cc index c316ef3..a3dd435 100644 --- a/plugingui/button.cc +++ b/plugingui/button.cc @@ -31,127 +31,134 @@ #include <stdio.h> #include <hugin.hpp> -GUI::Button::Button(Widget *parent) - : GUI::Widget(parent) -{ - box_up.topLeft = new Image(":pushbutton_tl.png"); - box_up.top = new Image(":pushbutton_t.png"); - box_up.topRight = new Image(":pushbutton_tr.png"); - box_up.left = new Image(":pushbutton_l.png"); - box_up.right = new Image(":pushbutton_r.png"); - box_up.bottomLeft = new Image(":pushbutton_bl.png"); - box_up.bottom = new Image(":pushbutton_b.png"); - box_up.bottomRight = new Image(":pushbutton_br.png"); - box_up.center = new Image(":pushbutton_c.png"); - - box_down.topLeft = new Image(":pushbuttondown_tl.png"); - box_down.top = new Image(":pushbuttondown_t.png"); - box_down.topRight = new Image(":pushbuttondown_tr.png"); - box_down.left = new Image(":pushbuttondown_l.png"); - box_down.right = new Image(":pushbuttondown_r.png"); - box_down.bottomLeft = new Image(":pushbuttondown_bl.png"); - box_down.bottom = new Image(":pushbuttondown_b.png"); - box_down.bottomRight = new Image(":pushbuttondown_br.png"); - box_down.center = new Image(":pushbuttondown_c.png"); - - draw_state = up; - button_state = up; - - handler = NULL; - ptr = NULL; -} +namespace GUI { -void GUI::Button::registerClickHandler(void (*handler)(void *), void *ptr) +Button::Button(Widget *parent) + : Widget(parent) + , draw_state(up) + , button_state(up) { - this->handler = handler; - this->ptr = ptr; + box_up.topLeft = new Image(":pushbutton_tl.png"); + box_up.top = new Image(":pushbutton_t.png"); + box_up.topRight = new Image(":pushbutton_tr.png"); + box_up.left = new Image(":pushbutton_l.png"); + box_up.right = new Image(":pushbutton_r.png"); + box_up.bottomLeft = new Image(":pushbutton_bl.png"); + box_up.bottom = new Image(":pushbutton_b.png"); + box_up.bottomRight = new Image(":pushbutton_br.png"); + box_up.center = new Image(":pushbutton_c.png"); + + box_down.topLeft = new Image(":pushbuttondown_tl.png"); + box_down.top = new Image(":pushbuttondown_t.png"); + box_down.topRight = new Image(":pushbuttondown_tr.png"); + box_down.left = new Image(":pushbuttondown_l.png"); + box_down.right = new Image(":pushbuttondown_r.png"); + box_down.bottomLeft = new Image(":pushbuttondown_bl.png"); + box_down.bottom = new Image(":pushbuttondown_b.png"); + box_down.bottomRight = new Image(":pushbuttondown_br.png"); + box_down.center = new Image(":pushbuttondown_c.png"); } -void GUI::Button::buttonEvent(ButtonEvent *e) +Button::~Button() { - if(e->direction == 1) { - draw_state = down; - button_state = down; - in_button = true; - repaintEvent(NULL); - } - if(e->direction == -1) { - draw_state = up; - button_state = up; - repaintEvent(NULL); - if(in_button) { - clicked(); - if(handler) handler(ptr); - } - } + delete(box_up.topLeft); + delete(box_up.top); + delete(box_up.topRight); + delete(box_up.left); + delete(box_up.right); + delete(box_up.bottomLeft); + delete(box_up.bottom); + delete(box_up.bottomRight); + delete(box_up.center); + delete(box_down.topLeft); + delete(box_down.top); + delete(box_down.topRight); + delete(box_down.left); + delete(box_down.right); + delete(box_down.bottomLeft); + delete(box_down.bottom); + delete(box_down.bottomRight); + delete(box_down.center); } -void GUI::Button::repaintEvent(GUI::RepaintEvent *e) +void Button::buttonEvent(ButtonEvent* buttonEvent) { - Painter p(this); - - p.clear(); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) return; - - switch(draw_state) { - case up: - p.drawBox(0, 0, &box_up, w, h); - break; - case down: - p.drawBox(0, 0, &box_down, w, h); - break; - } - - Font font(":fontemboss.png"); - p.setColour(Colour(0.1)); - p.drawText(width()/2-(text.length()*3)+(draw_state==up?0:1), - height()/2+5+1+(draw_state==up?0:1), font, text, true); + if(buttonEvent->direction == Direction::down) + { + draw_state = down; + button_state = down; + in_button = true; + repaintEvent(nullptr); + } + + if(buttonEvent->direction == Direction::up) + { + draw_state = up; + button_state = up; + repaintEvent(nullptr); + if(in_button) + { + clicked(); + clickNotifier(); + } + } } -void GUI::Button::setText(std::string text) +void Button::repaintEvent(RepaintEvent* repaintEvent) { - this->text = text; - repaintEvent(NULL); + Painter p(*this); + + p.clear(); + + int padTop = 3; + int padLeft = 0; + + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } + + switch(draw_state) { + case up: + p.drawBox(padLeft, padTop, box_up, w - padLeft, h - padTop); + break; + case down: + p.drawBox(padLeft, padTop, box_down, w - padLeft, h - padTop); + break; + } + + p.setColour(Colour(0.1)); + p.drawText(width()/2-(text.length()*3)+(draw_state==up?0:1) + (padLeft / 2), + height()/2+5+1+(draw_state==up?0:1) + (padTop / 2), font, text, + true); } -void GUI::Button::mouseLeaveEvent() +void Button::setText(const std::string& text) { - in_button = false; - if(button_state == down) { - draw_state = up; - repaintEvent(NULL); - } + this->text = text; + repaintEvent(nullptr); } -void GUI::Button::mouseEnterEvent() +void Button::mouseLeaveEvent() { - in_button = true; - if(button_state == down) { - draw_state = down; - repaintEvent(NULL); - } + in_button = false; + if(button_state == down) + { + draw_state = up; + repaintEvent(nullptr); + } } -void GUI::Button::mouseMoveEvent(MouseMoveEvent *e) +void Button::mouseEnterEvent() { + in_button = true; + if(button_state == down) + { + draw_state = down; + repaintEvent(nullptr); + } } -#ifdef TEST_BUTTON -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_BUTTON*/ +} //GUI:: diff --git a/plugingui/button.h b/plugingui/button.h index 682dfa2..f42dc99 100644 --- a/plugingui/button.h +++ b/plugingui/button.h @@ -24,57 +24,56 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_BUTTON_H__ -#define __DRUMGIZMO_BUTTON_H__ +#pragma once #include <string> #include "widget.h" #include "painter.h" +#include "notifier.h" +#include "font.h" namespace GUI { class Button : public Widget { public: - Button(Widget *parent); + Button(Widget *parent); + ~Button(); - bool isFocusable() { return true; } - bool catchMouse() { return true; } + // From Widget: + bool isFocusable() override { return true; } + bool catchMouse() override { return true; } - void setText(std::string text); + void setText(const std::string& text); - void registerClickHandler(void (*handler)(void *), void *ptr); + Notifier<> clickNotifier; - //protected: - virtual void clicked() {} +protected: + virtual void clicked() {} - virtual void repaintEvent(RepaintEvent *e); - virtual void buttonEvent(ButtonEvent *e); - - virtual void mouseLeaveEvent(); - virtual void mouseEnterEvent(); - virtual void mouseMoveEvent(MouseMoveEvent *e); + // From Widget: + virtual void repaintEvent(RepaintEvent* e) override; + virtual void buttonEvent(ButtonEvent* e) override; + virtual void mouseLeaveEvent() override; + virtual void mouseEnterEvent() override; private: - bool in_button; - - Painter::Box box_up; - Painter::Box box_down; + bool in_button{false}; - typedef enum { - up, - down - } state_t; + Painter::Box box_up; + Painter::Box box_down; - std::string text; + typedef enum { + up, + down + } state_t; - state_t draw_state; - state_t button_state; + std::string text; - void (*handler)(void *); - void *ptr; -}; + Font font{":fontemboss.png"}; + state_t draw_state{up}; + state_t button_state{up}; }; -#endif/*__DRUMGIZMO_BUTTON_H__*/ +} // GUI:: diff --git a/plugingui/checkbox.cc b/plugingui/checkbox.cc index faf3741..60ed7a6 100644 --- a/plugingui/checkbox.cc +++ b/plugingui/checkbox.cc @@ -30,101 +30,126 @@ #include <stdio.h> -GUI::CheckBox::CheckBox(Widget *parent) - : GUI::Widget(parent), - bg_on(":switch_back_on.png"), bg_off(":switch_back_off.png"), - knob(":switch_front.png") +namespace GUI { + +CheckBox::CheckBox(Widget* parent) + : Widget(parent) + , bg_on(":switch_back_on.png") + , bg_off(":switch_back_off.png") + , knob(":switch_front.png") + , state(false) + , middle(false) { - middle = false; - state = false; - handler = NULL; } -void GUI::CheckBox::buttonEvent(ButtonEvent *e) +void CheckBox::buttonEvent(ButtonEvent* buttonEvent) { - if(e->direction == -1 || e->doubleclick) { - state = !state; - middle = false; - if(handler) handler(ptr); - } else { - middle = true; - } - - repaintEvent(NULL); + if((buttonEvent->direction == Direction::up) || buttonEvent->doubleClick) + { + buttonDown = false; + middle = false; + if(inCheckbox) + { + internalSetChecked(!state); + } + } + else + { + buttonDown = true; + middle = true; + } + + repaintEvent(nullptr); } -void GUI::CheckBox::setText(std::string text) +void CheckBox::setText(std::string text) { - _text = text; - repaintEvent(NULL); + _text = text; + repaintEvent(nullptr); } -void GUI::CheckBox::registerClickHandler(void (*handler)(void *), void *ptr) +void CheckBox::keyEvent(KeyEvent* keyEvent) { - this->handler = handler; - this->ptr = ptr; + if(keyEvent->keycode == Key::character && keyEvent->text == " ") + { + if(keyEvent->direction == Direction::up) + { + middle = false; + internalSetChecked(!state); + } + else + { + middle = true; + } + + repaintEvent(nullptr); + } } -void GUI::CheckBox::keyEvent(KeyEvent *e) +void CheckBox::repaintEvent(RepaintEvent* repaintEvent) { - if(e->keycode == GUI::KeyEvent::KEY_CHARACTER && e->text == " ") { - if(e->direction == -1) { - state = !state; - middle = false; - } else { - middle = true; - } - - repaintEvent(NULL); - } + Painter p(*this); + + p.clear(); + + p.drawImage(0, (knob.height() - bg_on.height()) / 2, state ? bg_on : bg_off); + + if(middle) + { + p.drawImage((bg_on.width() - knob.width()) / 2 + 1, 0, knob); + return; + } + + if(state) + { + p.drawImage(bg_on.width() - 40 + 2, 0, knob); + } + else + { + p.drawImage(0, 0, knob); + } } -void GUI::CheckBox::repaintEvent(GUI::RepaintEvent *e) +bool CheckBox::checked() { - Painter p(this); - - p.clear(); - - if(state) { - p.drawImage(0, (knob.height() - bg_on.height()) / 2, &bg_on); - if(middle) p.drawImage((bg_on.width() - knob.width()) / 2 + 1, 0, &knob); - else p.drawImage(bg_on.width() - 40 + 2, 0, &knob); - } else { - p.drawImage(0, (knob.height() - bg_off.height()) / 2, &bg_off); - if(middle) p.drawImage((bg_on.width() - knob.width()) / 2 + 1, 0, &knob); - else p.drawImage(0, 0, &knob); - } - /* - p.setColour(Colour(1)); - Font font; - p.drawText(box + 8, height() / 2 + 5, font, _text); - */ + return state; } -bool GUI::CheckBox::checked() +void CheckBox::setChecked(bool c) { - return state; + internalSetChecked(c); } -void GUI::CheckBox::setChecked(bool c) +void CheckBox::mouseLeaveEvent() { - state = c; - repaintEvent(NULL); + inCheckbox = false; + if(buttonDown) + { + middle = false; + repaintEvent(nullptr); + } } -#ifdef TEST_CHECKBOX -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). +void CheckBox::mouseEnterEvent() +{ + inCheckbox = true; + if(buttonDown) + { + middle = true; + repaintEvent(nullptr); + } +} -TEST_END; +void CheckBox::internalSetChecked(bool checked) +{ + if(checked == state) + { + return; + } + + state = checked; + stateChangedNotifier(state); + repaintEvent(nullptr); +} -#endif/*TEST_CHECKBOX*/ +} // GUI:: diff --git a/plugingui/checkbox.h b/plugingui/checkbox.h index 1d6f9d6..927bf6d 100644 --- a/plugingui/checkbox.h +++ b/plugingui/checkbox.h @@ -24,48 +24,50 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_CHECKBOX_H__ -#define __DRUMGIZMO_CHECKBOX_H__ +#pragma once #include "widget.h" #include "image.h" +#include "notifier.h" namespace GUI { class CheckBox : public Widget { public: - CheckBox(Widget *parent); + CheckBox(Widget *parent); - void setText(std::string text); + void setText(std::string text); - bool isFocusable() { return true; } + // From Widget: + bool isFocusable() override { return true; } + bool catchMouse() override { return true; } - bool checked(); - void setChecked(bool checked); + bool checked(); + void setChecked(bool checked); - void registerClickHandler(void (*handler)(void *), void *ptr); + Notifier<bool> stateChangedNotifier; - //protected: - virtual void clicked() {} - - virtual void repaintEvent(RepaintEvent *e); - virtual void buttonEvent(ButtonEvent *e); - virtual void keyEvent(KeyEvent *e); +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void keyEvent(KeyEvent* keyEvent) override; + virtual void mouseLeaveEvent() override; + virtual void mouseEnterEvent() override; private: - Image bg_on; - Image bg_off; - Image knob; - - bool state; - bool middle; + void internalSetChecked(bool checked); - void (*handler)(void *); - void *ptr; + Image bg_on; + Image bg_off; + Image knob; - std::string _text; -}; + bool state; + bool middle; + bool buttonDown = false; + bool inCheckbox = false; + std::string _text; }; -#endif/*__DRUMGIZMO_CHECKBOX_H__*/ +} // GUI:: diff --git a/plugingui/colour.cc b/plugingui/colour.cc index 943011b..fb3d789 100644 --- a/plugingui/colour.cc +++ b/plugingui/colour.cc @@ -26,38 +26,25 @@ */ #include "colour.h" -GUI::Colour::Colour() +namespace GUI { + +Colour::Colour() { - red = blue = green = alpha = 1.0; + red = blue = green = alpha = 1.0; } -GUI::Colour::Colour(float grey, float a) +Colour::Colour(float grey, float a) { - red = green = blue = grey; - alpha = a; + red = green = blue = grey; + alpha = a; } -GUI::Colour::Colour(float r, float g, float b, float a) +Colour::Colour(float r, float g, float b, float a) { - red = r; - green = g; - blue = b; - alpha = a; + red = r; + green = g; + blue = b; + alpha = a; } -#ifdef TEST_COLOUR -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_COLOUR*/ +} // GUI:: diff --git a/plugingui/colour.h b/plugingui/colour.h index 92ec99e..9f539e9 100644 --- a/plugingui/colour.h +++ b/plugingui/colour.h @@ -24,28 +24,25 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_COLOUR_H__ -#define __DRUMGIZMO_COLOUR_H__ +#pragma once namespace GUI { class Colour { public: - Colour(); + Colour(); - Colour(float grey, float alpha = 1.0); + Colour(float grey, float alpha = 1.0); - Colour(float red, - float green, - float blue, - float alpha = 1.0); + Colour(float red, + float green, + float blue, + float alpha = 1.0); - float red; - float green; - float blue; - float alpha; + float red; + float green; + float blue; + float alpha; }; -}; - -#endif/*__DRUMGIZMO_COLOUR_H__*/ +} // GUI:: diff --git a/plugingui/combobox.cc b/plugingui/combobox.cc index 4637282..1323dab 100644 --- a/plugingui/combobox.cc +++ b/plugingui/combobox.cc @@ -33,199 +33,215 @@ #define BORDER 10 -void listboxSelectHandler(void *ptr) -{ - GUI::ComboBox *c = (GUI::ComboBox*)ptr; - GUI::ButtonEvent e; - e.direction = 1; - c->buttonEvent(&e); -} +namespace GUI { -GUI::ComboBox::ComboBox(GUI::Widget *parent) - : GUI::Widget(parent) +void ComboBox::listboxSelectHandler() { - handler = NULL; - ptr = NULL; - - box.topLeft = new Image(":widget_tl.png"); - box.top = new Image(":widget_t.png"); - box.topRight = new Image(":widget_tr.png"); - box.left = new Image(":widget_l.png"); - box.right = new Image(":widget_r.png"); - box.bottomLeft = new Image(":widget_bl.png"); - box.bottom = new Image(":widget_b.png"); - box.bottomRight = new Image(":widget_br.png"); - box.center = new Image(":widget_c.png"); - - listbox = new GUI::ListBoxThin(parent); - listbox->registerSelectHandler(listboxSelectHandler, this); - listbox->registerClickHandler(listboxSelectHandler, this); - listbox->hide(); + ButtonEvent buttonEvent; + buttonEvent.direction = Direction::down; + this->buttonEvent(&buttonEvent); } -GUI::ComboBox::~ComboBox() +ComboBox::ComboBox(Widget* parent) + : Widget(parent) + , listbox(parent) { + box.topLeft = new Image(":widget_tl.png"); + box.top = new Image(":widget_t.png"); + box.topRight = new Image(":widget_tr.png"); + box.left = new Image(":widget_l.png"); + box.right = new Image(":widget_r.png"); + box.bottomLeft = new Image(":widget_bl.png"); + box.bottom = new Image(":widget_b.png"); + box.bottomRight = new Image(":widget_br.png"); + box.center = new Image(":widget_c.png"); + + CONNECT(&listbox, selectionNotifier, this, &ComboBox::listboxSelectHandler); + CONNECT(&listbox, clickNotifier, this, &ComboBox::listboxSelectHandler); + + listbox.hide(); } -void GUI::ComboBox::addItem(std::string name, std::string value) +ComboBox::~ComboBox() { - listbox->addItem(name, value); + delete box.topLeft; + delete box.top; + delete box.topRight; + delete box.left; + delete box.right; + delete box.bottomLeft; + delete box.bottom; + delete box.bottomRight; + delete box.center; } -void GUI::ComboBox::clear() +void ComboBox::addItem(std::string name, std::string value) { - listbox->clear(); - repaintEvent(NULL); + listbox.addItem(name, value); } -bool GUI::ComboBox::selectItem(int index) +void ComboBox::clear() { - listbox->selectItem(index); - repaintEvent(NULL); - return true; + listbox.clear(); + repaintEvent(nullptr); } -std::string GUI::ComboBox::selectedName() +bool ComboBox::selectItem(int index) { - return listbox->selectedName(); + listbox.selectItem(index); + repaintEvent(nullptr); + return true; } -std::string GUI::ComboBox::selectedValue() +std::string ComboBox::selectedName() { - return listbox->selectedValue(); + return listbox.selectedName(); } -void GUI::ComboBox::registerValueChangedHandler(void (*handler)(void *), - void *ptr) +std::string ComboBox::selectedValue() { - this->handler = handler; - this->ptr = ptr; + return listbox.selectedValue(); } -static void drawArrow(GUI::Painter &p, int x, int y, int w, int h) +static void drawArrow(Painter &p, int x, int y, int w, int h) { - p.drawLine(x, y, x+(w/2), y+h); - p.drawLine(x+(w/2), y+h, x+w, y); + p.drawLine(x, y, x+(w/2), y+h); + p.drawLine(x+(w/2), y+h, x+w, y); - y++; - p.drawLine(x, y, x+(w/2), y+h); - p.drawLine(x+(w/2), y+h, x+w, y); + y++; + p.drawLine(x, y, x+(w/2), y+h); + p.drawLine(x+(w/2), y+h, x+w, y); } -void GUI::ComboBox::repaintEvent(GUI::RepaintEvent *e) +void ComboBox::repaintEvent(RepaintEvent* repaintEvent) { - Painter p(this); + Painter p(*this); + + p.clear(); - p.clear(); + std::string _text = selectedName(); - std::string _text = selectedName(); + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } - int w = width(); - int h = height(); - if(w == 0 || h == 0) return; - p.drawBox(0, 0, &box, w, h); + p.drawBox(0, 0, box, w, h); - p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); - p.drawText(BORDER - 4 + 3, height()/2+5 + 1 + 1, font, _text); + p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); + p.drawText(BORDER - 4 + 3, height()/2+5 + 1 + 1, font, _text); - // p.setColour(Colour(1, 1, 1)); - // p.drawText(BORDER - 4, (height()+font.textHeight()) / 2 + 1, font, _text); + // p.setColour(Colour(1, 1, 1)); + // p.drawText(BORDER - 4, (height()+font.textHeight()) / 2 + 1, font, _text); - //int n = height() / 2; + //int n = height() / 2; - // p.drawLine(width() - n - 6, 1 + 6, width() - 1 - 6, 1 + 6); - { - int w = 10; - int h = 6; - drawArrow(p, width() - 6 - 4 - w, (height() - h) / 2, w, h); - p.drawLine(width() - 6 - 4 - w - 4, 7, - width() - 6 - 4 - w - 4, height() - 8); - } + // p.drawLine(width() - n - 6, 1 + 6, width() - 1 - 6, 1 + 6); + { + int w = 10; + int h = 6; + drawArrow(p, width() - 6 - 4 - w, (height() - h) / 2, w, h); + p.drawLine(width() - 6 - 4 - w - 4, 7, + width() - 6 - 4 - w - 4, height() - 8); + } } -void GUI::ComboBox::scrollEvent(ScrollEvent *e) +void ComboBox::scrollEvent(ScrollEvent* scrollEvent) { - /* - scroll_offset += e->delta; - if(scroll_offset < 0) scroll_offset = 0; - if(scroll_offset > (items.size() - 1)) - scroll_offset = (items.size() - 1); - repaintEvent(NULL); - */ + /* + scroll_offset += e->delta; + if(scroll_offset < 0) + { + scroll_offset = 0; + } + if(scroll_offset > (items.size() - 1)) + { + scroll_offset = (items.size() - 1); + } + repaintEvent(nullptr); + */ } -void GUI::ComboBox::keyEvent(GUI::KeyEvent *e) +void ComboBox::keyEvent(KeyEvent* keyEvent) { - if(e->direction != -1) return; - - /* - switch(e->keycode) { - case GUI::KeyEvent::KEY_UP: - { - selected--; - if(selected < 0) selected = 0; - if(selected < scroll_offset) { - scroll_offset = selected; - if(scroll_offset < 0) scroll_offset = 0; - } - } - break; - case GUI::KeyEvent::KEY_DOWN: - { - // Number of items that can be displayed at a time. - int numitems = height() / (font.textHeight() + padding); - - selected++; - if(selected > (items.size() - 1)) - selected = (items.size() - 1); - if(selected > (scroll_offset + numitems - 1)) { - scroll_offset = selected - numitems + 1; - if(scroll_offset > (items.size() - 1)) - scroll_offset = (items.size() - 1); - } - } - break; - case GUI::KeyEvent::KEY_HOME: - selected = 0; - break; - case GUI::KeyEvent::KEY_END: - selected = items.size() - 1; - break; - default: - break; - } - - repaintEvent(NULL); - */ + if(keyEvent->direction != Direction::up) + { + return; + } + + /* + switch(keyEvent->keycode) { + case Key::up: + { + selected--; + if(selected < 0) + { + selected = 0; + } + if(selected < scroll_offset) + { + scroll_offset = selected; + if(scroll_offset < 0) + { + scroll_offset = 0; + } + } + } + break; + case Key::down: + { + // Number of items that can be displayed at a time. + int numitems = height() / (font.textHeight() + padding); + + selected++; + if(selected > (items.size() - 1)) + { + selected = (items.size() - 1); + } + if(selected > (scroll_offset + numitems - 1)) + { + scroll_offset = selected - numitems + 1; + if(scroll_offset > (items.size() - 1)) + { + scroll_offset = (items.size() - 1); + } + } + } + break; + case Key::home: + selected = 0; + break; + case Key::end: + selected = items.size() - 1; + break; + default: + break; + } + + repaintEvent(nullptr); + */ } -void GUI::ComboBox::buttonEvent(ButtonEvent *e) +void ComboBox::buttonEvent(ButtonEvent* buttonEvent) { - if(e->direction != 1) return; - - if(!listbox->visible()) { - listbox->resize(width() - 10, 100); - listbox->move(x() + 5, y() + height() - 7); - } else { - if(handler) handler(ptr); - } - - listbox->setVisible(!listbox->visible()); + if(buttonEvent->direction != Direction::down) + { + return; + } + + if(!listbox.visible()) + { + listbox.resize(width() - 10, 100); + listbox.move(x() + 5, y() + height() - 7); + } + else + { + valueChangedNotifier(listbox.selectedName(), listbox.selectedValue()); + } + + listbox.setVisible(!listbox.visible()); } -#ifdef TEST_COMBOBOX -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_COMBOBOX*/ +} // GUI:: diff --git a/plugingui/combobox.h b/plugingui/combobox.h index bc4ae38..1e4fb8d 100644 --- a/plugingui/combobox.h +++ b/plugingui/combobox.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_COMBOBOX_H__ -#define __DRUMGIZMO_COMBOBOX_H__ +#pragma once #include <string.h> #include <vector> @@ -39,35 +38,32 @@ namespace GUI { class ComboBox : public Widget { public: - ComboBox(Widget *parent); - ~ComboBox(); + ComboBox(Widget* parent); + ~ComboBox(); - bool isFocusable() { return true; } + void addItem(std::string name, std::string value); - void addItem(std::string name, std::string value); + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); + // From Widget: + bool isFocusable() override { return true; } + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void scrollEvent(ScrollEvent* scrollEvent) override; + virtual void keyEvent(KeyEvent* keyEvent) override; - void registerValueChangedHandler(void (*handler)(void *), void *ptr); - - virtual void repaintEvent(RepaintEvent *e); - virtual void buttonEvent(ButtonEvent *e); - virtual void scrollEvent(ScrollEvent *e); - virtual void keyEvent(KeyEvent *e); + Notifier<std::string, std::string> valueChangedNotifier; private: - Painter::Box box; - - GUI::Font font; - GUI::ListBoxThin *listbox; + Painter::Box box; - void (*handler)(void *); - void *ptr; -}; + void listboxSelectHandler(); + Font font; + ListBoxThin listbox; }; -#endif/*__DRUMGIZMO_COMBOBOX_H__*/ +} // GUI:: diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc new file mode 100644 index 0000000..9eae38c --- /dev/null +++ b/plugingui/dgwindow.cc @@ -0,0 +1,344 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * dgwindow.cc + * + * Mon Nov 23 20:30:45 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "dgwindow.h" + +#include "knob.h" +#include "verticalline.h" +#include "../version.h" + +#include "messagehandler.h" +#include "pluginconfig.h" + +namespace GUI { + +class LabeledControl : public Widget +{ +public: + LabeledControl(Widget* parent, const std::string& name) + : Widget(parent) + { + layout.setResizeChildren(false); + layout.setHAlignment(HAlignment::center); + + caption.setText(name); + caption.resize(100, 20); + caption.setAlignment(TextAlignment::center); + layout.addItem(&caption); + } + + void setControl(Widget* control) + { + layout.addItem(control); + } + + VBoxLayout layout{this}; + + Label caption{this}; +}; + +class File : public Widget +{ +public: + File(Widget* parent) + : Widget(parent) + { + layout.setResizeChildren(false); + layout.setVAlignment(VAlignment::center); + + lineedit.resize(243, 29); + layout.addItem(&lineedit); + + browseButton.setText("Browse..."); + browseButton.resize(85, 41); + layout.addItem(&browseButton); + } + + HBoxLayout layout{this}; + + LineEdit lineedit{this}; + Button browseButton{this}; +}; + +class HumanizeControls : public Widget +{ +public: + HumanizeControls(Widget* parent) + : Widget(parent) + { + layout.setResizeChildren(false); + layout.setVAlignment(VAlignment::center); + + velocity.resize(80, 80); + velocityCheck.resize(59, 38); + velocity.setControl(&velocityCheck); + layout.addItem(&velocity); + + attack.resize(80, 80); + attackKnob.resize(60, 60); + attack.setControl(&attackKnob); + layout.addItem(&attack); + + falloff.resize(80, 80); + falloffKnob.resize(60, 60); + falloff.setControl(&falloffKnob); + layout.addItem(&falloff); + } + + HBoxLayout layout{this}; + + LabeledControl velocity{this, "Humanizer"}; + LabeledControl attack{this, "Attack"}; + LabeledControl falloff{this, "Release"}; + + CheckBox velocityCheck{&velocity}; + Knob attackKnob{&attack}; + Knob falloffKnob{&falloff}; +}; + +DGWindow::DGWindow(MessageHandler& messageHandler, Config& config) + : messageHandler(messageHandler) + , config(config) +{ + + int vlineSpacing = 16; + + setFixedSize(370, 330); + setCaption("DrumGizmo v" VERSION); + + layout.setResizeChildren(false); + layout.setHAlignment(HAlignment::center); +// layout.setSpacing(0); + + auto headerCaption = new Label(this); + headerCaption->setText("DrumGizmo"); + headerCaption->setAlignment(TextAlignment::center); + headerCaption->resize(width() - 40, 32); + layout.addItem(headerCaption); + + auto headerLine = new VerticalLine(this); + headerLine->resize(width() - 40, vlineSpacing); + layout.addItem(headerLine); + + auto drumkitCaption = new Label(this); + drumkitCaption->setText("Drumkit file:"); + drumkitCaption->resize(width() - 40, 15); + layout.addItem(drumkitCaption); + + auto drumkitFile = new File(this); + drumkitFile->resize(width() - 40, 37); + lineedit = &drumkitFile->lineedit; + CONNECT(&drumkitFile->browseButton, clickNotifier, + this, &DGWindow::kitBrowseClick); + layout.addItem(drumkitFile); + + drumkitFileProgress = new ProgressBar(this); + drumkitFileProgress->resize(width() - 40, 11); + layout.addItem(drumkitFileProgress); + + VerticalLine *l = new VerticalLine(this); + l->resize(width() - 40, vlineSpacing); + layout.addItem(l); + + auto midimapCaption = new Label(this); + midimapCaption->setText("Midimap file:"); + midimapCaption->resize(width() - 40, 15); + layout.addItem(midimapCaption); + + auto midimapFile = new File(this); + midimapFile->resize(width() - 40, 37); + lineedit2 = &midimapFile->lineedit; + CONNECT(&midimapFile->browseButton, clickNotifier, + this, &DGWindow::midimapBrowseClick); + layout.addItem(midimapFile); + + midimapFileProgress = new ProgressBar(this); + midimapFileProgress->resize(width() - 40, 11); + layout.addItem(midimapFileProgress); + + VerticalLine *l2 = new VerticalLine(this); + l2->resize(width() - 40, vlineSpacing); + layout.addItem(l2); + + HumanizeControls* humanizeControls = new HumanizeControls(this); + humanizeControls->resize(80 * 3, 80); + layout.addItem(humanizeControls); + CONNECT(&humanizeControls->velocityCheck, stateChangedNotifier, + this, &DGWindow::velocityCheckClick); + + CONNECT(&humanizeControls->attackKnob, valueChangedNotifier, + this, &DGWindow::attackValueChanged); + + CONNECT(&humanizeControls->falloffKnob, valueChangedNotifier, + this, &DGWindow::falloffValueChanged); + + // Store pointers for PluginGUI access: + velocityCheck = &humanizeControls->velocityCheck; + attackKnob = &humanizeControls->attackKnob; + falloffKnob = &humanizeControls->falloffKnob; + + VerticalLine *l3 = new VerticalLine(this); + l3->resize(width() - 40, vlineSpacing); + layout.addItem(l3); + + Label *lbl_version = new Label(this); + lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. GPLv3 .::."); + lbl_version->resize(width(), 20); + lbl_version->setAlignment(TextAlignment::center); + layout.addItem(lbl_version); + + // Create file browser + fileBrowser = new FileBrowser(this); + fileBrowser->move(0, 0); + fileBrowser->resize(this->width() - 1, this->height() - 1); + fileBrowser->hide(); +} + +void DGWindow::repaintEvent(RepaintEvent* repaintEvent) +{ + if(!visible()) + { + return; + } + + Painter p(*this); + p.drawImageStretched(0,0, back, width(), height()); + p.drawImage(width() - logo.width(), height() - logo.height(), logo); +} + +void DGWindow::attackValueChanged(float value) +{ + ChangeSettingMessage *msg = + new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, + value); + + messageHandler.sendMessage(MSGRCV_ENGINE, msg); + +#ifdef STANDALONE + int i = value * 4; + switch(i) { + case 0: drumkitFileProgress->setState(ProgressBarState::Off); break; + case 1: drumkitFileProgress->setState(ProgressBarState::Blue); break; + case 2: drumkitFileProgress->setState(ProgressBarState::Green); break; + case 3: drumkitFileProgress->setState(ProgressBarState::Red); break; + default: break; + } +#endif +} + +void DGWindow::falloffValueChanged(float value) +{ + ChangeSettingMessage *msg = + new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, + value); + messageHandler.sendMessage(MSGRCV_ENGINE, msg); + +#ifdef STANDALONE + drumkitFileProgress->setProgress(value); +#endif +} + +void DGWindow::velocityCheckClick(bool checked) +{ + ChangeSettingMessage *msg = + new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, + checked); + messageHandler.sendMessage(MSGRCV_ENGINE, msg); +} + +void DGWindow::kitBrowseClick() +{ + std::string path = lineedit->text(); + if(path == "") + { + path = config.lastkit; + } + + if(path == "") + { + path = lineedit2->text(); + } + + fileBrowser->setPath(path); + CONNECT(fileBrowser, fileSelectNotifier, this, &DGWindow::selectKitFile); + fileBrowser->show(); +} + +void DGWindow::midimapBrowseClick() +{ + std::string path = lineedit2->text(); + if(path == "") + { + path = config.lastmidimap; + } + + if(path == "") + { + path = lineedit->text(); + } + + fileBrowser->setPath(path); + CONNECT(fileBrowser, fileSelectNotifier, this, &DGWindow::selectMapFile); + fileBrowser->show(); +} + +void DGWindow::selectKitFile(const std::string& filename) +{ + lineedit->setText(filename); + + fileBrowser->hide(); + + std::string drumkit = lineedit->text(); + + config.lastkit = drumkit; + config.save(); + + drumkitFileProgress->setProgress(0); + drumkitFileProgress->setState(ProgressBarState::Blue); + + LoadDrumKitMessage *msg = new LoadDrumKitMessage(); + msg->drumkitfile = drumkit; + + messageHandler.sendMessage(MSGRCV_ENGINE, msg); +} + +void DGWindow::selectMapFile(const std::string& filename) +{ + lineedit2->setText(filename); + fileBrowser->hide(); + + std::string midimap = lineedit2->text(); + + config.lastmidimap = midimap; + config.save(); + + LoadMidimapMessage *msg = new LoadMidimapMessage(); + msg->midimapfile = midimap; + messageHandler.sendMessage(MSGRCV_ENGINE, msg); +} + + +} // GUI:: diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h new file mode 100644 index 0000000..6eb4226 --- /dev/null +++ b/plugingui/dgwindow.h @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * dgwindow.h + * + * Mon Nov 23 20:30:45 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "window.h" + +#include "label.h" +#include "lineedit.h" +#include "checkbox.h" +#include "button.h" +#include "knob.h" +#include "progressbar.h" +#include "filebrowser.h" +#include "layout.h" + +class MessageHandler; + +namespace GUI { + +class Config; +class Header; +class File; + +class DGWindow : public Window { +public: + DGWindow(MessageHandler& messageHandler, Config& config); + + Header* header; + + File* drumkitFile; + LineEdit* lineedit; + ProgressBar* drumkitFileProgress; + + File* midimapFile; + LineEdit* lineedit2; + ProgressBar* midimapFileProgress; + + // Humanized velocity controls: + CheckBox* velocityCheck; + Knob* attackKnob; + Knob* falloffKnob; + FileBrowser* fileBrowser; + +protected: + // From Widget: + void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + void attackValueChanged(float value); + void falloffValueChanged(float value); + void velocityCheckClick(bool checked); + void kitBrowseClick(); + void midimapBrowseClick(); + void selectKitFile(const std::string& filename); + void selectMapFile(const std::string& filename); + + MessageHandler& messageHandler; + Config& config; + + VBoxLayout layout{this}; + + Image back{":bg.png"}; + Image logo{":logo.png"}; +}; + +} // GUI:: diff --git a/plugingui/directory.cc b/plugingui/directory.cc index 1465c86..08bf59a 100644 --- a/plugingui/directory.cc +++ b/plugingui/directory.cc @@ -28,7 +28,7 @@ #include <dirent.h> #include <stdio.h> -#include <string> +#include <string> #include <algorithm> #include <vector> #include <string.h> @@ -44,14 +44,16 @@ // http://en.wikipedia.org/wiki/Path_(computing) #ifdef WIN32 - #define SEP "\\" +#define SEP "\\" #else - #define SEP "/" +#define SEP "/" #endif +namespace GUI { + Directory::Directory(std::string path) { - setPath(path); + setPath(path); } Directory::~Directory() @@ -60,384 +62,507 @@ Directory::~Directory() std::string Directory::seperator() { - return SEP; + return SEP; } void Directory::setPath(std::string path) { - DEBUG(directory, "Setting path to '%s'\n", path.c_str()); - this->_path = cleanPath(path); - refresh(); + //DEBUG(directory, "Setting path to '%s'\n", path.c_str()); + this->_path = cleanPath(path); + refresh(); } size_t Directory::count() { - return _files.size(); + return _files.size(); } void Directory::refresh() { - _files = listFiles(_path, DIRECTORY_HIDDEN); -// _files = listFiles(_path); + _files = listFiles(_path, DIRECTORY_HIDDEN); + //_files = listFiles(_path); } bool Directory::cd(std::string dir) { - //TODO: Should this return true or false? - if(dir.empty() || dir == ".") return true; - - DEBUG(directory, "Changing to '%s'\n", dir.c_str()); - if(exists(_path + SEP + dir)) { - std::string path = _path + SEP + dir; - setPath(path); - refresh(); - return true; - } else { - return false; - } + //TODO: Should this return true or false? + if(dir.empty() || dir == ".") + { + return true; + } + + //DEBUG(directory, "Changing to '%s'\n", dir.c_str()); + if(exists(_path + SEP + dir)) + { + std::string path = _path + SEP + dir; + setPath(path); + refresh(); + return true; + } + else + { + return false; + } } bool Directory::cdUp() { - return this->cd(".."); + return this->cd(".."); } std::string Directory::path() { - return cleanPath(_path); + return cleanPath(_path); } Directory::EntryList Directory::entryList() { - return _files; + return _files; } #define MAX_FILE_LENGTH 1024 -std::string Directory::cwd() { - char path[MAX_FILE_LENGTH]; - char* c = getcwd(path, MAX_FILE_LENGTH); - - if(c) return c; - else return ""; +std::string Directory::cwd() +{ + char path[MAX_FILE_LENGTH]; + char* c = getcwd(path, MAX_FILE_LENGTH); + + if(c) + { + return c; + } + else + { + return ""; + } } std::string Directory::cleanPath(std::string path) { - DEBUG(directory, "Cleaning path '%s'\n", path.c_str()); - - Directory::Path pathlst = parsePath(path); - return Directory::pathToStr(pathlst); + //DEBUG(directory, "Cleaning path '%s'\n", path.c_str()); + Directory::Path pathlst = parsePath(path); + return Directory::pathToStr(pathlst); } Directory::EntryList Directory::listFiles(std::string path, unsigned char filter) { - DEBUG(directory, "Listing files in '%s'\n", path.c_str()); - - Directory::EntryList entries; - DIR *dir = opendir(path.c_str()); - if(!dir) { - DEBUG(directory, "Couldn't open directory '%s\n", path.c_str()); - return entries; - } - - std::vector<std::string> directories; - std::vector<std::string> files; - - struct dirent *entry; - while((entry = readdir(dir)) != NULL) { - std::string name = entry->d_name; - if(name == ".") continue; - - if(Directory::isRoot(path) && name == "..") continue; - - unsigned char entryinfo = 0; - if(isHidden(path + SEP + name)) { - entryinfo |= DIRECTORY_HIDDEN; - } - - std::string entrypath = path; - entrypath += SEP; - entrypath += entry->d_name; - if(Directory::isDir(entrypath)) { - if(!(entryinfo && filter)) { - if(name == "..") directories.push_back(entry->d_name); - else directories.push_back(std::string(SEP) + entry->d_name); - } - } - else { - int drumkit_suffix_length = strlen(DRUMKIT_SUFFIX); - if((int)name.size() < drumkit_suffix_length) continue; - if(name.substr(name.length() - drumkit_suffix_length, - drumkit_suffix_length) != DRUMKIT_SUFFIX) { - continue; - } - - -// if(!(entryinfo && filter)) { - files.push_back(entry->d_name); -// } - } - } - + DEBUG(directory, "Listing files in '%s'\n", path.c_str()); + + Directory::EntryList entries; + DIR *dir = opendir(path.c_str()); + if(!dir) + { + //DEBUG(directory, "Couldn't open directory '%s\n", path.c_str()); + return entries; + } + + std::vector<std::string> directories; + std::vector<std::string> files; + + struct dirent *entry; + while((entry = readdir(dir)) != nullptr) + { + std::string name = entry->d_name; + if(name == ".") + { + continue; + } + + if(Directory::isRoot(path) && name == "..") + { + continue; + } + + unsigned char entryinfo = 0; + if(isHidden(path + SEP + name)) + { + entryinfo |= DIRECTORY_HIDDEN; + } + + std::string entrypath = path; + entrypath += SEP; + entrypath += entry->d_name; + if(Directory::isDir(entrypath)) + { + if(!(entryinfo && filter)) + { + if(name == "..") + { + directories.push_back(entry->d_name); + } + else + { + directories.push_back(std::string(SEP) + entry->d_name); + } + } + } + else + { + int drumkit_suffix_length = strlen(DRUMKIT_SUFFIX); + if((int)name.size() < drumkit_suffix_length) + { + continue; + } + + if(name.substr(name.length() - drumkit_suffix_length, + drumkit_suffix_length) != DRUMKIT_SUFFIX) + { + continue; + } + + + //if(!(entryinfo && filter)) { + files.push_back(entry->d_name); + //} + } + } #ifdef WIN32 - DEBUG(directory, "Root is %s\n", Directory::root(path).c_str()); - DEBUG(directory, "Current path %s is root? %d", path.c_str(), Directory::isRoot(path)); -if(Directory::isRoot(path)) entries.push_back(".."); + //DEBUG(directory, "Root is %s\n", Directory::root(path).c_str()); + //DEBUG(directory, "Current path %s is root? %d", path.c_str(), + // Directory::isRoot(path)); + if(Directory::isRoot(path)) + { + entries.push_back(".."); + } #endif - // sort - for(int x = 0; x < (int)directories.size(); x++) { - for(int y = 0; y < (int)directories.size(); y++) { - if(directories[x] < directories[y]) { - - std::string tmp = directories[x]; - directories[x] = directories[y]; - directories[y] = tmp; - } - } - } - - for(int x = 0; x < (int)files.size(); x++) { - for(int y = 0; y < (int)files.size(); y++) { - if(files[x] < files[y]) { - - std::string tmp = files[x]; - files[x] = files[y]; - files[y] = tmp; - } - } - } - - - for(std::vector<std::string>::iterator it = directories.begin(); it != directories.end(); it++) { - entries.push_back(*it); - } - - for(std::vector<std::string>::iterator it = files.begin(); it != files.end(); it++) { - entries.push_back(*it); - } - - - return entries; + // sort + for(int x = 0; x < (int)directories.size(); x++) + { + for(int y = 0; y < (int)directories.size(); y++) + { + if(directories[x] < directories[y]) + { + std::string tmp = directories[x]; + directories[x] = directories[y]; + directories[y] = tmp; + } + } + } + + for(int x = 0; x < (int)files.size(); x++) + { + for(int y = 0; y < (int)files.size(); y++) + { + if(files[x] < files[y]) + { + std::string tmp = files[x]; + files[x] = files[y]; + files[y] = tmp; + } + } + } + + + for(auto directory : directories) + { + entries.push_back(directory); + } + + for(auto file : files) + { + entries.push_back(file); + } + + closedir(dir); + return entries; } bool Directory::isRoot(std::string path) { #ifdef WIN32 - std::transform(path.begin(), path.end(), path.begin(), ::tolower); - std::string root_str = Directory::root(path); - std::transform(root_str.begin(), root_str.end(), root_str.begin(), ::tolower); - // TODO: This is not a correct root calculation, but works with partitions - if(path.size() == 2) { - if(path == root_str) return true; - else return false; - } else if (path.size() == 3) { - if(path == root_str + SEP) return true; - return false; - } else { - return false; - } + std::transform(path.begin(), path.end(), path.begin(), ::tolower); + std::string root_str = Directory::root(path); + std::transform(root_str.begin(), root_str.end(), root_str.begin(), ::tolower); + + // TODO: This is not a correct root calculation, but works with partitions + if(path.size() == 2) + { + if(path == root_str) + { + return true; + } + else + { + return false; + } + } + else + { + if (path.size() == 3) + { + if(path == root_str + SEP) + { + return true; + } + return false; + } + else + { + return false; + } + } #else - if(path == SEP) return true; - else return false; + if(path == SEP) + { + return true; + } + else + { + return false; + } #endif } std::string Directory::root() { - return root(cwd()); + return root(cwd()); } std::string Directory::root(std::string path) { #ifdef WIN32 - if(path.size() < 2) { - return "c:"; // just something default when input is bad - } else { - return path.substr(0, 2); - } + if(path.size() < 2) + { + return "c:"; // just something default when input is bad + } + else + { + return path.substr(0, 2); + } #else - return SEP; + return SEP; #endif } Directory::DriveList Directory::drives() { - Directory::DriveList drives; + Directory::DriveList drives; #ifdef WIN32 - unsigned int d = GetLogicalDrives(); - for(int i = 0; i < 32; i++) { - if(d & (1 << i)) { - drive_t drive; - char name[] = "x:"; - name[0] = i + 'a'; - - drive.name = name; - drive.number = i; - drives.push_back(drive); - } - } + unsigned int d = GetLogicalDrives(); + for(int i = 0; i < 32; ++i) + { + if(d & (1 << i)) + { + drive_t drive; + char name[] = "x:"; + name[0] = i + 'a'; + + drive.name = name; + drive.number = i; + drives.push_back(drive); + } + } #endif - return drives; + return drives; } bool Directory::isDir() { - return isDir(_path); + return isDir(_path); } bool Directory::isDir(std::string path) { - DEBUG(directory, "Is '%s' a directory?\n", path.c_str()); - struct stat st; - if(stat(path.c_str(), &st) == 0) { - if((st.st_mode & S_IFDIR) != 0) { - DEBUG(directory, "\t...yes!\n"); - return true; - } - } - DEBUG(directory, "\t...no!\n"); - return false; + //DEBUG(directory, "Is '%s' a directory?\n", path.c_str()); + struct stat st; + if(stat(path.c_str(), &st) == 0) + { + if((st.st_mode & S_IFDIR) != 0) + { + //DEBUG(directory, "\t...yes!\n"); + return true; + } + } + //DEBUG(directory, "\t...no!\n"); + return false; } bool Directory::fileExists(std::string filename) { - return !isDir(_path + SEP + filename); + return !isDir(_path + SEP + filename); } bool Directory::exists(std::string path) { - struct stat st; - if(stat(path.c_str(), &st) == 0) { - return true; - } else { - return false; - } + struct stat st; + if(stat(path.c_str(), &st) == 0) + { + return true; + } + else + { + return false; + } } -bool Directory::isHidden(std::string path) +bool Directory::isHidden(std::string path) { - DEBUG(directory, "Is '%s' hidden?\n", path.c_str()); + //DEBUG(directory, "Is '%s' hidden?\n", path.c_str()); #ifdef WIN32 - // We dont want to filter out '..' pointing to root of a partition - unsigned pos = path.find_last_of("/\\"); - std::string entry = path.substr(pos+1); - if(entry == "..") { - return false; - } - - DWORD fattribs = GetFileAttributes(path.c_str()); - if(fattribs & FILE_ATTRIBUTE_HIDDEN) { - DEBUG(directory, "\t...yes!\n"); - return true; - } - else if(fattribs & FILE_ATTRIBUTE_SYSTEM) { - DEBUG(directory, "\t...yes!\n"); - return true; - } - else { - DEBUG(directory, "\t...no!\n"); - return false; - } + // We dont want to filter out '..' pointing to root of a partition + unsigned pos = path.find_last_of("/\\"); + std::string entry = path.substr(pos+1); + if(entry == "..") + { + return false; + } + + DWORD fattribs = GetFileAttributes(path.c_str()); + if(fattribs & FILE_ATTRIBUTE_HIDDEN) + { + //DEBUG(directory, "\t...yes!\n"); + return true; + } + else + { + if(fattribs & FILE_ATTRIBUTE_SYSTEM) + { + //DEBUG(directory, "\t...yes!\n"); + return true; + } + else + { + //DEBUG(directory, "\t...no!\n"); + return false; + } + } #else - unsigned pos = path.find_last_of("/\\"); - std::string entry = path.substr(pos+1); - if(entry.size() > 1 && - entry.at(0) == '.' && - entry.at(1) != '.') { - DEBUG(directory, "\t...yes!\n"); - return true; - } - else { - DEBUG(directory, "\t...no!\n"); - return false; - } + unsigned pos = path.find_last_of("/\\"); + std::string entry = path.substr(pos+1); + if(entry.size() > 1 && + entry.at(0) == '.' && + entry.at(1) != '.') + { + //DEBUG(directory, "\t...yes!\n"); + return true; + } + else + { + //DEBUG(directory, "\t...no!\n"); + return false; + } #endif } Directory::Path Directory::parsePath(std::string path_str) { - //TODO: Handle "." input and propably other special cases - - DEBUG(directory, "Parsing path '%s'", path_str.c_str()); - Directory::Path path; - - std::string current_char; - std::string prev_char; - std::string dir; - for(size_t c = 0; c < path_str.size(); c++) { - current_char = path_str.at(c); - - if(current_char == SEP) { - if(prev_char == SEP) { - dir.clear(); - prev_char = current_char; - continue; - } else if(prev_char == ".") { - prev_char = current_char; - continue; - } - - if(!dir.empty()) path.push_back(dir); - dir.clear(); - continue; - } else if(current_char == ".") { - if(prev_char == ".") { - dir.clear(); - if(!path.empty()) path.pop_back(); - continue; - } - } - - dir += current_char; - prev_char = current_char; - } - - if(!dir.empty()) path.push_back(dir); - - return path; + //TODO: Handle "." input and propably other special cases + + //DEBUG(directory, "Parsing path '%s'", path_str.c_str()); + Directory::Path path; + + std::string current_char; + std::string prev_char; + std::string dir; + for(size_t c = 0; c < path_str.size(); ++c) + { + current_char = path_str.at(c); + + if(current_char == SEP) + { + if(prev_char == SEP) + { + dir.clear(); + prev_char = current_char; + continue; + } + else + { + if(prev_char == ".") + { + prev_char = current_char; + continue; + } + } + if(!dir.empty()) + { + path.push_back(dir); + } + dir.clear(); + continue; + } + else + { + if(current_char == ".") + { + if(prev_char == ".") + { + dir.clear(); + if(!path.empty()) + { + path.pop_back(); + } + continue; + } + } + } + dir += current_char; + prev_char = current_char; + } + + if(!dir.empty()) + { + path.push_back(dir); + } + + return path; } std::string Directory::pathToStr(Directory::Path& path) { - std::string cleaned_path; - DEBUG(directory, "Number of directories in path is %d\n", (int)path.size()); + std::string cleaned_path; + //DEBUG(directory, "Number of directories in path is %d\n", (int)path.size()); - for(Directory::Path::iterator it = path.begin(); - it != path.end(); it++) { - std::string dir = *it; - DEBUG(directory, "\tDir '%s'\n", dir.c_str()); + for(auto it = path.begin(); it != path.end(); ++it) + { + std::string dir = *it; + //DEBUG(directory, "\tDir '%s'\n", dir.c_str()); #ifdef WIN32 - if(it != path.begin()) cleaned_path += SEP; - cleaned_path += dir; + if(it != path.begin()) + { + cleaned_path += SEP; + } + cleaned_path += dir; #else - cleaned_path += SEP + dir; + cleaned_path += SEP + dir; #endif - } + } - DEBUG(directory, "Cleaned path '%s'\n", cleaned_path.c_str()); + //DEBUG(directory, "Cleaned path '%s'\n", cleaned_path.c_str()); - if(cleaned_path.empty()) { - cleaned_path = Directory::root(); + if(cleaned_path.empty()) + { + cleaned_path = Directory::root(); #ifdef WIN32 - cleaned_path += SEP; -#endif - } + cleaned_path += SEP; +#endif + } #ifdef WIN32 - if(cleaned_path.size() == 2) cleaned_path += SEP; + if(cleaned_path.size() == 2) + { + cleaned_path += SEP; + } #endif - return cleaned_path; + return cleaned_path; } std::string Directory::pathDirectory(std::string filepath) { - if(Directory::isDir(filepath)) return filepath; - - Directory::Path path = parsePath(filepath); - if(path.size() > 0) path.pop_back(); - - return Directory::pathToStr(path); + if(Directory::isDir(filepath)) + { + return filepath; + } + + Directory::Path path = parsePath(filepath); + if(path.size() > 0) + { + path.pop_back(); + } + + return Directory::pathToStr(path); } + +} // GUI:: diff --git a/plugingui/directory.h b/plugingui/directory.h index 04ed3e7..a3f0059 100644 --- a/plugingui/directory.h +++ b/plugingui/directory.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_DIRECTORY_H__ -#define __DRUMGIZMO_DIRECTORY_H__ +#pragma once #include <string> #include <list> @@ -38,56 +37,57 @@ #define DIRECTORY_HIDDEN 1 +namespace GUI { + class Directory { +public: + typedef struct drive { + int number; + std::string name; + } drive_t; + + typedef std::list<std::string> EntryList; + typedef std::list<drive> DriveList; + + Directory(std::string path); + ~Directory(); + + std::string seperator(); + + size_t count(); + void refresh(); + std::string path(); + bool cdUp(); + bool cd(std::string dir); + bool isDir(); + void setPath(std::string path); + bool fileExists(std::string file); + + // Add filter, ie. directories or files only + EntryList entryList(); + + //void setSorting(); + + static std::string cwd(); + static std::string root(); + static std::string root(std::string path); + static std::string cleanPath(std::string path); + static Directory::EntryList listFiles(std::string path, unsigned char filter = 0); + static bool isRoot(std::string path); + static Directory::DriveList drives(); + static bool isDir(std::string path); + static bool isHidden(std::string entry); + static bool exists(std::string path); + static std::string pathDirectory(std::string filepath); + +private: + std::string _path; + EntryList _files; + DriveList _drives; - public: - typedef struct drive { - int number; - std::string name; - } drive_t; - - typedef std::list<std::string> EntryList; - typedef std::list<drive> DriveList; - - Directory(std::string path); - ~Directory(); - - std::string seperator(); - - size_t count(); - void refresh(); - std::string path(); - bool cdUp(); - bool cd(std::string dir); - bool isDir(); - void setPath(std::string path); - bool fileExists(std::string file); - - // Add filter, ie. directories or files only - EntryList entryList(); - - //void setSorting(); - - static std::string cwd(); - static std::string root(); - static std::string root(std::string path); - static std::string cleanPath(std::string path); - static Directory::EntryList listFiles(std::string path, unsigned char filter = 0); - static bool isRoot(std::string path); - static Directory::DriveList drives(); - static bool isDir(std::string path); - static bool isHidden(std::string entry); - static bool exists(std::string path); - static std::string pathDirectory(std::string filepath); - - private: - std::string _path; - EntryList _files; - DriveList _drives; - - typedef std::list<std::string> Path; - static Path parsePath(std::string path); - static std::string pathToStr(Path &path); + typedef std::list<std::string> Path; + static Path parsePath(std::string path); + static std::string pathToStr(Path &path); }; -#endif/*__DRUMGIZMO_DIRECTORY_H__*/ +} // GUI:: diff --git a/plugingui/eventhandler.cc b/plugingui/eventhandler.cc index cec5fab..9a6fa8d 100644 --- a/plugingui/eventhandler.cc +++ b/plugingui/eventhandler.cc @@ -29,166 +29,237 @@ #include "window.h" #include "painter.h" -GUI::EventHandler::EventHandler(GUI::NativeWindow *n, GUI::Window *w) -{ - native = n; - window = w; +namespace GUI { - last_click = 0; - last_was_dbl_click = false; -} +EventHandler::EventHandler(NativeWindow& nativeWindow, Window& window) + : window(window) + , nativeWindow(nativeWindow) +// , last_click(0) + , lastWasDoubleClick(false) +{} -bool GUI::EventHandler::hasEvent() +bool EventHandler::hasEvent() { - return native->hasEvent(); + return nativeWindow.hasEvent(); } -GUI::Event *GUI::EventHandler::getNextEvent() +Event *EventHandler::getNextEvent() { - return native->getNextEvent(); + return nativeWindow.getNextEvent(); } -void GUI::EventHandler::registerCloseHandler(void (*handler)(void *), void *ptr) +Event *EventHandler::peekNextEvent() { - this->closeHandler = handler; - this->closeHandlerPtr = ptr; + return nativeWindow.peekNextEvent(); } -void GUI::EventHandler::processEvents() +void EventHandler::processEvents() { - while(hasEvent()) { - Painter p(window); // Make sure we only redraw buffer one time. - - Event *event = getNextEvent(); - - if(event == NULL) continue; - - // Widget *widget = gctx->widgets[event->window_id]; - switch(event->type()) { - case Event::Repaint: - // window->repaint((RepaintEvent*)event); - window->redraw(); - break; - case Event::Resize: - { - // window->repaint((RepaintEvent*)event) - ResizeEvent *re = (ResizeEvent*)event; - if(re->width != window->width() || re->height != window->height()) { - window->resized(re->width, re->height); - //window->repaint_r(NULL); - } - } - break; - case Event::MouseMove: - { - MouseMoveEvent *me = (MouseMoveEvent*)event; - - Widget *w = window->find(me->x, me->y); - Widget *oldw = window->mouseFocus(); - if(w != oldw) { - // Send focus leave to oldw - if(oldw) oldw->mouseLeaveEvent(); - // Send focus enter to w - if(w) w->mouseEnterEvent(); - - window->setMouseFocus(w); - } - - if(window->buttonDownFocus()) { - Widget *w = window->buttonDownFocus(); - /* - if(me->x < w->x()) me->x = w->x(); - if(me->x > w->x() + w->width()) me->x = w->x() + w->width(); - if(me->y < w->y()) me->y = w->y(); - if(me->y > w->y() + w->height()) me->y = w->y() + w->height(); - */ - me->x -= w->windowX(); - me->y -= w->windowY(); - - window->buttonDownFocus()->mouseMoveEvent(me); - break; - } - - if(w) { - me->x -= w->windowX(); - me->y -= w->windowY(); - w->mouseMoveEvent(me); - } - } - break; - case Event::Button: - { - if(last_was_dbl_click) { - last_was_dbl_click = false; - continue; - } - ButtonEvent *be = (ButtonEvent *)event; - - last_was_dbl_click = be->doubleclick; - - Widget *w = window->find(be->x, be->y); - - if(window->buttonDownFocus()) { - if(be->direction == -1) { - Widget *w = window->buttonDownFocus(); - /* - if(be->x < w->x()) be->x = w->x(); - if(be->x > w->x() + w->width()) be->x = w->x() + w->width(); - if(be->y < w->y()) be->y = w->y(); - if(be->y > w->y() + w->height()) be->y = w->y() + w->height(); - */ - be->x -= w->windowX(); - be->y -= w->windowY(); - - w->buttonEvent(be); - break; - } else { - window->setButtonDownFocus(NULL); - } - } - - if(w) { - be->x -= w->windowX(); - be->y -= w->windowY(); - - w->buttonEvent(be); - - if(be->direction == 1) { - if(w->catchMouse()) window->setButtonDownFocus(w); - } - - if(w->isFocusable()) window->setKeyboardFocus(w); - } - } - break; - case Event::Scroll: - { - ScrollEvent *se = (ScrollEvent *)event; - - Widget *w = window->find(se->x, se->y); - - //printf("scroller (%d,%d) %p\n", se->x, se->y, w); - - if(w) { - se->x -= w->windowX(); - se->y -= w->windowY(); - - w->scrollEvent(se); - } - } - break; - case Event::Key: - // window->key((KeyEvent*)event); - // lineedit->keyEvent((KeyEvent*)event); - if(window->keyboardFocus()) - window->keyboardFocus()->keyEvent((KeyEvent*)event); - break; - case Event::Close: - if(closeHandler) closeHandler(closeHandlerPtr); - //delete window; - //window = NULL; - break; - } - delete event; - } + while(hasEvent()) + { + Painter p(window); // Make sure we only redraw buffer one time. + + auto event = getNextEvent(); + + if(event == nullptr) + { + continue; + } + + switch(event->type()) { + case EventType::repaint: + window.redraw(); + break; + + case EventType::resize: + { + while(true) + { + if(!hasEvent()) + { + break; + } + + auto peekEvent = peekNextEvent(); + if(!peekEvent || (peekEvent->type() != EventType::resize)) + { + break; + } + + event = getNextEvent(); + } + + auto resizeEvent = static_cast<ResizeEvent*>(event); + if((resizeEvent->width != window.width()) || + (resizeEvent->height != window.height())) + { + window.resized(resizeEvent->width, resizeEvent->height); + } + } + break; + + case EventType::mouseMove: + { + while(true) + { + if(!hasEvent()) + { + break; + } + + auto peekEvent = peekNextEvent(); + if(!peekEvent || (peekEvent->type() != EventType::mouseMove)) + { + break; + } + + event = getNextEvent(); + } + + auto moveEvent = static_cast<MouseMoveEvent*>(event); + + auto widget = window.find(moveEvent->x, moveEvent->y); + auto oldwidget = window.mouseFocus(); + if(widget != oldwidget) + { + // Send focus leave to oldwidget + if(oldwidget) + { + oldwidget->mouseLeaveEvent(); + } + + // Send focus enter to widget + if(widget) + { + widget->mouseEnterEvent(); + } + + window.setMouseFocus(widget); + } + + if(window.buttonDownFocus()) + { + auto widget = window.buttonDownFocus(); + moveEvent->x -= widget->windowX(); + moveEvent->y -= widget->windowY(); + + window.buttonDownFocus()->mouseMoveEvent(moveEvent); + break; + } + + if(widget) + { + moveEvent->x -= widget->windowX(); + moveEvent->y -= widget->windowY(); + widget->mouseMoveEvent(moveEvent); + } + } + break; + + case EventType::button: + { + if(lastWasDoubleClick) + { + lastWasDoubleClick = false; + continue; + } + + auto buttonEvent = static_cast<ButtonEvent*>(event); + + lastWasDoubleClick = buttonEvent->doubleClick; + + auto widget = window.find(buttonEvent->x, buttonEvent->y); + + if(window.buttonDownFocus()) + { + if(buttonEvent->direction == Direction::up) + { + auto widget = window.buttonDownFocus(); + buttonEvent->x -= widget->windowX(); + buttonEvent->y -= widget->windowY(); + + widget->buttonEvent(buttonEvent); + window.setButtonDownFocus(nullptr); + break; + } + } + + if(widget) + { + buttonEvent->x -= widget->windowX(); + buttonEvent->y -= widget->windowY(); + + widget->buttonEvent(buttonEvent); + + if((buttonEvent->direction == Direction::down) && + widget->catchMouse()) + { + window.setButtonDownFocus(widget); + } + + if(widget->isFocusable()) + { + window.setKeyboardFocus(widget); + } + } + } + break; + + case EventType::scroll: + { + int delta = 0; + while(true) + { + if(!hasEvent()) + { + break; + } + + auto peekEvent = peekNextEvent(); + if(!peekEvent || (peekEvent->type() != EventType::scroll)) + { + break; + } + + auto scrollEvent = static_cast<ScrollEvent*>(event); + delta += scrollEvent->delta; + event = getNextEvent(); + } + + auto scrollEvent = static_cast<ScrollEvent*>(event); + scrollEvent->delta += delta; + + auto widget = window.find(scrollEvent->x, scrollEvent->y); + if(widget) + { + scrollEvent->x -= widget->windowX(); + scrollEvent->y -= widget->windowY(); + + widget->scrollEvent(scrollEvent); + } + } + break; + + case EventType::key: + { + + // TODO: Filter out multiple arrow events. + + auto keyEvent = static_cast<KeyEvent*>(event); + if(window.keyboardFocus()) + { + window.keyboardFocus()->keyEvent(keyEvent); + } + } + break; + + case EventType::close: + closeNotifier(); + break; + } + + delete event; + } } + +} // GUI:: diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h index 028418d..b011f87 100644 --- a/plugingui/eventhandler.h +++ b/plugingui/eventhandler.h @@ -24,39 +24,42 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_EVENTHANDLER_H__ -#define __DRUMGIZMO_EVENTHANDLER_H__ +#pragma once #include "guievent.h" #include "nativewindow.h" -//#include "window.h" +#include "notifier.h" namespace GUI { + class Window; class EventHandler { public: - EventHandler(NativeWindow *native, Window *window); + EventHandler(NativeWindow& nativeWindow, Window& window); - void processEvents(); + //! \brief Process all events currently in the event queue. + void processEvents(); - bool hasEvent(); - Event *getNextEvent(); + //! \brief Query if any events are currently in the event queue. + bool hasEvent(); - void registerCloseHandler(void (*handler)(void *), void *ptr); + //! \brief Get a single event from the event queue. + //! \return A pointer to the event or nullptr if there are none. + Event *getNextEvent(); -private: - Window *window; - int last_click; - void (*closeHandler)(void *); - void *closeHandlerPtr; + //! \brief Get a single event from the event queue without popping it. + //! \return A pointer to the event or nullptr if there are none. + Event *peekNextEvent(); - // Used to ignore mouse button release after a double click. - bool last_was_dbl_click; + Notifier<> closeNotifier; - NativeWindow *native; -}; +private: + Window& window; + NativeWindow& nativeWindow; + // Used to ignore mouse button release after a double click. + bool lastWasDoubleClick; }; -#endif/*__DRUMGIZMO_EVENTHANDLER_H__*/ +} // GUI:: diff --git a/plugingui/filebrowser.cc b/plugingui/filebrowser.cc index f025c25..6313415 100644 --- a/plugingui/filebrowser.cc +++ b/plugingui/filebrowser.cc @@ -45,224 +45,216 @@ #include <direct.h> #endif -struct GUI::FileBrowser::private_data { - GUI::LineEdit *lineedit; - GUI::ListBox *listbox; - void (*filesel_handler)(void *, std::string); - void *ptr; - Directory *dir; +namespace GUI { + +FileBrowser::FileBrowser(Widget *parent) + : Widget(parent) + , dir(Directory::cwd()) + , lbl_path(this) + , lineedit(this) + , listbox(this) + , btn_sel(this) + , btn_esc(this) + , back(":bg.png") +{ #ifdef WIN32 - bool above_root; - bool in_root; + above_root = false; #endif -}; -static void cancel(void *ptr) -{ - GUI::FileBrowser *fp = (GUI::FileBrowser *)ptr; - fp->hide(); -} - -static void changeDir(void *ptr) -{ - struct GUI::FileBrowser::private_data *prv = - (struct GUI::FileBrowser::private_data *) ptr; - - GUI::ListBox *lb = prv->listbox; - GUI::LineEdit *le = prv->lineedit; - std::string value = lb->selectedValue(); - Directory* dir = prv->dir; - -// if(!Directory::isDir(dir->path() + dir->seperator())) { -// return; -// } + lbl_path.setText("Path:"); - lb->clear(); - - INFO(filebrowser, "Changing path to '%s'\n", - (dir->path() + dir->seperator() + value).c_str()); - -#ifdef WIN32 - if(prv->above_root && !value.empty()) { - dir->setPath(value + dir->seperator()); - value.clear(); - prv->above_root = false; - } -#endif + //lineedit.setReadOnly(true); + CONNECT(&lineedit, enterPressedNotifier, this, &FileBrowser::handleKeyEvent); + CONNECT(&listbox, selectionNotifier, + this, &FileBrowser::listSelectionChanged); - if(value.empty() && !dir->isDir() && Directory::exists(dir->path())) { - DEBUG(filebrowser, "Selecting file '%s'\n", dir->path().c_str()); - if(prv->filesel_handler) prv->filesel_handler(prv->ptr, dir->path().c_str()); - return; - } + btn_sel.setText("Select"); + CONNECT(&btn_sel, clickNotifier, this, &FileBrowser::selectButtonClicked); - if(!value.empty() && dir->fileExists(value)) { - std::string file = dir->path() + dir->seperator() + value; - DEBUG(filebrowser, "Selecting file '%s'\n", file.c_str()); - if(prv->filesel_handler) prv->filesel_handler(prv->ptr, file); - return; - } + btn_esc.setText("Cancel"); + CONNECT(&btn_esc, clickNotifier, this, &FileBrowser::cancelButtonClicked); - std::vector<GUI::ListBoxBasic::Item> items; + changeDir(); +} -#ifdef WIN32 - if(Directory::isRoot(dir->path()) && value == "..") { - DEBUG(filebrowser, "Showing partitions...\n"); - Directory::DriveList entries = dir->drives(); - for(Directory::DriveList::iterator it = entries.begin(); - it != entries.end(); it++) { - GUI::ListBoxBasic::Item item; - std::string name = (*it).name; - item.name = name; - item.value = name; - items.push_back(item); - } - prv->above_root = true; - } else { -#endif - - if(!value.empty() && !dir->cd(value)) { - DEBUG(filebrowser, "Error changing to '%s'\n", - (dir->path() + dir->seperator() + value).c_str()); - return; - } - - Directory::EntryList entries = dir->entryList(); - - if(entries.empty()) { - dir->cdUp(); - entries = dir->entryList(); - } - - DEBUG(filebrowser, "Setting path of lineedit to %s\n", - dir->path().c_str()); - le->setText(dir->path()); - - for(Directory::EntryList::iterator it = entries.begin(); - it != entries.end(); it++) { - GUI::ListBoxBasic::Item item; - std::string name = *it; - item.name = name; - item.value = name; - items.push_back(item); - } -#ifdef WIN32 - } -#endif - lb->addItems(items); +FileBrowser::~FileBrowser() +{ } -static void handleKeyEvent(void *ptr) { - struct GUI::FileBrowser::private_data *prv = - (struct GUI::FileBrowser::private_data *) ptr; - - GUI::ListBox *lb = prv->listbox; - lb->clearSelectedValue(); - GUI::LineEdit *le = prv->lineedit; - - std::string value = le->text(); - if(value.size() > 1 && value[0] == '@') { - DEBUG(filebrowser, "Selecting ref-file '%s'\n", value.c_str()); - if(prv->filesel_handler) { - prv->filesel_handler(prv->ptr, value); - } - return; - } - - prv->dir->setPath(le->text()); - changeDir(ptr); +void FileBrowser::setPath(const std::string& path) +{ + INFO(filebrowser, "Setting path to '%s'\n", path.c_str()); + + if(!path.empty()) + { + dir.setPath(Directory::pathDirectory(path)); + } + else + { + dir.setPath(Directory::pathDirectory(Directory::cwd())); + } + + listbox.clear(); + + changeDir(); } -GUI::FileBrowser::FileBrowser(GUI::Widget *parent) - : GUI::Widget(parent), - lbl_path(this), lineedit(this), listbox(this), btn_sel(this), btn_esc(this), - back(":bg.png") +void FileBrowser::resize(int w, int h) { - prv = new struct GUI::FileBrowser::private_data(); - prv->filesel_handler = NULL; + Widget::resize(w,h); - prv->dir = new Directory(Directory::cwd()); -#ifdef WIN32 - prv->above_root = false; -#endif + int offset = 0; + int brd = 5; // border + int btn_h = 30; - lbl_path.setText("Path:"); + offset += brd; -// lineedit.setReadOnly(true); - prv->lineedit = &lineedit; - prv->lineedit->registerEnterPressedHandler(handleKeyEvent, prv); + lbl_path.move(0, offset); + lineedit.move(60, offset); - prv->listbox = &listbox; - listbox.registerSelectHandler(changeDir, prv); + offset += btn_h; - btn_sel.setText("Select"); - btn_sel.registerClickHandler(changeDir, prv); + lbl_path.resize(60, btn_h); + lineedit.resize(w - 60 - brd, btn_h); - btn_esc.setText("Cancel"); - btn_esc.registerClickHandler(cancel, this); + offset += brd; - changeDir(prv); + listbox.move(brd, offset); + listbox.resize(w - 1 - 2*brd, h - btn_h - 2*brd - offset); - resize(200, 190); + btn_esc.move(brd, h - btn_h - brd); + btn_esc.resize((w - 1 - 2*brd) / 2 - brd / 2, btn_h); + + btn_sel.move(brd + w / 2 - brd / 2, h - btn_h - brd); + btn_sel.resize((w - 1 - 2*brd) / 2, btn_h); } -GUI::FileBrowser::~FileBrowser() +void FileBrowser::repaintEvent(RepaintEvent* repaintEvent) { - // delete prv->listbox; - delete prv; + Painter p(*this); + p.drawImageStretched(0,0, back, width(), height()); } -void GUI::FileBrowser::setPath(std::string path) +void FileBrowser::listSelectionChanged() { - INFO(filebrowser, "Setting path to '%s'\n", path.c_str()); - if(path.empty()) path = Directory::cwd(); + changeDir(); +} - prv->dir->setPath(Directory::pathDirectory(path)); - prv->listbox->clear(); +void FileBrowser::selectButtonClicked() +{ + changeDir(); +} - changeDir(prv); +void FileBrowser::cancelButtonClicked() +{ + cancel(); } -void GUI::FileBrowser::resize(int w, int h) +void FileBrowser::handleKeyEvent() { - GUI::Widget::resize(w,h); + listbox.clearSelectedValue(); + + std::string value = lineedit.text(); + if((value.size() > 1) && (value[0] == '@')) + { + DEBUG(filebrowser, "Selecting ref-file '%s'\n", value.c_str()); + fileSelectNotifier(value); + return; + } + + dir.setPath(lineedit.text()); + changeDir(); +} - int offset = 0; - int brd = 5; // border - int btn_h = 30; +void FileBrowser::cancel() +{ + hide(); +} - offset += brd; +void FileBrowser::changeDir() +{ + std::string value = listbox.selectedValue(); - lbl_path.move(0, offset); - lineedit.move(60, offset); +// if(!Directory::isDir(dir->path() + dir->seperator())) +// { +// return; +// } - offset += btn_h; + listbox.clear(); - lbl_path.resize(60, btn_h); - lineedit.resize(w - 60 - brd, btn_h); + INFO(filebrowser, "Changing path to '%s'\n", + (dir.path() + dir.seperator() + value).c_str()); - offset += brd; +#ifdef WIN32 + if(above_root && !value.empty()) + { + dir.setPath(value + dir.seperator()); + value.clear(); + above_root = false; + } +#endif - listbox.move(brd, offset); - listbox.resize(w - 1 - 2*brd, h - btn_h - 2*brd - offset); + if(value.empty() && !dir.isDir() && Directory::exists(dir.path())) + { + DEBUG(filebrowser, "Selecting file '%s'\n", dir.path().c_str()); + fileSelectNotifier(dir.path()); + return; + } - btn_esc.move(brd, h - btn_h - brd); - btn_esc.resize((w - 1 - 2*brd) / 2 - brd / 2, btn_h); + if(!value.empty() && dir.fileExists(value)) + { + std::string file = dir.path() + dir.seperator() + value; + DEBUG(filebrowser, "Selecting file '%s'\n", file.c_str()); + fileSelectNotifier(file); + return; + } - btn_sel.move(brd + w / 2 - brd / 2, h - btn_h - brd); - btn_sel.resize((w - 1 - 2*brd) / 2, btn_h); -} + std::vector<ListBoxBasic::Item> items; -void GUI::FileBrowser::registerFileSelectHandler(void (*handler)(void *, - std::string), - void *ptr) -{ - prv->filesel_handler = handler; - prv->ptr = ptr; +#ifdef WIN32 + if(Directory::isRoot(dir.path()) && (value == "..")) + { + DEBUG(filebrowser, "Showing partitions...\n"); + for(auto drive : dir.drives()) + { + ListBoxBasic::Item item; + item.name = drive.name; + item.value = drive.name; + items.push_back(item); + } + above_root = true; + } + else +#endif + { + if(!value.empty() && !dir.cd(value)) + { + DEBUG(filebrowser, "Error changing to '%s'\n", + (dir.path() + dir.seperator() + value).c_str()); + return; + } + + Directory::EntryList entries = dir.entryList(); + + if(entries.empty()) + { + dir.cdUp(); + entries = dir.entryList(); + } + + DEBUG(filebrowser, "Setting path of lineedit to %s\n", dir.path().c_str()); + lineedit.setText(dir.path()); + + for(auto entry : entries) + { + ListBoxBasic::Item item; + item.name = entry; + item.value = entry; + items.push_back(item); + } + } + + listbox.addItems(items); } -void GUI::FileBrowser::repaintEvent(GUI::RepaintEvent *e) -{ - Painter p(this); - p.drawImageStretched(0,0, &back, width(), height()); -} +} // GUI:: diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h index 6583b53..bd9dd8e 100644 --- a/plugingui/filebrowser.h +++ b/plugingui/filebrowser.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_FILEBROWSER_H__ -#define __DRUMGIZMO_FILEBROWSER_H__ +#pragma once #include "widget.h" @@ -35,41 +34,48 @@ #include "label.h" #include "image.h" #include "directory.h" +#include "notifier.h" namespace GUI { class FileBrowser : public Widget { public: - struct private_data; + FileBrowser(Widget *parent); + ~FileBrowser(); - FileBrowser(Widget *parent); - ~FileBrowser(); + void setPath(const std::string& path); - void setPath(std::string path); + Notifier<const std::string&> fileSelectNotifier; // (const std::string& path) - bool isFocusable() { return true; } - - void registerFileSelectHandler(void (*handler)(void *, std::string), - void *ptr); - - virtual void repaintEvent(RepaintEvent *e); - - virtual void resize(int w, int h); + // From Widget: + bool isFocusable() override { return true; } + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void resize(int w, int h) override; private: - struct private_data *prv; + void listSelectionChanged(); + void selectButtonClicked(); + void cancelButtonClicked(); + void handleKeyEvent(); - GUI::Label lbl_path; - GUI::LineEdit lineedit; + Directory dir; +#ifdef WIN32 + bool above_root; + bool in_root; +#endif - GUI::ListBox listbox; + void cancel(); + void changeDir(); - GUI::Button btn_sel; - GUI::Button btn_esc; + Label lbl_path; - Image back; -}; + LineEdit lineedit; + ListBox listbox; + + Button btn_sel; + Button btn_esc; + Image back; }; -#endif/*__DRUMGIZMO_FILEBROWSER_H__*/ +} // GUI:: diff --git a/plugingui/font.cc b/plugingui/font.cc index f96bd95..d02efe7 100644 --- a/plugingui/font.cc +++ b/plugingui/font.cc @@ -26,106 +26,100 @@ */ #include "font.h" -#ifdef X11 -#include <X11/Xlib.h> -#endif/*X11*/ +namespace GUI { -GUI::Font::Font(std::string fontfile) - : img_font(fontfile) +Font::Font(const std::string& fontfile) + : img_font(fontfile) { - int px = 0; - int c; - for(c = 0; c < 255 && px < (int)img_font.width(); c++) { - character_offset[c] = px + 1; - character_pre_bias[c] = 0; - character_post_bias[c] = 0; - if(c > 0) { - character_width[c - 1] = - character_offset[c] - character_offset[c - 1] - 1; - } - px++; - GUI::Colour c; - while(px < (int)img_font.width()) { - c = img_font.getPixel(px, 0); - // Find next purple pixel in top row: - if(c.red == 1 && c.green == 0 && c.blue == 1 && c.alpha == 1) break; - px++; - } - } - c++; - character_width[c - 1] = character_offset[c] - character_offset[c - 1] - 1; -} - -void GUI::Font::setFace(std::string face) -{ - face = face; -} + size_t px = 0; + size_t c; -std::string GUI::Font::face() -{ - return "";//face; -} + for(c = 0; c < characters.size() && px < img_font.width(); ++c) + { + auto& character = characters[c]; + character.offset = px + 1; -void GUI::Font::setSize(size_t points) -{ - (void)points; -} + if(c > 0) + { + characters[c - 1].width = + character.offset - characters[c - 1].offset - 1; + } -size_t GUI::Font::size() -{ - return 0; + ++px; + + Colour pixel; + while(px < img_font.width()) + { + pixel = img_font.getPixel(px, 0); + + // Find next purple pixel in top row: + if((pixel.red == 1) && (pixel.green == 0) && + (pixel.blue == 1) && (pixel.alpha == 1)) + { + break; + } + + ++px; + } + + characters[c] = character; + } + + ++c; + + characters[c - 1].width = characters[c].offset - characters[c - 1].offset - 1; } -size_t GUI::Font::textWidth(std::string text) +size_t Font::textWidth(const std::string& text) const { - size_t len = 0; + size_t len = 0; - for(size_t i = 0; i < text.length(); i++) { - unsigned int cha = text[i]; - len += character_width[(char)cha] + 1 + character_post_bias[(char)cha]; - } + for(auto cha : text) + { + auto& character = characters[cha]; + len += character.width + spacing + character.post_bias; + } - return len; + return len; } -size_t GUI::Font::textHeight(std::string text) +size_t Font::textHeight(const std::string& text) const { - return img_font.height(); + return img_font.height(); } -GUI::PixelBufferAlpha *GUI::Font::render(std::string text) +void Font::setLetterSpacing(int letter_spacing) { - int border = 1; - PixelBufferAlpha *pb = - new PixelBufferAlpha(textWidth(text), textHeight(text)); - - int x_offset = 0; - for(size_t i = 0; i < text.length(); i++) { - unsigned int cha = text[i]; - for(size_t x = 0; x < character_width[(char)cha]; x++) { - for(size_t y = 0; y < img_font.height(); y++) { - Colour c = img_font.getPixel(x + (character_offset[(char)cha]), y); - pb->setPixel(x + x_offset + character_pre_bias[(char)cha], y, - c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255); - } - } - x_offset += character_width[(char)cha] + border + - character_post_bias[(char)cha]; - } - - return pb; + spacing = letter_spacing; } -#ifdef TEST_FONT -//deps: -//cflags: -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). +int Font::letterSpacing() const +{ + return spacing; +} -TEST_END; +PixelBufferAlpha *Font::render(const std::string& text) const +{ + PixelBufferAlpha *pb = + new PixelBufferAlpha(textWidth(text), textHeight(text)); + + int x_offset = 0; + for(auto cha : text) + { + auto& character = characters[cha]; + for(size_t x = 0; x < character.width; ++x) + { + for(size_t y = 0; y < img_font.height(); ++y) + { + Colour c = img_font.getPixel(x + character.offset, y); + pb->setPixel(x + x_offset + character.pre_bias, y, + c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255); + } + } + x_offset += character.width + spacing + character.post_bias; + } + + return pb; +} -#endif/*TEST_FONT*/ +} // GUI:: diff --git a/plugingui/font.h b/plugingui/font.h index b47fbde..e29528d 100644 --- a/plugingui/font.h +++ b/plugingui/font.h @@ -24,11 +24,10 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_FONT_H__ -#define __DRUMGIZMO_FONT_H__ +#pragma once #include <string> -#include <map> +#include <array> #include "pixelbuffer.h" #include "image.h" @@ -37,27 +36,29 @@ namespace GUI { class Font { public: - Font(std::string fontfile = ":font.png"); - - void setFace(std::string face); - std::string face(); + Font(const std::string& fontfile = ":font.png"); - void setSize(size_t points); - size_t size(); + size_t textWidth(const std::string& text) const; + size_t textHeight(const std::string& text = "") const; - size_t textWidth(std::string text); - size_t textHeight(std::string text = ""); + void setLetterSpacing(int letterSpacing); + int letterSpacing() const; - PixelBufferAlpha *render(std::string text); + PixelBufferAlpha *render(const std::string& text) const; private: - Image img_font; + Image img_font; - std::map<char, int> character_offset; - std::map<char, size_t> character_width; - std::map<char, int> character_pre_bias; - std::map<char, int> character_post_bias; -}; + class Character { + public: + int offset{0}; + size_t width{0}; + int pre_bias{0}; + int post_bias{0}; + }; + std::array<Character, 255> characters; + int spacing{1}; }; -#endif/*__DRUMGIZMO_FONT_H__*/ + +} // GUI:: diff --git a/plugingui/guievent.h b/plugingui/guievent.h index 4732101..6e2ded9 100644 --- a/plugingui/guievent.h +++ b/plugingui/guievent.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_GUI_EVENT_H__ -#define __DRUMGIZMO_GUI_EVENT_H__ +#pragma once #include <unistd.h> @@ -38,104 +37,117 @@ namespace GUI { +enum class EventType { + mouseMove, + repaint, + button, + scroll, + key, + close, + resize +}; + class Event { public: - typedef enum { - MouseMove, - Repaint, - Button, - Scroll, - Key, - Close, - Resize - } Type; - virtual ~Event() {} - - virtual Type type() = 0; + virtual ~Event() {} + + virtual EventType type() = 0; #ifdef X11 - ::Window window_id; + ::Window window_id; #endif/*X11*/ }; class MouseMoveEvent : public Event { public: - Type type() { return MouseMove; } + EventType type() { return EventType::mouseMove; } + + int x; + int y; +}; + + +enum class Direction { + up, + down, +}; - int x; - int y; +enum class MouseButton { + right, + middle, + left, }; class ButtonEvent : public Event { public: - Type type() { return Button; } + EventType type() { return EventType::button; } - int x; - int y; + int x; + int y; - int direction; - int button; - int doubleclick; + Direction direction; + MouseButton button; + + bool doubleClick; }; class ScrollEvent : public Event { public: - Type type() { return Scroll; } + EventType type() { return EventType::scroll; } - int x; - int y; + int x; + int y; - int delta; + int delta; }; class RepaintEvent : public Event { public: - Type type() { return Repaint; } + EventType type() { return EventType::repaint; } + + int x; + int y; + size_t width; + size_t height; +}; - int x; - int y; - size_t width; - size_t height; +enum class Key { + unknown, + left, + right, + up, + down, + deleteKey, + backspace, + home, + end, + pageDown, + pageUp, + enter, + character, //!< The actual character is stored in KeyEvent::text }; class KeyEvent : public Event { public: - Type type() { return Key; } - - int direction; - int keycode; - std::string text; - - enum { - KEY_UNKNOWN =-1, - KEY_LEFT = 1, - KEY_RIGHT = 2, - KEY_UP = 3, - KEY_DOWN = 4, - KEY_DELETE = 5, - KEY_BACKSPACE = 6, - KEY_HOME = 7, - KEY_END = 8, - KEY_PGDOWN = 9, - KEY_PGUP = 10, - KEY_ENTER = 11, - KEY_CHARACTER = 0xffff // character data is stored in 'text' - }; + EventType type() { return EventType::key; } + + Direction direction; + + Key keycode; + std::string text; }; class CloseEvent : public Event { public: - Type type() { return Close; } + EventType type() { return EventType::close; } }; class ResizeEvent : public Event { public: - Type type() { return Resize; } - - size_t width; - size_t height; -}; + EventType type() { return EventType::resize; } + size_t width; + size_t height; }; -#endif/*__DRUMGIZMO_GUI_EVENT_H__*/ +} // GUI:: diff --git a/plugingui/image.cc b/plugingui/image.cc index 65b8242..3cefbb3 100644 --- a/plugingui/image.cc +++ b/plugingui/image.cc @@ -26,94 +26,100 @@ */ #include "image.h" -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <stdint.h> +#include <cstring> +#include <cstdint> +#include <cstdlib> #include <hugin.hpp> #include "resource.h" -// http://blog.hammerian.net/2009/reading-png-images-from-memory/ - #include "lodepng/lodepng.h" -GUI::Image::Image(const char* data, size_t size) +namespace GUI { + +Image::Image(const char* data, size_t size) { - load(data, size); + load(data, size); } -GUI::Image::Image(std::string filename) +Image::Image(const std::string& filename) { - GUI::Resource rc(filename); - load(rc.data(), rc.size()); + Resource rc(filename); + load(rc.data(), rc.size()); } -GUI::Image::~Image() +Image::~Image() { - free(image_data); + std::free(image_data); } -void GUI::Image::setError(int err) +void Image::setError() { - GUI::Resource rc(":png_error"); + Resource rc(":png_error"); - const unsigned char *p = (const unsigned char *)rc.data(); + const unsigned char* p = (const unsigned char*)rc.data(); - uint32_t iw, ih; + std::uint32_t iw, ih; - memcpy(&iw, p, sizeof(uint32_t)); p += sizeof(uint32_t); - memcpy(&ih, p, sizeof(uint32_t)); p += sizeof(uint32_t); + std::memcpy(&iw, p, sizeof(uint32_t)); + p += sizeof(uint32_t); - w = iw; - h = ih; + std::memcpy(&ih, p, sizeof(uint32_t)); + p += sizeof(uint32_t); - DEBUG(image, "w:%d, h:%d\n", (int)w, (int)h); + _width = iw; + _height = ih; - image_data = (unsigned char*)malloc(rc.size() - 8); - memcpy(image_data, p, rc.size() - 8); + size_t image_size = rc.size() - (sizeof(iw) + sizeof(ih)); + image_data = (unsigned char*)std::malloc(image_size); + memcpy(image_data, p, image_size); } -void GUI::Image::load(const char* data, size_t size) +void Image::load(const char* data, size_t size) { - //unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, - // const unsigned char* in, size_t insize); - unsigned iw, ih; - unsigned res = lodepng_decode32((unsigned char**)&image_data, &iw, &ih, - (const unsigned char*)data, size); - w = iw; - h = ih; - - if(res != 0) { - ERR(image, "[read_png_file] Error during init_io"); - setError(3); - return; - } + unsigned int iw, ih; + unsigned int res = lodepng_decode32((unsigned char**)&image_data, + &iw, &ih, + (const unsigned char*)data, size); + + _width = iw; + _height = ih; + + if(res != 0) + { + ERR(image, "Error in lodepng_decode32: %d", res); + setError(); + return; + } } -size_t GUI::Image::width() +size_t Image::width() const { - return w; + return _width; } -size_t GUI::Image::height() +size_t Image::height() const { - return h; + return _height; } -GUI::Colour GUI::Image::getPixel(size_t x, size_t y) +Colour Image::getPixel(size_t x, size_t y) const { - if(x > width() || y > height()) return GUI::Colour(0,0,0,0); - unsigned char *ptr = &image_data[(x + y * width()) * 4]; - float r = ptr[0]; - float g = ptr[1]; - float b = ptr[2]; - float a = ptr[3]; - GUI::Colour c(r / 255.0, - g / 255.0, - b / 255.0, - a / 255.0); - return c; + if(x > _width || y > _height) + { + return Colour(0,0,0,0); + } + + unsigned char* ptr = &image_data[(x + y * width()) * 4]; + + float r = ptr[0]; + float g = ptr[1]; + float b = ptr[2]; + float a = ptr[3]; + + Colour c(r / 255.0, g / 255.0, b / 255.0, a / 255.0); + + return c; } + +} // GUI:: diff --git a/plugingui/image.h b/plugingui/image.h index cec1518..0decc22 100644 --- a/plugingui/image.h +++ b/plugingui/image.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_IMAGE_H__ -#define __DRUMGIZMO_IMAGE_H__ +#pragma once #include <string> @@ -36,24 +35,22 @@ namespace GUI { class Image { public: - Image(const char* data, size_t size); - Image(std::string filename); - ~Image(); + Image(const char* data, size_t size); + Image(const std::string& filename); + ~Image(); - size_t width(); - size_t height(); + size_t width() const; + size_t height() const; - Colour getPixel(size_t x, size_t y); + Colour getPixel(size_t x, size_t y) const; private: - void setError(int err); + void setError(); - void load(const char* data, size_t size); + void load(const char* data, size_t size); - size_t w, h; - unsigned char *image_data; + size_t _width, _height; + unsigned char* image_data; }; -}; - -#endif/*__DRUMGIZMO_IMAGE_H__*/ +} // GUI:: diff --git a/plugingui/knob.cc b/plugingui/knob.cc index 4cac180..ab2eca9 100644 --- a/plugingui/knob.cc +++ b/plugingui/knob.cc @@ -37,169 +37,167 @@ #endif #include <math.h> -GUI::Knob::Knob(Widget *parent) - : GUI::Widget(parent), img_knob(":knob.png") +namespace GUI { + +Knob::Knob(Widget *parent) + : Widget(parent) + , img_knob(":knob.png") { - state = up; + state = up; - val = 0.0; - maximum = 1.0; - minimum = 0.0; - mouse_offset_x = 0; + maximum = 1.0; + minimum = 0.0; - handler = NULL; - ptr = NULL; -} + currentValue = minimum; -void GUI::Knob::setValue(float v) -{ - val = v; - if(handler) handler(ptr); - repaintEvent(NULL); + mouse_offset_x = 0; } -float GUI::Knob::value() +void Knob::setValue(float value) { - return val; + internalSetValue(value); } -void GUI::Knob::registerClickHandler(void (*handler)(void *), void *ptr) +float Knob::value() { - this->handler = handler; - this->ptr = ptr; + return currentValue; } -void GUI::Knob::scrollEvent(ScrollEvent *e) +void Knob::scrollEvent(ScrollEvent* scrollEvent) { - val -= e->delta / 200.0; - if(val < 0) val = 0; - if(val > 1) val = 1; - - if(handler) handler(ptr); - - repaintEvent(NULL); + float value = currentValue - (scrollEvent->delta / 200.0); + internalSetValue(value); } -void GUI::Knob::mouseMoveEvent(MouseMoveEvent *e) +void Knob::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) { - if(state == down) { - if(mouse_offset_x == (e->x + -1*e->y)) return; + if(state == down) + { + if(mouse_offset_x == (mouseMoveEvent->x + (-1 * mouseMoveEvent->y))) + { + return; + } - float dval = mouse_offset_x - (e->x + -1*e->y); - val -= dval / 300.0; + float dval = + mouse_offset_x - (mouseMoveEvent->x + (-1 * mouseMoveEvent->y)); + float value = currentValue - (dval / 300.0); - if(val < 0) val = 0; - if(val > 1) val = 1; + internalSetValue(value); - if(handler) handler(ptr); - repaintEvent(NULL); - - mouse_offset_x = e->x + -1*e->y; - } + mouse_offset_x = mouseMoveEvent->x + (-1 * mouseMoveEvent->y); + } } -void GUI::Knob::keyEvent(KeyEvent *e) +void Knob::keyEvent(KeyEvent* keyEvent) { - if(e->direction != -1) return; - - switch(e->keycode) { - case GUI::KeyEvent::KEY_UP: - val += 0.01; - break; - case GUI::KeyEvent::KEY_DOWN: - val -= 0.01; - break; - case GUI::KeyEvent::KEY_RIGHT: - val += 0.01; - break; - case GUI::KeyEvent::KEY_LEFT: - val -= 0.01; - break; - case GUI::KeyEvent::KEY_HOME: - val = 0; - break; - case GUI::KeyEvent::KEY_END: - val = 1; - break; - default: - break; - } - - if(val < 0) val = 0; - if(val > 1) val = 1; - - repaintEvent(NULL); + if(keyEvent->direction != Direction::up) + { + return; + } + + float value = currentValue; + switch(keyEvent->keycode) { + case Key::up: + value += 0.01; + break; + case Key::down: + value -= 0.01; + break; + case Key::right: + value += 0.01; + break; + case Key::left: + value -= 0.01; + break; + case Key::home: + value = 0; + break; + case Key::end: + value = 1; + break; + default: + break; + } + + internalSetValue(value); } -void GUI::Knob::buttonEvent(ButtonEvent *e) +void Knob::buttonEvent(ButtonEvent* buttonEvent) { - if(e->direction == 1) { - state = down; - mouse_offset_x = e->x + -1*e->y; - if(handler) handler(ptr); - repaintEvent(NULL); - } - if(e->direction == -1) { - state = up; - mouse_offset_x = e->x + -1*e->y; - repaintEvent(NULL); - clicked(); - if(handler) handler(ptr); - } + if(buttonEvent->direction == Direction::down) + { + state = down; + mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y); + } + + if(buttonEvent->direction == Direction::up) + { + state = up; + mouse_offset_x = buttonEvent->x + (-1 * buttonEvent->y); + clicked(); + } } -void GUI::Knob::repaintEvent(GUI::RepaintEvent *e) +void Knob::repaintEvent(RepaintEvent* repaintEvent) { - int diameter = (width()>height()?height():width()); - int radius = diameter / 2; - int center_x = width() / 2; - int center_y = height() / 2; - - Painter p(this); - - p.clear(); - p.drawImageStretched(0, 0, &img_knob, diameter, diameter); - - char buf[64]; - sprintf(buf, "%.2f", val * maximum); - Font font; - p.drawText(center_x - font.textWidth(buf) / 2 + 1, - center_y + font.textHeight(buf) / 2 + 1, font, buf); - - double padval = val * 0.8 + 0.1; // Make it start from 20% and stop at 80% - - double from_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.6; - double from_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.6; - - double to_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.8; - double to_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.8; - - // Draw "fat" line by drawing 9 lines with moved start/ending points. - p.setColour(Colour(1, 0, 0, 1)); - for(int _x = -1; _x < 2; _x++) { - for(int _y = -1; _y < 2; _y++) { - p.drawLine(from_x + center_x + _x, - from_y + center_y + _y, - to_x + center_x + _x, - to_y + center_y + _y); - - } - } + int diameter = (width()>height()?height():width()); + int radius = diameter / 2; + int center_x = width() / 2; + int center_y = height() / 2; + + Painter p(*this); + + p.clear(); + p.drawImageStretched(0, 0, img_knob, diameter, diameter); + + char buf[64]; + sprintf(buf, "%.2f", currentValue * maximum); + p.drawText(center_x - font.textWidth(buf) / 2 + 1, + center_y + font.textHeight(buf) / 2 + 1, font, buf); + + // Make it start from 20% and stop at 80% + double padval = currentValue * 0.8 + 0.1; + + double from_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.6; + double from_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.6; + + double to_x = sin((-1 * padval + 1) * 2 * M_PI) * radius * 0.8; + double to_y = cos((-1 * padval + 1) * 2 * M_PI) * radius * 0.8; + + // Draw "fat" line by drawing 9 lines with moved start/ending points. + p.setColour(Colour(1, 0, 0, 1)); + for(int _x = -1; _x < 2; _x++) + { + for(int _y = -1; _y < 2; _y++) + { + p.drawLine(from_x + center_x + _x, + from_y + center_y + _y, + to_x + center_x + _x, + to_y + center_y + _y); + } + } } -#ifdef TEST_KNOB -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; +void Knob::internalSetValue(float value) +{ + if(value < minimum) + { + value = minimum; + } + + if(value > maximum) + { + value = maximum; + } + + if(value == currentValue) + { + return; + } + + currentValue = value; + valueChangedNotifier(currentValue); + repaintEvent(nullptr); +} -#endif/*TEST_KNOB*/ +} // GUI:: diff --git a/plugingui/knob.h b/plugingui/knob.h index a6af499..4a71b2e 100644 --- a/plugingui/knob.h +++ b/plugingui/knob.h @@ -24,57 +24,57 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_KNOB_H__ -#define __DRUMGIZMO_KNOB_H__ +#pragma once #include "widget.h" - #include "image.h" +#include "font.h" +#include "notifier.h" namespace GUI { class Knob : public Widget { public: - Knob(Widget *parent); + Knob(Widget *parent); - bool catchMouse() { return true; } - bool isFocusable() { return true; } + // From Widget: + bool catchMouse() override { return true; } + bool isFocusable() override { return true; } - void setValue(float value); - float value(); + void setValue(float value); + float value(); - void registerClickHandler(void (*handler)(void *), void *ptr); + Notifier<float> valueChangedNotifier; // (float newValue) - //protected: - virtual void clicked() {} +protected: + virtual void clicked() {} - virtual void repaintEvent(RepaintEvent *e); - virtual void buttonEvent(ButtonEvent *e); - virtual void mouseMoveEvent(MouseMoveEvent *e); - virtual void scrollEvent(ScrollEvent *e); - virtual void keyEvent(KeyEvent *e); + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; + virtual void scrollEvent(ScrollEvent* scrollEvent) override; + virtual void keyEvent(KeyEvent* keyEvent) override; private: - typedef enum { - up, - down - } state_t; - - float val; - float maximum; - float minimum; + //! Sets the internal value and sends out the changed notification. + void internalSetValue(float value); - state_t state; + typedef enum { + up, + down + } state_t; - GUI::Image img_knob; + state_t state; - void (*handler)(void *); - void *ptr; + float currentValue; + float maximum; + float minimum; - int mouse_offset_x; - -}; + Image img_knob; + int mouse_offset_x; + Font font; }; -#endif/*__DRUMGIZMO_KNOB_H__*/ +} // GUI:: diff --git a/plugingui/label.cc b/plugingui/label.cc index bcc7005..f4a2cc1 100644 --- a/plugingui/label.cc +++ b/plugingui/label.cc @@ -27,43 +27,53 @@ #include "label.h" #include "painter.h" +#include "guievent.h" -GUI::Label::Label(GUI::Widget *parent) : GUI::Widget(parent) +namespace GUI { + +Label::Label(Widget *parent) + : Widget(parent) { } -void GUI::Label::setText(std::string text) +void Label::setText(const std::string& text) { - _text = text; - repaintEvent(NULL); + _text = text; + repaintEvent(nullptr); } -void GUI::Label::repaintEvent(GUI::RepaintEvent *e) +void Label::setAlignment(TextAlignment alignment) { - Painter p(this); - - p.clear(); - - p.setColour(Colour(1)); + this->alignment = alignment; +} - Font font(":fontemboss.png"); - p.drawText(10, (height() + font.textHeight()) / 2, font, _text, true); +void Label::resizeToText() +{ + resize(font.textWidth(_text) + border, font.textHeight()); } +void Label::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); -#ifdef TEST_LABEL -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" + p.clear(); -TEST_BEGIN; + p.setColour(Colour(1)); -// TODO: Put some testcode here (see test.h for usable macros). + int offset = 0; + switch(alignment) { + case TextAlignment::left: + offset = border; + break; + case TextAlignment::center: + offset = (width() - font.textWidth(_text)) / 2; + break; + case TextAlignment::right: + offset = width() - font.textWidth(_text) - border; + break; + } -TEST_END; + p.drawText(offset, (height() + font.textHeight()) / 2, font, _text, true); +} -#endif/*TEST_LABEL*/ +} // GUI:: diff --git a/plugingui/label.h b/plugingui/label.h index 50f02d6..794778d 100644 --- a/plugingui/label.h +++ b/plugingui/label.h @@ -24,30 +24,41 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_LABEL_H__ -#define __DRUMGIZMO_LABEL_H__ +#pragma once #include "widget.h" -#include <string> +#include "font.h" -#include "guievent.h" +#include <string> namespace GUI { +enum class TextAlignment { + left, + center, + right, +}; + class Label : public Widget { public: - Label(Widget *parent); + Label(Widget *parent); - void setText(std::string text); + void setText(const std::string& text); - //protected: - virtual void repaintEvent(RepaintEvent *e); + void setAlignment(TextAlignment alignment); -private: - std::string _text; -}; + void resizeToText(); +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + std::string _text; + Font font{":fontemboss.png"}; + TextAlignment alignment{TextAlignment::left}; + int border{0}; }; -#endif/*__DRUMGIZMO_LABEL_H__*/ +} // GUI:: diff --git a/plugingui/layout.cc b/plugingui/layout.cc new file mode 100644 index 0000000..65042a4 --- /dev/null +++ b/plugingui/layout.cc @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * layout.cc + * + * Sat Mar 21 15:12:36 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "layout.h" + +#include "widget.h" + +namespace GUI { + +LayoutItem::LayoutItem() + : parent(nullptr) +{ +} + +LayoutItem::~LayoutItem() +{ + setLayoutParent(nullptr); // Will disconnect from layout if any. +} + +void LayoutItem::setLayoutParent(Layout *p) +{ + if(this->parent) + { + this->parent->removeItem(this); + } + + this->parent = p; +} + +Layout::Layout(LayoutItem *parent) + : parent(parent) +{ + auto widget = dynamic_cast<Widget*>(parent); + if(widget) + { + CONNECT(widget, sizeChangeNotifier, this, &Layout::sizeChanged); + } +} + +void Layout::addItem(LayoutItem *item) +{ + items.push_back(item); + item->setLayoutParent(this); + layout(); +} + +void Layout::removeItem(LayoutItem *item) +{ + LayoutItemList::iterator i = items.begin(); + while(i != items.end()) + { + if(*i == item) + { + i = items.erase(i); + continue; + } + ++i; + } + + layout(); +} + +void Layout::sizeChanged(int width, int height) +{ + layout(); +} + +// +// BoxLayout +// + +BoxLayout::BoxLayout(LayoutItem *parent) + : Layout(parent) +{ +} + +void BoxLayout::setResizeChildren(bool resizeChildren) +{ + this->resizeChildren = resizeChildren; + layout(); +} + +void BoxLayout::setSpacing(size_t spacing) +{ + this->spacing = spacing; + layout(); +} + +// +// VBoxLayout +// + +VBoxLayout::VBoxLayout(LayoutItem *parent) + : BoxLayout(parent) + , align(HAlignment::center) +{ +} + +void VBoxLayout::layout() +{ + size_t y = 0; + size_t w = parent->width(); + //size_t h = parent->height() / items.size(); + + LayoutItemList::iterator i = items.begin(); + while(i != items.end()) + { + LayoutItem *item = *i; + if(resizeChildren) + { + item->resize(w, parent->height() / items.size()); + } + + size_t x = 0; + switch(align) { + case HAlignment::left: + x = 0; + break; + case HAlignment::center: + x = (w / 2) - (item->width() / 2); + break; + case HAlignment::right: + x = w - item->width(); + break; + } + + item->move(x, y); + y += item->height() + spacing; + ++i; + } +} + +void VBoxLayout::setHAlignment(HAlignment alignment) +{ + align = alignment; +} + +// +// HBoxLayout +// + +HBoxLayout::HBoxLayout(LayoutItem *parent) + : BoxLayout(parent) + , align(VAlignment::center) +{ +} + +void HBoxLayout::layout() +{ + if(items.empty()) + { + return; + } + +// size_t w = parent->width() / items.size(); + size_t h = parent->height(); + size_t x = 0; + + LayoutItemList::iterator i = items.begin(); + while(i != items.end()) + { + LayoutItem *item = *i; + if(resizeChildren) + { + item->resize(parent->width() / items.size(), h); + item->move(x, 0); + } + else + { + size_t y = 0; + switch(align) { + case VAlignment::top: + y = 0; + break; + case VAlignment::center: + y = (h / 2) - (item->height() / 2); + break; + case VAlignment::bottom: + y = h - item->height(); + break; + } + + int diff = 0;//w - item->width(); + item->move(x + diff / 2, y); + } + x += item->width() + spacing; + ++i; + } +} + +void HBoxLayout::setVAlignment(VAlignment alignment) +{ + align = alignment; +} + +} // GUI:: diff --git a/plugingui/layout.h b/plugingui/layout.h new file mode 100644 index 0000000..949c1ca --- /dev/null +++ b/plugingui/layout.h @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * layout.h + * + * Sat Mar 21 15:12:36 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include <list> +#include <cstdlib> + +#include "notifier.h" + +namespace GUI { + +class Layout; + +class LayoutItem { +public: + LayoutItem(); + virtual ~LayoutItem(); + + void setLayoutParent(Layout* parent); + + virtual void resize(int width, int height) = 0; + virtual void move(size_t x, size_t y) = 0; + virtual int x() = 0; + virtual int y() = 0; + virtual size_t width() = 0; + virtual size_t height() = 0; + +private: + Layout* parent; +}; + +//! \brief Abtract Layout class. +class Layout : public Listener +{ +public: + Layout(LayoutItem *parent); + virtual ~Layout() {} + + virtual void addItem(LayoutItem *item); + virtual void removeItem(LayoutItem *item); + + //! \brief Reimplement this method to create a new Layout rule. + virtual void layout() = 0; + +protected: + void sizeChanged(int width, int height); + + LayoutItem *parent; + typedef std::list<LayoutItem *> LayoutItemList; + LayoutItemList items; +}; + +//! \brief Abstract box layout +class BoxLayout : public Layout { +public: + BoxLayout(LayoutItem *parent); + + //! \brief Set to false to only move the items, not scale them. + void setResizeChildren(bool resize_children); + + void setSpacing(size_t spacing); + + // From Layout: + virtual void layout() override = 0; + +protected: + bool resizeChildren{false}; + size_t spacing{0}; +}; + +enum class HAlignment { + left, + center, + right, +}; + +//! \brief A Layout that lays out its elements vertically. +class VBoxLayout : public BoxLayout { +public: + VBoxLayout(LayoutItem *parent); + + void setHAlignment(HAlignment alignment); + + // From BoxLayout: + virtual void layout() override; + +protected: + HAlignment align; +}; + +enum class VAlignment { + top, + center, + bottom, +}; + +//! \brief A Layout that lays out its elements vertically. +class HBoxLayout : public BoxLayout { +public: + HBoxLayout(LayoutItem *parent); + + void setVAlignment(VAlignment alignment); + + // From BoxLayout: + virtual void layout() override; + +protected: + VAlignment align; +}; + +} // GUI:: diff --git a/plugingui/led.cc b/plugingui/led.cc index d26a0de..6950140 100644 --- a/plugingui/led.cc +++ b/plugingui/led.cc @@ -28,79 +28,70 @@ #include "painter.h" -GUI::LED::LED(Widget *parent) - : GUI::Widget(parent) +namespace GUI { + +LED::LED(Widget *parent) + : Widget(parent) + , state(Off) { - state = off; } -void GUI::LED::setState(GUI::LED::state_t state) +void LED::setState(state_t state) { - if(this->state != state) { - this->state = state; - repaintEvent(NULL); - } + if(this->state != state) + { + this->state = state; + repaintEvent(nullptr); + } } -void GUI::LED::repaintEvent(GUI::RepaintEvent *e) +void LED::repaintEvent(RepaintEvent* repaintEvent) { - size_t h = height() - 1; - size_t w = width() - 1; + size_t h = height() - 1; + size_t w = width() - 1; - Painter p(this); - float alpha = 0.9; - switch(state) { - case red: - p.setColour(Colour(1, 0, 0,alpha)); - break; - case green: - p.setColour(Colour(0, 1, 0, alpha)); - break; - case blue: - p.setColour(Colour(0, 0, 1, alpha)); - break; - case off: - p.setColour(Colour(0.2, 0.2, 0.2, alpha)); - break; - } + Painter p(*this); + float alpha = 0.9; + switch(state) { + case Red: + p.setColour(Colour(1, 0, 0,alpha)); + break; + case Green: + p.setColour(Colour(0, 1, 0, alpha)); + break; + case Blue: + p.setColour(Colour(0, 0, 1, alpha)); + break; + case Off: + p.setColour(Colour(0.2, 0.2, 0.2, alpha)); + break; + } - size_t size = w / 2; - if(h / 2 < size) size = h / 2; - p.drawFilledCircle(w/2, h/2, size); + size_t size = w / 2; + if((h / 2) < size) + { + size = h / 2; + } + p.drawFilledCircle(w / 2, h / 2, size); - switch(state) { - case red: - p.setColour(Colour(0.4, 0, 0,alpha)); - break; - case green: - p.setColour(Colour(0, 0.4, 0, alpha)); - break; - case blue: - p.setColour(Colour(0, 0, 0.4, alpha)); - break; - case off: - p.setColour(Colour(0.1, 0.1, 0.1, alpha)); - break; - } - p.drawCircle(w/2, h/2, size); + switch(state) { + case Red: + p.setColour(Colour(0.4, 0, 0, alpha)); + break; + case Green: + p.setColour(Colour(0, 0.4, 0, alpha)); + break; + case Blue: + p.setColour(Colour(0, 0, 0.4, alpha)); + break; + case Off: + p.setColour(Colour(0.1, 0.1, 0.1, alpha)); + break; + } + p.drawCircle(w / 2, h / 2, size); - p.setColour(Colour(1,alpha)); - p.drawFilledCircle(w/3, h/3, size / 6); + p.setColour(Colour(1, alpha)); + p.drawFilledCircle(w / 3, h / 3, size / 6); } -#ifdef TEST_LED -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_LED*/ +} // GUI:: diff --git a/plugingui/led.h b/plugingui/led.h index 7bbd59a..6b1b730 100644 --- a/plugingui/led.h +++ b/plugingui/led.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_LED_H__ -#define __DRUMGIZMO_LED_H__ +#pragma once #include "widget.h" @@ -33,24 +32,23 @@ namespace GUI { class LED : public Widget { public: - typedef enum { - red, - green, - blue, - off - } state_t; + typedef enum { + Red, + Green, + Blue, + Off + } state_t; - LED(Widget *parent); + LED(Widget *parent); - void setState(state_t state); + void setState(state_t state); - //protected: - void repaintEvent(RepaintEvent *e); +protected: + // From Widget: + void repaintEvent(RepaintEvent* repaintEvent) override; private: - state_t state; + state_t state; }; -}; - -#endif/*__DRUMGIZMO_LED_H__*/ +} // GUI:: diff --git a/plugingui/lineedit.cc b/plugingui/lineedit.cc index 5e1eb9b..2df40ff 100644 --- a/plugingui/lineedit.cc +++ b/plugingui/lineedit.cc @@ -27,213 +27,271 @@ #include "lineedit.h" #include <stdio.h> - -#include "window.h" - -#include <assert.h> - #include <hugin.hpp> #define BORDER 10 -GUI::LineEdit::LineEdit(Widget *parent) - : GUI::Widget(parent) +namespace GUI { + +LineEdit::LineEdit(Widget *parent) + : Widget(parent) { - pos = 0; - offsetpos = 0; - setReadOnly(false); - - box.topLeft = new Image(":widget_tl.png"); - box.top = new Image(":widget_t.png"); - box.topRight = new Image(":widget_tr.png"); - box.left = new Image(":widget_l.png"); - box.right = new Image(":widget_r.png"); - box.bottomLeft = new Image(":widget_bl.png"); - box.bottom = new Image(":widget_b.png"); - box.bottomRight = new Image(":widget_br.png"); - box.center = new Image(":widget_c.png"); - - handler = NULL; + setReadOnly(false); + + box.topLeft = new Image(":widget_tl.png"); + box.top = new Image(":widget_t.png"); + box.topRight = new Image(":widget_tr.png"); + box.left = new Image(":widget_l.png"); + box.right = new Image(":widget_r.png"); + box.bottomLeft = new Image(":widget_bl.png"); + box.bottom = new Image(":widget_b.png"); + box.bottomRight = new Image(":widget_br.png"); + box.center = new Image(":widget_c.png"); } -void GUI::LineEdit::registerEnterPressedHandler(void (*handler)(void *), void *ptr) +LineEdit::~LineEdit() { - this->handler = handler; - this->ptr = ptr; + delete box.topLeft; + delete box.top; + delete box.topRight; + delete box.left; + delete box.right; + delete box.bottomLeft; + delete box.bottom; + delete box.bottomRight; + delete box.center; } -void GUI::LineEdit::setReadOnly(bool ro) +void LineEdit::setReadOnly(bool ro) { - readonly = ro; + readonly = ro; } -bool GUI::LineEdit::readOnly() +bool LineEdit::readOnly() { - return readonly; + return readonly; } -void GUI::LineEdit::setText(std::string text) +void LineEdit::setText(const std::string& text) { - _text = text; - pos = text.size(); - - repaintEvent(NULL); - textChanged(); + _text = text; + pos = text.size(); + + visibleText = _text; + offsetPos = 0; + + repaintEvent(nullptr); + textChanged(); } -std::string GUI::LineEdit::text() +std::string LineEdit::text() { - return _text; + return _text; } -void GUI::LineEdit::buttonEvent(ButtonEvent *e) +void LineEdit::buttonEvent(ButtonEvent *buttonEvent) { - if(readOnly()) return; - - - if(e->direction == 1) { - for(int i = 0; i < (int)_visibletext.length(); i++) { - if(e->x < (int)(font.textWidth(_visibletext.substr(0, i)) + BORDER)) { - pos = i + offsetpos; - break; - } - } - repaintEvent(NULL); - } + if(readOnly()) + { + return; + } + + if(buttonEvent->direction == Direction::down) + { + for(int i = 0; i < (int)visibleText.length(); ++i) + { + int textWidth = font.textWidth(visibleText.substr(0, i)); + if(buttonEvent->x < (textWidth + BORDER)) + { + pos = i + offsetPos; + break; + } + } + repaintEvent(nullptr); + } } -void GUI::LineEdit::keyEvent(GUI::KeyEvent *e) +void LineEdit::keyEvent(KeyEvent *keyEvent) { - if(readOnly()) return; - - bool change = false; - - if(e->direction == -1) { - - if(e->keycode == GUI::KeyEvent::KEY_LEFT) { - if(pos) pos--; - if(offsetpos >= pos) walkstate = WALK_LEFT; - - } else if(e->keycode == GUI::KeyEvent::KEY_HOME) { - pos = 0; - - } else if(e->keycode == GUI::KeyEvent::KEY_END) { - pos = _text.length(); - - } else if(e->keycode == GUI::KeyEvent::KEY_RIGHT) { - if(pos < _text.length()) pos++; - if(offsetpos + _visibletext.length() <= pos && - pos < _text.length()) walkstate = WALK_RIGHT; - - } else if(e->keycode == GUI::KeyEvent::KEY_DELETE) { - if(pos < _text.length()) { - std::string t = _text.substr(0, pos); - t += _text.substr(pos + 1, std::string::npos); - _text = t; - change = true; - } - - } else if(e->keycode == GUI::KeyEvent::KEY_BACKSPACE) { - if(pos > 0) { - std::string t = _text.substr(0, pos - 1); - t += _text.substr(pos, std::string::npos); - _text = t; - pos--; - change = true; - } - - } else if(e->keycode == GUI::KeyEvent::KEY_CHARACTER) { - std::string pre = _text.substr(0, pos); - std::string post = _text.substr(pos, std::string::npos); - _text = pre + e->text + post; - change = true; - pos++; - - } else if(e->keycode == GUI::KeyEvent::KEY_ENTER) { - if(handler) handler(ptr); - } - repaintEvent(NULL); - } - - if(change) textChanged(); + if(readOnly()) + { + return; + } + + bool change = false; + + if(keyEvent->direction == Direction::down) + { + switch(keyEvent->keycode) { + case Key::left: + if(pos == 0) + { + return; + } + + pos--; + + if(offsetPos >= pos) + { + walkstate = WalkLeft; + } + break; + + case Key::right: + if(pos == _text.length()) + { + return; + } + + pos++; + + if((pos < _text.length()) && ((offsetPos + visibleText.length()) <= pos)) + { + walkstate = WalkRight; + } + break; + + case Key::home: + pos = 0; + visibleText = _text; + offsetPos = 0; + break; + + case Key::end: + pos = _text.length(); + visibleText = _text; + offsetPos = 0; + break; + + case Key::deleteKey: + if(pos < _text.length()) + { + std::string t = _text.substr(0, pos); + t += _text.substr(pos + 1, std::string::npos); + _text = t; + change = true; + } + break; + + case Key::backspace: + if(pos > 0) + { + std::string t = _text.substr(0, pos - 1); + t += _text.substr(pos, std::string::npos); + _text = t; + pos--; + change = true; + } + break; + + case Key::character: + { + std::string pre = _text.substr(0, pos); + std::string post = _text.substr(pos, std::string::npos); + _text = pre + keyEvent->text + post; + change = true; + pos++; + } + break; + + case Key::enter: + enterPressedNotifier(); + break; + + default: + break; + } + + repaintEvent(nullptr); + } + + if(change) + { + textChanged(); + } } -void GUI::LineEdit::repaintEvent(GUI::RepaintEvent *e) +void LineEdit::repaintEvent(RepaintEvent *repaintEvent) { - Painter p(this); - - p.clear(); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) return; - p.drawBox(0, 0, &box, w, h); - - p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); - - if(walkstate == WALK_LEFT) { - _visibletext = _text.substr(pos, std::string::npos); - offsetpos = pos; - } - else if(walkstate == WALK_RIGHT) { - int d = (offsetpos < _text.length()) ? 1 : 0; - _visibletext = _text.substr(offsetpos + d); - offsetpos = offsetpos + d; - } - else { - _visibletext = _text; - offsetpos = 0; - } - while(true) { - int textwidth = font.textWidth(_visibletext); - if(textwidth > w - BORDER - 4 + 3) { - if(walkstate == WALK_LEFT) { - _visibletext = _visibletext.substr(0, _visibletext.length()-1); - } - else if(walkstate == WALK_RIGHT) { - _visibletext = _visibletext.substr(0, _visibletext.length()-1); - } - else { - if(offsetpos < pos) { - _visibletext = _visibletext.substr(1); - offsetpos++; - } - else { - _visibletext = _visibletext.substr(0, _visibletext.length() - 1); - } - } - } - else { - break; - } - } - - walkstate = NOOP; - - p.drawText(BORDER - 4 + 3, height()/2+5 + 1 + 1 + 1, font, _visibletext); - - if(readOnly()) return; - - if(hasKeyboardFocus()) { - size_t px = font.textWidth(_visibletext.substr(0, pos - offsetpos)); - p.drawLine(px + BORDER - 1 - 4 + 3, 6, - px + BORDER - 1 - 4 + 3, height() - 7); - } + Painter p(*this); + + p.clear(); + + int w = width(); + int h = height(); + if((w == 0) || (h == 0)) + { + return; + } + + p.drawBox(0, 0, box, w, h); + + p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); + + switch(walkstate) { + case WalkLeft: + visibleText = _text.substr(pos, std::string::npos); + offsetPos = pos; + break; + + case WalkRight: + { + int delta = (offsetPos < _text.length()) ? 1 : 0; + visibleText = _text.substr(offsetPos + delta); + offsetPos = offsetPos + delta; + } + break; + + case Noop: + break; + } + + while(true) + { + int textWidth = font.textWidth(visibleText); + if(textWidth <= (w - BORDER - 4 + 3)) + { + break; + } + + switch(walkstate) { + case WalkLeft: + visibleText = visibleText.substr(0, visibleText.length() - 1); + break; + + case WalkRight: + visibleText = visibleText.substr(0, visibleText.length() - 1); + break; + + case Noop: + if(offsetPos < pos) + { + visibleText = visibleText.substr(1); + offsetPos++; + } + else + { + visibleText = visibleText.substr(0, visibleText.length() - 1); + } + break; + } + } + + walkstate = Noop; + + p.drawText(BORDER - 4 + 3, height() / 2 + 5 + 1 + 1 + 1, font, visibleText); + + if(readOnly()) + { + return; + } + + if(hasKeyboardFocus()) + { + size_t px = font.textWidth(visibleText.substr(0, pos - offsetPos)); + p.drawLine(px + BORDER - 1 - 4 + 3, 6, + px + BORDER - 1 - 4 + 3, height() - 7); + } } -#ifdef TEST_LINEEDIT -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_LINEEDIT*/ +} // GUI:: diff --git a/plugingui/lineedit.h b/plugingui/lineedit.h index f85e9bd..ae1c7b8 100644 --- a/plugingui/lineedit.h +++ b/plugingui/lineedit.h @@ -24,9 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_LINEEDIT_H__ -#define __DRUMGIZMO_LINEEDIT_H__ - +#pragma once #include <string> @@ -38,49 +36,45 @@ namespace GUI { class LineEdit : public Widget { public: - LineEdit(Widget *parent); + LineEdit(Widget *parent); + ~LineEdit(); - bool isFocusable() { return true; } + bool isFocusable() override { return true; } - std::string text(); - void setText(std::string text); + std::string text(); + void setText(const std::string& text); - void setReadOnly(bool readonly); - bool readOnly(); + void setReadOnly(bool readonly); + bool readOnly(); - void registerEnterPressedHandler(void (*handler)(void *), void *ptr); + Notifier<> enterPressedNotifier; - //protected: - virtual void keyEvent(KeyEvent *e); - virtual void repaintEvent(RepaintEvent *e); - virtual void buttonEvent(ButtonEvent *e); + //protected: + virtual void keyEvent(KeyEvent *keyEvent) override; + virtual void repaintEvent(RepaintEvent *repaintEvent) override; + virtual void buttonEvent(ButtonEvent *buttonEvent) override; protected: - virtual void textChanged() {} + virtual void textChanged() {} private: - Painter::Box box; - - Font font; + Painter::Box box; - std::string _text; - size_t pos; - std::string _visibletext; - size_t offsetpos; + Font font; - enum state_t { - NOOP = 0, - WALK_LEFT = 1, - WALK_RIGHT = 2 - }; - state_t walkstate; + std::string _text; + size_t pos{0}; + std::string visibleText; + size_t offsetPos{0}; - bool readonly; - - void (*handler)(void *); - void *ptr; -}; + enum state_t { + Noop, + WalkLeft, + WalkRight, + }; + state_t walkstate{Noop}; + bool readonly; }; -#endif/*__DRUMGIZMO_LINEEDIT_H__*/ +} // GUI:: diff --git a/plugingui/listbox.cc b/plugingui/listbox.cc index ed873b2..8097ca9 100644 --- a/plugingui/listbox.cc +++ b/plugingui/listbox.cc @@ -29,95 +29,97 @@ #include "painter.h" #include "font.h" -#include <stdio.h> - -GUI::ListBox::ListBox(GUI::Widget *parent) - : GUI::Widget(parent) +namespace GUI { + +ListBox::ListBox(Widget *parent) + : Widget(parent) + , selectionNotifier(basic.selectionNotifier) + , clickNotifier(basic.clickNotifier) + , valueChangedNotifier(basic.valueChangedNotifier) + , basic(this) { - box.topLeft = new Image(":widget_tl.png"); - box.top = new Image(":widget_t.png"); - box.topRight = new Image(":widget_tr.png"); - box.left = new Image(":widget_l.png"); - box.right = new Image(":widget_r.png"); - box.bottomLeft = new Image(":widget_bl.png"); - box.bottom = new Image(":widget_b.png"); - box.bottomRight = new Image(":widget_br.png"); - box.center = new Image(":widget_c.png"); - - basic = new GUI::ListBoxBasic(this); - basic->move(box.left->width(), box.top->height()); + box.topLeft = new Image(":widget_tl.png"); + box.top = new Image(":widget_t.png"); + box.topRight = new Image(":widget_tr.png"); + box.left = new Image(":widget_l.png"); + box.right = new Image(":widget_r.png"); + box.bottomLeft = new Image(":widget_bl.png"); + box.bottom = new Image(":widget_b.png"); + box.bottomRight = new Image(":widget_br.png"); + box.center = new Image(":widget_c.png"); + + basic.move(box.left->width(), box.top->height()); } -GUI::ListBox::~ListBox() +ListBox::~ListBox() { + delete box.topLeft; + delete box.top; + delete box.topRight; + delete box.left; + delete box.right; + delete box.bottomLeft; + delete box.bottom; + delete box.bottomRight; + delete box.center; } -void GUI::ListBox::addItem(std::string name, std::string value) +void ListBox::addItem(std::string name, std::string value) { - basic->addItem(name, value); + basic.addItem(name, value); } -void GUI::ListBox::addItems(std::vector<ListBoxBasic::Item> &items) +void ListBox::addItems(std::vector<ListBoxBasic::Item> &items) { - basic->addItems(items); + basic.addItems(items); } -void GUI::ListBox::clear() +void ListBox::clear() { - basic->clear(); + basic.clear(); } -bool GUI::ListBox::selectItem(int index) +bool ListBox::selectItem(int index) { - return basic->selectItem(index); + return basic.selectItem(index); } -std::string GUI::ListBox::selectedName() +std::string ListBox::selectedName() { - return basic->selectedName(); + return basic.selectedName(); } -std::string GUI::ListBox::selectedValue() +std::string ListBox::selectedValue() { - return basic->selectedValue(); + return basic.selectedValue(); } -void GUI::ListBox::clearSelectedValue() +void ListBox::clearSelectedValue() { - basic->clearSelectedValue(); + basic.clearSelectedValue(); } -void GUI::ListBox::registerClickHandler(void (*handler)(void *), void *ptr) +void ListBox::repaintEvent(RepaintEvent* repaintEvent) { - basic->registerClickHandler(handler, ptr); -} + Painter p(*this); -void GUI::ListBox::registerSelectHandler(void (*handler)(void *), void *ptr) -{ - basic->registerSelectHandler(handler, ptr); -} + p.clear(); -void GUI::ListBox::registerValueChangeHandler(void (*handler)(void *), - void *ptr) -{ - basic->registerValueChangeHandler(handler, ptr); -} + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } -void GUI::ListBox::repaintEvent(GUI::RepaintEvent *e) -{ - GUI::Painter p(this); - - p.clear(); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) return; - p.drawBox(0, 0, &box, w, h); + p.drawBox(0, 0, box, w, h); } -void GUI::ListBox::resize(int width, int height) +void ListBox::resize(int width, int height) { - GUI::Widget::resize(width, height); - basic->resize(width - (box.left->width() + box.right->width()), - height - (box.top->height() + box.bottom->height())); + Widget::resize(width, height); + basic.resize(width - (box.left->width() + box.right->width()), + height - (box.top->height() + box.bottom->height())); } + +} // GUI:: diff --git a/plugingui/listbox.h b/plugingui/listbox.h index c8677e7..f805fcb 100644 --- a/plugingui/listbox.h +++ b/plugingui/listbox.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_LISTBOX_H__ -#define __DRUMGIZMO_LISTBOX_H__ +#pragma once #include <string.h> #include <vector> @@ -38,31 +37,31 @@ namespace GUI { class ListBox : public Widget { public: - ListBox(Widget *parent); - ~ListBox(); + ListBox(Widget *parent); + ~ListBox(); - void addItem(std::string name, std::string value); - void addItems(std::vector<ListBoxBasic::Item> &items); + void addItem(std::string name, std::string value); + void addItems(std::vector<ListBoxBasic::Item> &items); - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); - void clearSelectedValue(); + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); + void clearSelectedValue(); - void registerSelectHandler(void (*handler)(void *), void *ptr); - void registerClickHandler(void (*handler)(void *), void *ptr); - void registerValueChangeHandler(void (*handler)(void *), void *ptr); + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void resize(int w, int h) override; - virtual void repaintEvent(GUI::RepaintEvent *e); - virtual void resize(int w, int h); + // Forwarded notifiers from ListBoxBasic::basic + Notifier<>& selectionNotifier; + Notifier<>& clickNotifier; + Notifier<>& valueChangedNotifier; private: - ListBoxBasic *basic; + ListBoxBasic basic; - Painter::Box box; + Painter::Box box; }; -}; - -#endif/*__DRUMGIZMO_LISTBOX_H__*/ +} // GUI:: diff --git a/plugingui/listboxbasic.cc b/plugingui/listboxbasic.cc index df7877d..10d6c66 100644 --- a/plugingui/listboxbasic.cc +++ b/plugingui/listboxbasic.cc @@ -1,4 +1,3 @@ - /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * listboxbasic.cc @@ -30,305 +29,332 @@ #include "painter.h" #include "font.h" -#include <stdio.h> -#include <hugin.hpp> - -void scrolled(void *ptr) -{ - GUI::ListBoxBasic *l = (GUI::ListBoxBasic *)ptr; - l->repaintEvent(NULL); -} +namespace GUI { -GUI::ListBoxBasic::ListBoxBasic(GUI::Widget *parent) - : GUI::Widget(parent), scroll(this), bg_img(":widget_c.png") +ListBoxBasic::ListBoxBasic(Widget *parent) + : Widget(parent) + , scroll(this) + , bg_img(":widget_c.png") { - scroll.move(0,0); - scroll.resize(18, 100); + scroll.move(0,0); + scroll.resize(18, 100); - scroll.registerValueChangeHandler(scrolled, this); + CONNECT(&scroll, valueChangeNotifier, + this, &ListBoxBasic::onScrollBarValueChange); - padding = 4; - btn_size = 18; + padding = 4; + btn_size = 18; - selected = -1; - marked = -1; - - clk_handler = NULL; - clk_ptr = NULL; - - sel_handler = NULL; - sel_ptr = NULL; - - valch_handler = NULL; - valch_ptr = NULL; + selected = -1; + marked = -1; } -GUI::ListBoxBasic::~ListBoxBasic() +ListBoxBasic::~ListBoxBasic() { } -void GUI::ListBoxBasic::setSelection(int index) +void ListBoxBasic::setSelection(int index) { - selected = index; - if(valch_handler) valch_handler(valch_ptr); + selected = index; + if(marked == -1) + { + marked = index; + } + valueChangedNotifier(); } -void GUI::ListBoxBasic::addItem(std::string name, std::string value) +void ListBoxBasic::addItem(const std::string& name, const std::string& value) { - std::vector<GUI::ListBoxBasic::Item> items; - GUI::ListBoxBasic::Item item; - item.name = name; - item.value = value; - items.push_back(item); - addItems(items); + std::vector<ListBoxBasic::Item> items; + ListBoxBasic::Item item; + item.name = name; + item.value = value; + items.push_back(item); + addItems(items); } -void GUI::ListBoxBasic::addItems(std::vector<GUI::ListBoxBasic::Item> &is) +void ListBoxBasic::addItems(const std::vector<ListBoxBasic::Item>& newItems) { - // DEBUG(list, "addItems %lu\n", is.size()); - std::vector<GUI::ListBoxBasic::Item>::iterator i = is.begin(); - while(i != is.end()) { - items.push_back(*i); - i++; - } - -/* - // sort - for(int x = 0; x < (int)items.size(); x++) { - for(int y = 0; y < (int)items.size(); y++) { - if(items[x].name < items[y].name) { - if(x == selected) setSelection(y); - else if(selected == y) setSelection(x); - - GUI::ListBoxBasic::Item tmp = items[x]; - items[x] = items[y]; - items[y] = tmp; - } - } - } -*/ - - if(selected == -1) setSelection((int)items.size() - 1); - setSelection(0); - - int numitems = height() / (font.textHeight() + padding); - scroll.setRange(numitems); - scroll.setMaximum(items.size()); + for(auto& item : newItems) + { + items.push_back(item); + } + + if(selected == -1) + { + //setSelection((int)items.size() - 1); + setSelection(0); + } + + int numitems = height() / (font.textHeight() + padding); + scroll.setRange(numitems); + scroll.setMaximum(items.size()); + repaintEvent(nullptr); } -void GUI::ListBoxBasic::clear() +void ListBoxBasic::clear() { - items.clear(); - setSelection(-1); - scroll.setValue(0); - repaintEvent(NULL); + items.clear(); + setSelection(-1); + marked = -1; + scroll.setValue(0); + repaintEvent(nullptr); } -bool GUI::ListBoxBasic::selectItem(int index) +bool ListBoxBasic::selectItem(int index) { - if(index < 0 || index > (int)items.size() - 1) return false; - setSelection(index); - repaintEvent(NULL); - return true; -} + if(index < 0 || (index > (int)items.size() - 1)) + { + return false; + } -std::string GUI::ListBoxBasic::selectedName() -{ - if(selected < 0 || selected > (int)items.size() - 1) return ""; - return items[selected].name; -} + setSelection(index); + repaintEvent(nullptr); -std::string GUI::ListBoxBasic::selectedValue() -{ - if(selected < 0 || selected > (int)items.size() - 1) return ""; - return items[selected].value; + return true; } -void GUI::ListBoxBasic::clearSelectedValue() +std::string ListBoxBasic::selectedName() { - setSelection(-1); + if(selected < 0 || (selected > (int)items.size() - 1)) + { + return ""; + } + + return items[selected].name; } -void GUI::ListBoxBasic::registerClickHandler(void (*handler)(void *), void *ptr) +std::string ListBoxBasic::selectedValue() { - this->clk_handler = handler; - this->clk_ptr = ptr; + if(selected < 0 || (selected > (int)items.size() - 1)) + { + return ""; + } + + return items[selected].value; } -void GUI::ListBoxBasic::registerSelectHandler(void (*handler)(void *), void *ptr) +void ListBoxBasic::clearSelectedValue() { - this->sel_handler = handler; - this->sel_ptr = ptr; + setSelection(-1); } -void GUI::ListBoxBasic::registerValueChangeHandler(void (*handler)(void *), - void *ptr) +void ListBoxBasic::onScrollBarValueChange(int value) { - this->valch_handler = handler; - this->valch_ptr = ptr; + repaintEvent(nullptr); } -void GUI::ListBoxBasic::repaintEvent(GUI::RepaintEvent *e) +void ListBoxBasic::repaintEvent(RepaintEvent* repaintEvent) { - DEBUG(list, "repaint\n"); - GUI::Painter p(this); - - p.clear(); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) return; - - p.drawImageStretched(0, 0, &bg_img, w, h); - - p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); - - int yoffset = padding / 2; - int skip = scroll.value(); - int numitems = height() / (font.textHeight() + padding) + 1; - for(int idx = skip; idx < (int)items.size() && idx < skip + numitems; idx++) { - GUI::ListBoxBasic::Item *i = &items[idx]; - if(idx == selected) { - p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 0.5)); - p.drawFilledRectangle(0, - yoffset - (padding / 2), - width() - 1, - yoffset + (font.textHeight() + 1)); - } - - if(idx == marked) { - p.drawRectangle(0, - yoffset - (padding / 2), - width() - 1, - yoffset + (font.textHeight() + 1)); - } - - p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); - - p.drawText(2, yoffset + font.textHeight(), font, i->name); - yoffset += font.textHeight() + padding; - } + Painter p(*this); + + p.clear(); + + int w = width(); + int h = height(); + + if((w == 0) || (h == 0)) + { + return; + } + + p.drawImageStretched(0, 0, bg_img, w, h); + + p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); + + int yoffset = padding / 2; + int skip = scroll.value(); + int numitems = height() / (font.textHeight() + padding) + 1; + for(int idx = skip; (idx < (int)items.size()) && (idx < (skip + numitems)); + idx++) + { + auto& item = items[idx]; + if(idx == selected) + { + p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 0.5)); + p.drawFilledRectangle(0, + yoffset - (padding / 2), + width() - 1, + yoffset + (font.textHeight() + 1)); + } + + if(idx == marked) + { + p.drawRectangle(0, + yoffset - (padding / 2), + width() - 1, + yoffset + (font.textHeight() + 1)); + } + + p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); + + p.drawText(2, yoffset + font.textHeight(), font, item.name); + yoffset += font.textHeight() + padding; + } } -void GUI::ListBoxBasic::scrollEvent(ScrollEvent *e) +void ListBoxBasic::scrollEvent(ScrollEvent* scrollEvent) { - scroll.scrollEvent(e); + // forward scroll event to scroll bar. + scroll.scrollEvent(scrollEvent); } -void GUI::ListBoxBasic::keyEvent(GUI::KeyEvent *e) +void ListBoxBasic::keyEvent(KeyEvent* keyEvent) { - if(e->direction != -1) return; - - switch(e->keycode) { - case GUI::KeyEvent::KEY_UP: - { - marked--; - if(marked < 0) marked = 0; - - if(marked < scroll.value()) { - scroll.setValue(marked); - } - } - break; - case GUI::KeyEvent::KEY_DOWN: - { - // Number of items that can be displayed at a time. - int numitems = height() / (font.textHeight() + padding); - - marked++; - if(marked > ((int)items.size() - 1)) marked = (int)items.size() - 1; - - if(marked > (scroll.value() + numitems - 1)) { - scroll.setValue(marked - numitems + 1); - } - } - break; - case GUI::KeyEvent::KEY_HOME: - marked = 0; - if(marked < scroll.value()) { - scroll.setValue(marked); - } - break; - case GUI::KeyEvent::KEY_END: - { - // Number of items that can be displayed at a time. - int numitems = height() / (font.textHeight() + padding); - - marked = (int)items.size() - 1; - if(marked > (scroll.value() + numitems - 1)) { - scroll.setValue(marked - numitems + 1); - } - } - break; - case GUI::KeyEvent::KEY_CHARACTER: - if(e->text == " ") { - setSelection(marked); - // if(sel_handler) sel_handler(sel_ptr); - } - break; - case GUI::KeyEvent::KEY_ENTER: - setSelection(marked); - if(sel_handler) sel_handler(sel_ptr); - break; - default: - break; - } - - repaintEvent(NULL); + if(keyEvent->direction != Direction::down) + { + return; + } + + switch(keyEvent->keycode) { + case Key::up: + if(marked == 0) + { + return; + } + + marked--; + + if(marked < scroll.value()) + { + scroll.setValue(marked); + } + break; + + case Key::down: + { + // Number of items that can be displayed at a time. + int numitems = height() / (font.textHeight() + padding); + + if(marked == ((int)items.size() - 1)) + { + return; + } + + marked++; + + if(marked > (scroll.value() + numitems - 1)) + { + scroll.setValue(marked - numitems + 1); + } + } + break; + + case Key::home: + marked = 0; + if(marked < scroll.value()) + { + scroll.setValue(marked); + } + break; + + case Key::end: + { + // Number of items that can be displayed at a time. + int numitems = height() / (font.textHeight() + padding); + + marked = (int)items.size() - 1; + if(marked > (scroll.value() + numitems - 1)) + { + scroll.setValue(marked - numitems + 1); + } + } + break; + + case Key::character: + if(keyEvent->text == " ") + { + setSelection(marked); + //selectionNotifier(); + } + break; + + case Key::enter: + setSelection(marked); + selectionNotifier(); + break; + + default: + break; + } + + repaintEvent(nullptr); } -void GUI::ListBoxBasic::buttonEvent(ButtonEvent *e) +void ListBoxBasic::buttonEvent(ButtonEvent* buttonEvent) { - if(e->x > ((int)width() - btn_size) && e->y < ((int)width() - 1)) { - if(e->y > 0 && e->y < btn_size) { - if(e->direction == -1) return; - scroll.setValue(scroll.value() - 1); - return; - } - - if(e->y > ((int)height() - btn_size) && e->y < ((int)height() - 1)) { - if(e->direction == -1) return; - scroll.setValue(scroll.value() + 1); - return; - } - } - - if(e->direction == -1) { - int skip = scroll.value(); - size_t yoffset = padding / 2; - for(int idx = skip; idx < (int)items.size(); idx++) { - yoffset += font.textHeight() + padding; - if(e->y < (int)yoffset - (padding / 2)) { - setSelection(idx); - marked = selected; - if(clk_handler) clk_handler(clk_ptr); - break; - } - } - - repaintEvent(NULL); - } - - if(e->direction != -1) { - int skip = scroll.value(); - size_t yoffset = padding / 2; - for(int idx = skip; idx < (int)items.size(); idx++) { - yoffset += font.textHeight() + padding; - if(e->y < (int)yoffset - (padding / 2)) { - marked = idx; - break; - } - } - - repaintEvent(NULL); - } - - if(e->doubleclick && sel_handler) sel_handler(sel_ptr); + if((buttonEvent->x > ((int)width() - btn_size)) && + (buttonEvent->y < ((int)width() - 1))) + { + if(buttonEvent->y > 0 && buttonEvent->y < btn_size) + { + if(buttonEvent->direction == Direction::up) + { + return; + } + scroll.setValue(scroll.value() - 1); + return; + } + + if(buttonEvent->y > ((int)height() - btn_size) && + buttonEvent->y < ((int)height() - 1)) + { + if(buttonEvent->direction == Direction::up) + { + return; + } + scroll.setValue(scroll.value() + 1); + return; + } + } + + if(buttonEvent->direction == Direction::up) + { + int skip = scroll.value(); + size_t yoffset = padding / 2; + for(int idx = skip; idx < (int)items.size(); idx++) + { + yoffset += font.textHeight() + padding; + if(buttonEvent->y < (int)yoffset - (padding / 2)) + { + setSelection(idx); + marked = selected; + clickNotifier(); + break; + } + } + + repaintEvent(nullptr); + } + + if(buttonEvent->direction != Direction::up) + { + int skip = scroll.value(); + size_t yoffset = padding / 2; + for(int idx = skip; idx < (int)items.size(); idx++) + { + yoffset += font.textHeight() + padding; + if(buttonEvent->y < ((int)yoffset - (padding / 2))) + { + marked = idx; + break; + } + } + + repaintEvent(nullptr); + } + + if(buttonEvent->doubleClick) + { + selectionNotifier(); + } } -void GUI::ListBoxBasic::resize(int w, int h) +void ListBoxBasic::resize(int w, int h) { - GUI::Widget::resize(w,h); - scroll.move(w - scroll.width(), 0); - scroll.resize(scroll.width(), h); + Widget::resize(w,h); + scroll.move(w - scroll.width(), 0); + scroll.resize(scroll.width(), h); } + +} // GUI:: diff --git a/plugingui/listboxbasic.h b/plugingui/listboxbasic.h index deb4a67..3a190da 100644 --- a/plugingui/listboxbasic.h +++ b/plugingui/listboxbasic.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_LISTBOXBASIC_H__ -#define __DRUMGIZMO_LISTBOXBASIC_H__ +#pragma once #include <string.h> #include <vector> @@ -33,69 +32,62 @@ #include "widget.h" #include "font.h" #include "painter.h" - #include "scrollbar.h" +#include "notifier.h" namespace GUI { class ListBoxBasic : public Widget { public: - class Item { - public: - std::string name; - std::string value; - }; - - ListBoxBasic(Widget *parent); - ~ListBoxBasic(); - - bool isFocusable() { return true; } + class Item { + public: + std::string name; + std::string value; + }; - void addItem(std::string name, std::string value); - void addItems(std::vector<Item> &items); + ListBoxBasic(Widget *parent); + ~ListBoxBasic(); - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); + void addItem(const std::string& name, const std::string& value); + void addItems(const std::vector<Item>& items); - void clearSelectedValue(); + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); - void registerSelectHandler(void (*handler)(void *), void *ptr); - void registerClickHandler(void (*handler)(void *), void *ptr); - void registerValueChangeHandler(void (*handler)(void *), void *ptr); + void clearSelectedValue(); - virtual void repaintEvent(RepaintEvent *e); - virtual void buttonEvent(ButtonEvent *e); - virtual void scrollEvent(ScrollEvent *e); - virtual void keyEvent(KeyEvent *e); - virtual void resize(int w, int h); + Notifier<> selectionNotifier; + Notifier<> clickNotifier; + Notifier<> valueChangedNotifier; -private: - ScrollBar scroll; + // From Widget: + virtual void resize(int w, int h) override; - Image bg_img; +protected: + void onScrollBarValueChange(int value); - void setSelection(int index); + // From Widget: + bool isFocusable() override { return true; } + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void keyEvent(KeyEvent* keyEvent) override; + virtual void scrollEvent(ScrollEvent* scrollEvent) override; - std::vector<Item> items; + ScrollBar scroll; - int selected; - int marked; - GUI::Font font; - int padding; - int btn_size; + Image bg_img; - void (*sel_handler)(void *); - void *sel_ptr; + void setSelection(int index); - void (*clk_handler)(void *); - void *clk_ptr; - - void (*valch_handler)(void *); - void *valch_ptr; -}; + std::vector<Item> items; + int selected; + int marked; + Font font; + int padding; + int btn_size; }; -#endif/*__DRUMGIZMO_LISTBOXBASIC_H__*/ +} // GUI:: diff --git a/plugingui/listboxthin.cc b/plugingui/listboxthin.cc index 3f0fbc6..16ea49e 100644 --- a/plugingui/listboxthin.cc +++ b/plugingui/listboxthin.cc @@ -29,90 +29,92 @@ #include "painter.h" #include "font.h" -#include <stdio.h> - -GUI::ListBoxThin::ListBoxThin(GUI::Widget *parent) - : GUI::Widget(parent) +namespace GUI { + +ListBoxThin::ListBoxThin(Widget *parent) + : Widget(parent) + , selectionNotifier(basic.selectionNotifier) + , clickNotifier(basic.clickNotifier) + , valueChangedNotifier(basic.valueChangedNotifier) + , basic(this) { - box.topLeft = new Image(":thinlistbox_tl.png"); - box.top = new Image(":thinlistbox_t.png"); - box.topRight = new Image(":thinlistbox_tr.png"); - box.left = new Image(":thinlistbox_l.png"); - box.right = new Image(":thinlistbox_r.png"); - box.bottomLeft = new Image(":thinlistbox_bl.png"); - box.bottom = new Image(":thinlistbox_b.png"); - box.bottomRight = new Image(":thinlistbox_br.png"); - box.center = new Image(":thinlistbox_c.png"); - - basic = new GUI::ListBoxBasic(this); - basic->move(box.left->width(), box.top->height()); + box.topLeft = new Image(":thinlistbox_tl.png"); + box.top = new Image(":thinlistbox_t.png"); + box.topRight = new Image(":thinlistbox_tr.png"); + box.left = new Image(":thinlistbox_l.png"); + box.right = new Image(":thinlistbox_r.png"); + box.bottomLeft = new Image(":thinlistbox_bl.png"); + box.bottom = new Image(":thinlistbox_b.png"); + box.bottomRight = new Image(":thinlistbox_br.png"); + box.center = new Image(":thinlistbox_c.png"); + + basic.move(box.left->width(), box.top->height()); } -GUI::ListBoxThin::~ListBoxThin() +ListBoxThin::~ListBoxThin() { + delete box.topLeft; + delete box.top; + delete box.topRight; + delete box.left; + delete box.right; + delete box.bottomLeft; + delete box.bottom; + delete box.bottomRight; + delete box.center; } -void GUI::ListBoxThin::addItem(std::string name, std::string value) +void ListBoxThin::addItem(std::string name, std::string value) { - basic->addItem(name, value); + basic.addItem(name, value); } -void GUI::ListBoxThin::addItems(std::vector<ListBoxBasic::Item> &items) +void ListBoxThin::addItems(std::vector<ListBoxBasic::Item> &items) { - basic->addItems(items); + basic.addItems(items); } -void GUI::ListBoxThin::clear() +void ListBoxThin::clear() { - basic->clear(); + basic.clear(); } -bool GUI::ListBoxThin::selectItem(int index) +bool ListBoxThin::selectItem(int index) { - return basic->selectItem(index); + return basic.selectItem(index); } -std::string GUI::ListBoxThin::selectedName() +std::string ListBoxThin::selectedName() { - return basic->selectedName(); + return basic.selectedName(); } -std::string GUI::ListBoxThin::selectedValue() +std::string ListBoxThin::selectedValue() { - return basic->selectedValue(); + return basic.selectedValue(); } -void GUI::ListBoxThin::registerClickHandler(void (*handler)(void *), void *ptr) +void ListBoxThin::repaintEvent(RepaintEvent* repaintEvent) { - basic->registerClickHandler(handler, ptr); -} + Painter p(*this); -void GUI::ListBoxThin::registerSelectHandler(void (*handler)(void *), void *ptr) -{ - basic->registerSelectHandler(handler, ptr); -} + p.clear(); -void GUI::ListBoxThin::registerValueChangeHandler(void (*handler)(void *), - void *ptr) -{ - basic->registerValueChangeHandler(handler, ptr); -} + int w = width(); + int h = height(); + if(w == 0 || h == 0) + { + return; + } -void GUI::ListBoxThin::repaintEvent(GUI::RepaintEvent *e) -{ - GUI::Painter p(this); - - p.clear(); - - int w = width(); - int h = height(); - if(w == 0 || h == 0) return; - p.drawBox(0, 0, &box, w, h); + p.drawBox(0, 0, box, w, h); } -void GUI::ListBoxThin::resize(int width, int height) +void ListBoxThin::resize(int width, int height) { - GUI::Widget::resize(width, height); - basic->resize(width - (box.left->width() + box.right->width()), - height - (box.top->height() + box.bottom->height())); + Widget::resize(width, height); + basic.resize(width - (box.left->width() + box.right->width()), + height - (box.top->height() + box.bottom->height())); } + +} // GUI:: diff --git a/plugingui/listboxthin.h b/plugingui/listboxthin.h index 9c5363a..bc9399b 100644 --- a/plugingui/listboxthin.h +++ b/plugingui/listboxthin.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_LISTBOXTHIN_H__ -#define __DRUMGIZMO_LISTBOXTHIN_H__ +#pragma once #include <string.h> #include <vector> @@ -33,35 +32,36 @@ #include "widget.h" #include "painter.h" #include "listboxbasic.h" +#include "notifier.h" namespace GUI { class ListBoxThin : public Widget { public: - ListBoxThin(Widget *parent); - ~ListBoxThin(); + ListBoxThin(Widget *parent); + ~ListBoxThin(); - void addItem(std::string name, std::string value); - void addItems(std::vector<ListBoxBasic::Item> &items); + void addItem(std::string name, std::string value); + void addItems(std::vector<ListBoxBasic::Item> &items); - void clear(); - bool selectItem(int index); - std::string selectedName(); - std::string selectedValue(); + void clear(); + bool selectItem(int index); + std::string selectedName(); + std::string selectedValue(); - void registerSelectHandler(void (*handler)(void *), void *ptr); - void registerClickHandler(void (*handler)(void *), void *ptr); - void registerValueChangeHandler(void (*handler)(void *), void *ptr); + // From Widget: + virtual void repaintEvent(GUI::RepaintEvent* repaintEvent) override; + virtual void resize(int w, int h) override; - virtual void repaintEvent(GUI::RepaintEvent *e); - virtual void resize(int w, int h); + // Forwarded notifier from ListBoxBasic::basic + Notifier<>& selectionNotifier; + Notifier<>& clickNotifier; + Notifier<>& valueChangedNotifier; private: - ListBoxBasic *basic; + ListBoxBasic basic; - Painter::Box box; + Painter::Box box; }; -}; - -#endif/*__DRUMGIZMO_LISTBOXTHIN_H__*/ +} // GUI:: diff --git a/plugingui/nativewindow.h b/plugingui/nativewindow.h index d68909d..a44693c 100644 --- a/plugingui/nativewindow.h +++ b/plugingui/nativewindow.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_NATIVEWINDOW_H__ -#define __DRUMGIZMO_NATIVEWINDOW_H__ +#pragma once #include <string> @@ -33,25 +32,53 @@ namespace GUI { +//! \brief Interface class for native window implementations. class NativeWindow { public: - NativeWindow() {} - virtual ~NativeWindow() {} - - virtual void setFixedSize(int width, int height) = 0; - virtual void resize(int width, int height) = 0; - virtual void move(int x, int y) = 0; - virtual void show() = 0; - virtual void setCaption(const std::string &caption) = 0; - virtual void hide() = 0; - virtual void handleBuffer() = 0; - virtual void redraw() = 0; - virtual void grabMouse(bool grab) = 0; - - virtual bool hasEvent() = 0; - virtual Event *getNextEvent() = 0; -}; + NativeWindow() {} + virtual ~NativeWindow() {} + + //! \brief Set a fixed size to the window. + //! It resizes the window and disallows user resizing. + virtual void setFixedSize(int width, int height) = 0; + + // TODO: setScalable(bool) ?? + + //! \brief Set a new size of the window. + virtual void resize(int width, int height) = 0; + + //! \brief Move the window to a new position. + virtual void move(int x, int y) = 0; + + //! \brief Show the window if it is hidden. + virtual void show() = 0; + + //! \brief Hides the window. + virtual void hide() = 0; + + //! \brief Sets the window caption in the title bar (if it has one). + virtual void setCaption(const std::string &caption) = 0; + + //! \brief Recreate a window render buffer based on the internal buffer. + //! This need to be called whenever the internal buffer size has changed. + virtual void handleBuffer() = 0; + + //! \brief Draw the internal rendering buffer to the window buffer. + virtual void redraw() = 0; + + //! \brief Toggle capture mouse mode. + virtual void grabMouse(bool grab) = 0; + + //! \brief Query if the event queue contains any events. + virtual bool hasEvent() = 0; + + //! \brief Read a single event from the event queue. + //! \return A pointer to the event or nullptr is none exists. + virtual Event *getNextEvent() = 0; + //! \brief Read next event without popping it from the event queue. + //! \return A pointer to the event or nullptr is none exists. + virtual Event* peekNextEvent() = 0; }; -#endif/*__DRUMGIZMO_NATIVEWINDOW_H__*/ +} // GUI:: diff --git a/plugingui/nativewindow_pugl.cc b/plugingui/nativewindow_pugl.cc index 45cddab..b9dcd54 100644 --- a/plugingui/nativewindow_pugl.cc +++ b/plugingui/nativewindow_pugl.cc @@ -29,184 +29,228 @@ #include <stdlib.h> #include <list> -#include "hugin.hpp" +#ifdef __APPLE__ +#include <OpenGL/glu.h> +#else +#include <GL/glu.h> +#include <GL/glext.h> +#include <GL/gl.h> +#endif + +#include "window.h" #include "guievent.h" -static GUI::Window* windowptr; -static std::list<GUI::Event*> eventq; +#include <hugin.hpp> -static void onDisplay(PuglView* view) +namespace GUI { + +void NativeWindowPugl::onDisplay(PuglView* view) { + NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); + Window* windowptr = native->window; - glDisable(GL_DEPTH_TEST); - glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT); - GLuint image; + GLuint image; - glGenTextures(1, &image); + glGenTextures(1, &image); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //GL_NEAREST = no smoothing - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //GL_NEAREST = no smoothing + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, windowptr->wpixbuf.width, - windowptr->wpixbuf.height, 0, GL_RGB, GL_UNSIGNED_BYTE, - windowptr->wpixbuf.buf); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, windowptr->wpixbuf.width, + windowptr->wpixbuf.height, 0, GL_RGB, GL_UNSIGNED_BYTE, + windowptr->wpixbuf.buf); - glEnable(GL_TEXTURE_2D); - - glBegin(GL_QUADS); - glTexCoord2d(0.0, 0.0); glVertex2f(0.0, 0.0); - glTexCoord2d(0.0, 1.0); glVertex2f(0.0, windowptr->wpixbuf.height); - glTexCoord2d(1.0, 1.0); glVertex2f(windowptr->wpixbuf.width, windowptr->wpixbuf.height); - glTexCoord2d(1.0, 0.0); glVertex2f(windowptr->wpixbuf.width, 0.0); - glEnd(); + glEnable(GL_TEXTURE_2D); - glDeleteTextures(1, &image); - glDisable(GL_TEXTURE_2D); - glFlush(); - - puglPostRedisplay(view); -} + glBegin(GL_QUADS); + glTexCoord2d(0.0, 0.0); glVertex2f(0.0, 0.0); + glTexCoord2d(0.0, 1.0); glVertex2f(0.0, windowptr->wpixbuf.height); + glTexCoord2d(1.0, 1.0); glVertex2f(windowptr->wpixbuf.width, windowptr->wpixbuf.height); + glTexCoord2d(1.0, 0.0); glVertex2f(windowptr->wpixbuf.width, 0.0); + glEnd(); -static void onMouse(PuglView* view, int button, bool press, int x, int y) -{ - DEBUG(nativewindow_pugl, "Mouse %d %s at (%d,%d)\n", button, - press? "down":"up", x, y); + glDeleteTextures(1, &image); + glDisable(GL_TEXTURE_2D); + glFlush(); - GUI::ButtonEvent* e = new GUI::ButtonEvent(); - e->x = x; - e->y = y; - e->button = button; - e->direction = press?1:-1; - e->doubleclick = false; + puglPostRedisplay(view); +} - eventq.push_back(e); +void NativeWindowPugl::onMouse(PuglView* view, int button, bool press, int x, int y) +{ + NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); + + DEBUG(nativewindow_pugl, "Mouse %d %s at (%d,%d)\n", button, + press? "down":"up", x, y); + + ButtonEvent* e = new ButtonEvent(); + e->x = x; + e->y = y; + + switch(button) { + case 1: + e->button = MouseButton::left; + break; + case 2: + e->button = MouseButton::middle; + break; + case 3: + default: + e->button = MouseButton::right; + break; + } + + e->direction = press ? Direction::down : Direction::up; + e->doubleClick = false; + + native->eventq.push_back(e); } -static void onKeyboard(PuglView* view, bool press, uint32_t key) +void NativeWindowPugl::onKeyboard(PuglView* view, bool press, uint32_t key) { - if(press) { - GUI::KeyEvent* e = new GUI::KeyEvent(); - e->direction = press?-1:1; + NativeWindowPugl* native = (NativeWindowPugl*)puglGetHandle(view); + + KeyEvent* e = new KeyEvent(); + e->direction = press ? Direction::down : Direction::up; + + printf("%d\n", key); - printf("%d\n", key); - - switch(key) { - case PUGL_KEY_LEFT: e->keycode = GUI::KeyEvent::KEY_LEFT; break; - case PUGL_KEY_RIGHT: e->keycode = GUI::KeyEvent::KEY_RIGHT; break; - case PUGL_KEY_UP: e->keycode = GUI::KeyEvent::KEY_UP; break; - case PUGL_KEY_DOWN: e->keycode = GUI::KeyEvent::KEY_DOWN; break; - case PUGL_KEY_PAGE_UP: e->keycode = GUI::KeyEvent::KEY_PGDOWN; break; - case PUGL_KEY_PAGE_DOWN: e->keycode = GUI::KeyEvent::KEY_PGUP; break; - default: e->keycode = GUI::KeyEvent::KEY_UNKNOWN; break; - } + switch(key) { + case PUGL_KEY_LEFT: e->keycode = Key::left; break; + case PUGL_KEY_RIGHT: e->keycode = Key::right; break; + case PUGL_KEY_UP: e->keycode = Key::up; break; + case PUGL_KEY_DOWN: e->keycode = Key::down; break; + case PUGL_KEY_PAGE_UP: e->keycode = Key::pageDown; break; + case PUGL_KEY_PAGE_DOWN: e->keycode = Key::pageUp; break; + default: e->keycode = Key::unknown; break; + } - // TODO: perform character type check - if(e->keycode == GUI::KeyEvent::KEY_UNKNOWN) { - e->keycode = GUI::KeyEvent::KEY_CHARACTER; - e->text.assign(1, (char)key); - } + // TODO: perform character type check + if(e->keycode == Key::unknown) + { + e->keycode = Key::character; + e->text.assign(1, (char)key); + } - printf("\t text: %s\n", e->text.c_str()); - - eventq.push_back(e); - } + printf("\t text: %s\n", e->text.c_str()); + + native->eventq.push_back(e); } -GUI::NativeWindowPugl::NativeWindowPugl(GUI::Window *window) - : GUI::NativeWindow() +NativeWindowPugl::NativeWindowPugl(Window *window) + : window(window) { - INFO(nativewindow, "Running with PuGL native window\n"); - this->window = window; - windowptr = window; - view = NULL; - init(); + INFO(nativewindow, "Running with PuGL native window\n"); + init(); } -GUI::NativeWindowPugl::~NativeWindowPugl() +NativeWindowPugl::~NativeWindowPugl() { - puglDestroy(view); + puglDestroy(view); } -void GUI::NativeWindowPugl::init() { - PuglView* old = view; - if(view) old = view; -// view = puglCreate(0, "DrumgGizmo", window->x(), window->y(), false, true); - view = puglCreate(0, "DrumgGizmo", 370, 330, false, true); - puglSetDisplayFunc(view, onDisplay); - puglSetMouseFunc(view, onMouse); - puglSetKeyboardFunc(view, onKeyboard); +void NativeWindowPugl::init() { + PuglView* oldView = view; + if(view) + { + oldView = view; + } + +// view = puglCreate(0, "DrumgGizmo", window->x(), window->y(), false, true); + view = puglCreate(0, "DrumgGizmo", 370, 330, false, true); + puglSetHandle(view, (PuglHandle)this); + puglSetDisplayFunc(view, onDisplay); + puglSetMouseFunc(view, onMouse); + puglSetKeyboardFunc(view, onKeyboard); + + if(oldView) + { + free(oldView); + } +} - if(old) free(old); +void NativeWindowPugl::setFixedSize(int width, int height) +{ +// redraw(); } -void GUI::NativeWindowPugl::setFixedSize(int width, int height) +void NativeWindowPugl::resize(int width, int height) { -// redraw(); +// DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height); +// init(); +// redraw(); } -void GUI::NativeWindowPugl::resize(int width, int height) +void NativeWindowPugl::move(int x, int y) { -// DEBUG(nativewindow_pugl, "Resizing to %dx%d\n", width, height); -// init(); -// redraw(); +// redraw(); } -void GUI::NativeWindowPugl::move(int x, int y) +void NativeWindowPugl::show() { -// redraw(); +// redraw(); } -void GUI::NativeWindowPugl::show() +void NativeWindowPugl::hide() { -// redraw(); +// redraw(); } -void GUI::NativeWindowPugl::hide() +void NativeWindowPugl::handleBuffer() { -// redraw(); + onDisplay(view); } -void GUI::NativeWindowPugl::handleBuffer() +void NativeWindowPugl::redraw() { - onDisplay(view); +// handleBuffer(); } -void GUI::NativeWindowPugl::redraw() +void NativeWindowPugl::setCaption(const std::string &caption) { -// handleBuffer(); +// redraw(); } -void GUI::NativeWindowPugl::setCaption(const std::string &caption) +void NativeWindowPugl::grabMouse(bool grab) { -// redraw(); +// redraw(); } -void GUI::NativeWindowPugl::grabMouse(bool grab) +bool NativeWindowPugl::hasEvent() { -// redraw(); + // dirty hack - assume that this function is called enough times to get fluent gui + // ^^ Bad assumption + puglProcessEvents(view); + return !eventq.empty(); } -bool GUI::NativeWindowPugl::hasEvent() +Event *NativeWindowPugl::getNextEvent() { - // dirty hack - assume that this function is called enough times to get fluent gui - // ^^ Bad assumption - puglProcessEvents(view); - return !eventq.empty(); + Event *event = nullptr; + + if(!eventq.empty()) { + event = eventq.front(); + eventq.pop_front(); + } + return event; } -GUI::Event *GUI::NativeWindowPugl::getNextEvent() +Event *NativeWindowPugl::peekNextEvent() { - Event *event = NULL; - - if(!eventq.empty()) { - event = eventq.front(); - eventq.pop_front(); - } - return event; + Event *event = nullptr; + + if(!eventq.empty()) { + event = eventq.front(); + } + return event; } + +} // GUI:: diff --git a/plugingui/nativewindow_pugl.h b/plugingui/nativewindow_pugl.h index cf761fd..335e7e4 100644 --- a/plugingui/nativewindow_pugl.h +++ b/plugingui/nativewindow_pugl.h @@ -24,49 +24,48 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_NATIVEWINDOW_PUGL_H__ -#define __DRUMGIZMO_NATIVEWINDOW_PUGL_H__ -#endif/*__DRUMGIZMO_NATIVEWINDOW_PUGL_H__*/ +#pragma once #include "nativewindow.h" - -#include "window.h" - #include "pugl.h" -#ifdef __APPLE__ -# include <OpenGL/glu.h> -#else -# include <GL/glu.h> -# include <GL/glext.h> -# include <GL/gl.h> -#endif +#include <list> namespace GUI { +class Event; class Window; + class NativeWindowPugl : public NativeWindow { public: - NativeWindowPugl(GUI::Window *window); - ~NativeWindowPugl(); + NativeWindowPugl(Window *window); + ~NativeWindowPugl(); - void init(); - void setFixedSize(int width, int height); - void resize(int width, int height); - void move(int x, int y); - void show(); - void setCaption(const std::string &caption); - void hide(); - void handleBuffer(); - void redraw(); - void grabMouse(bool grab); + void init(); + void setFixedSize(int width, int height); + void resize(int width, int height); + void move(int x, int y); + void show(); + void setCaption(const std::string &caption); + void hide(); + void handleBuffer(); + void redraw(); + void grabMouse(bool grab); - bool hasEvent(); - Event *getNextEvent(); + bool hasEvent(); + Event *getNextEvent(); + Event *peekNextEvent(); private: - GUI::Window *window; - PuglView* view; -}; + Window* window{nullptr}; + PuglView* view{nullptr}; + + std::list<Event*> eventq; + // Internal pugl c-callbacks + static void onDisplay(PuglView* view); + static void onMouse(PuglView* view, int button, bool press, int x, int y); + static void onKeyboard(PuglView* view, bool press, uint32_t key); }; + +} // GUI:: diff --git a/plugingui/nativewindow_win32.cc b/plugingui/nativewindow_win32.cc index 871bafe..cf39010 100644 --- a/plugingui/nativewindow_win32.cc +++ b/plugingui/nativewindow_win32.cc @@ -26,49 +26,56 @@ */ #include "nativewindow_win32.h" -#ifdef WIN32 - #include "window.h" -LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +#include <cstring> + +namespace GUI { + +LRESULT CALLBACK NativeWindowWin32::dialogProc(HWND hwnd, UINT msg, + WPARAM wp, LPARAM lp) { - GUI::NativeWindowWin32 *native = - (GUI::NativeWindowWin32 *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + NativeWindowWin32* native = + (NativeWindowWin32*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - // NOTE: 'native' is NULL intil the WM_CREATE message has been handled. - if(!native) return DefWindowProc(hwnd, msg, wp, lp); + // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled. + if(!native) + { + return DefWindowProc(hwnd, msg, wp, lp); + } - GUI::Window *window = native->window; + Window& window = native->window; switch(msg) { case WM_SIZE: - { - static bool first = true; - if(!first) { - GUI::ResizeEvent *e = new GUI::ResizeEvent(); - e->width = LOWORD(lp); - e->height = HIWORD(lp); - native->event = e; - first = false; - } - } + { + static bool first = true; + if(!first) + { + ResizeEvent* resizeEvent = new ResizeEvent(); + resizeEvent->width = LOWORD(lp); + resizeEvent->height = HIWORD(lp); + native->event = resizeEvent; + first = false; + } + } break; case WM_MOVE: - { -// GUI::MoveEvent *e = new GUI::MoveEvent(); -// e->x = (int)(short) LOWORD(lp); -// e->y = (int)(short) HIWORD(lp); -// native->event = e; - } + { +// MoveEvent* moveEvent = new MoveEvent(); +// moveEvent->x = (short)LOWORD(lp); +// moveEvent->y = (short)HIWORD(lp); +// native->event = moveEvent; + } break; case WM_CLOSE: - { - GUI::CloseEvent *e = new GUI::CloseEvent(); - native->event = e; - } - break; + { + CloseEvent* closeEvent = new CloseEvent(); + native->event = closeEvent; + } + break; // HWND child, old; // old = 0; @@ -83,31 +90,30 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) // else PostQuitMessage(0); // return 0; case WM_MOUSEMOVE: - { - - GUI::MouseMoveEvent *e = new GUI::MouseMoveEvent(); - e->x = (int)(short) LOWORD(lp); - e->y = (int)(short) HIWORD(lp); - native->event = e; - } + { + MouseMoveEvent* mouseMoveEvent = new MouseMoveEvent(); + mouseMoveEvent->x = (short)LOWORD(lp); + mouseMoveEvent->y = (short)HIWORD(lp); + native->event = mouseMoveEvent; + } break; case WM_MOUSEWHEEL: - { - GUI::ScrollEvent *e = new GUI::ScrollEvent(); - - // NOTE: lp is coordinates in screen space, not client space. - POINT p; - p.x = (int)(short) LOWORD(lp); - p.y = (int)(short) HIWORD(lp); - ScreenToClient(hwnd, &p); - - e->x = p.x; - e->y = p.y; - e->delta = -1 * (short)HIWORD(wp) / 60; - native->event = e; - } - break; + { + ScrollEvent* scrollEvent = new ScrollEvent(); + + // NOTE: lp is coordinates in screen space, not client space. + POINT p; + p.x = (short)LOWORD(lp); + p.y = (short)HIWORD(lp); + ScreenToClient(hwnd, &p); + + scrollEvent->x = p.x; + scrollEvent->y = p.y; + scrollEvent->delta = -1 * (short)HIWORD(wp) / 60; + native->event = scrollEvent; + } + break; case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: @@ -118,283 +124,324 @@ LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) case WM_MBUTTONUP: case WM_MBUTTONDBLCLK: case WM_MBUTTONDOWN: - { - GUI::ButtonEvent *e = new GUI::ButtonEvent(); - e->x = (int)(short) LOWORD(lp); - e->y = (int)(short) HIWORD(lp); - - if(msg == WM_LBUTTONUP || - msg == WM_LBUTTONDBLCLK || - msg == WM_LBUTTONDOWN) e->button = 0; - - if(msg == WM_RBUTTONUP || - msg == WM_RBUTTONDBLCLK || - msg == WM_RBUTTONDOWN) e->button = 1; - - if(msg == WM_MBUTTONUP || - msg == WM_MBUTTONDBLCLK || - msg == WM_MBUTTONDOWN) e->button = 2; - - e->direction = 0; - if(msg == WM_LBUTTONUP || - msg == WM_RBUTTONUP || - msg == WM_MBUTTONUP) e->direction = -1; - - if(msg == WM_LBUTTONDOWN || - msg == WM_RBUTTONDOWN || - msg == WM_MBUTTONDOWN) e->direction = 1; - - e->doubleclick = (msg == WM_LBUTTONDBLCLK || - msg == WM_RBUTTONDBLCLK || - msg == WM_MBUTTONDBLCLK); - - native->event = e; - } + { + ButtonEvent* buttonEvent = new ButtonEvent(); + + buttonEvent->x = (short)LOWORD(lp); + buttonEvent->y = (short)HIWORD(lp); + + if(msg == WM_LBUTTONUP || + msg == WM_LBUTTONDBLCLK || + msg == WM_LBUTTONDOWN) + { + buttonEvent->button = MouseButton::left; + } + else if(msg == WM_RBUTTONUP || + msg == WM_RBUTTONDBLCLK || + msg == WM_RBUTTONDOWN) + { + buttonEvent->button = MouseButton::middle; + } + else if(msg == WM_MBUTTONUP || + msg == WM_MBUTTONDBLCLK || + msg == WM_MBUTTONDOWN) + { + buttonEvent->button = MouseButton::right; + } + else + { + delete buttonEvent; + break; // unknown button + } + + if(msg == WM_LBUTTONUP || + msg == WM_RBUTTONUP || + msg == WM_MBUTTONUP) + { + buttonEvent->direction = Direction::up; + } + else if(msg == WM_LBUTTONDOWN || + msg == WM_RBUTTONDOWN || + msg == WM_MBUTTONDOWN) + { + buttonEvent->direction = Direction::down; + } + + buttonEvent->doubleClick = (msg == WM_LBUTTONDBLCLK || + msg == WM_RBUTTONDBLCLK || + msg == WM_MBUTTONDBLCLK); + + native->event = buttonEvent; + } break; case WM_KEYDOWN: - { - GUI::KeyEvent *e = new GUI::KeyEvent(); - //printf("wp: %d\n", wp); - switch(wp) { - case 37: e->keycode = GUI::KeyEvent::KEY_LEFT; break; - case 39: e->keycode = GUI::KeyEvent::KEY_RIGHT; break; - case 38: e->keycode = GUI::KeyEvent::KEY_UP; break; - case 40: e->keycode = GUI::KeyEvent::KEY_DOWN; break; - case 8: e->keycode = GUI::KeyEvent::KEY_BACKSPACE; break; - case 46: e->keycode = GUI::KeyEvent::KEY_DELETE; break; - case 36: e->keycode = GUI::KeyEvent::KEY_HOME; break; - case 35: e->keycode = GUI::KeyEvent::KEY_END; break; - case 33: e->keycode = GUI::KeyEvent::KEY_PGUP; break; - case 34: e->keycode = GUI::KeyEvent::KEY_PGDOWN; break; - case 13: e->keycode = GUI::KeyEvent::KEY_ENTER; break; - default: e->keycode = GUI::KeyEvent::KEY_UNKNOWN; break; - } - e->text = ""; - e->direction = -1; - native->event = e; - } + case WM_KEYUP: + { + KeyEvent* keyEvent = new KeyEvent(); + + switch(wp) { + case VK_LEFT: keyEvent->keycode = Key::left; break; + case VK_RIGHT: keyEvent->keycode = Key::right; break; + case VK_UP: keyEvent->keycode = Key::up; break; + case VK_DOWN: keyEvent->keycode = Key::down; break; + case VK_BACK: keyEvent->keycode = Key::backspace; break; + case VK_DELETE: keyEvent->keycode = Key::deleteKey; break; + case VK_HOME: keyEvent->keycode = Key::home; break; + case VK_END: keyEvent->keycode = Key::end; break; + case VK_PRIOR: keyEvent->keycode = Key::pageUp; break; + case VK_NEXT: keyEvent->keycode = Key::pageDown; break; + case VK_RETURN: keyEvent->keycode = Key::enter; break; + default: keyEvent->keycode = Key::unknown; break; + } + + keyEvent->text = ""; + keyEvent->direction = + (msg == WM_KEYDOWN) ? Direction::down : Direction::up; + + native->event = keyEvent; + } break; case WM_CHAR: - { - //printf("WM_CHAR %d %d\n", (int)lp, (int)wp); - if(wp >= ' ') { // Filter control chars. - GUI::KeyEvent *e = new GUI::KeyEvent(); - e->keycode = GUI::KeyEvent::KEY_CHARACTER; - e->text += (char)wp; - e->direction = -1; - native->event = e; - } - } + { + if(wp >= ' ') // Filter control chars. + { + KeyEvent* keyEvent = new KeyEvent(); + keyEvent->keycode = Key::character; + keyEvent->text += (char)wp; + keyEvent->direction = Direction::up; + native->event = keyEvent; + } + } break; case WM_PAINT: - { - GUI::RepaintEvent *e = new GUI::RepaintEvent(); - e->x = 0; - e->y = 0; - e->width = 100; - e->height = 100; - native->event = e; - - // Move to window.h (in class) - HDC pDC; - HBITMAP old; - HBITMAP ourbitmap; - int * framebuf; - GUI::PixelBuffer &px = window->wpixbuf; - - { // Create bitmap (move to window.cc) - HDC hDC; - BITMAPINFO bitmapinfo; - hDC = CreateCompatibleDC(NULL); - bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bitmapinfo.bmiHeader.biWidth = px.width; - bitmapinfo.bmiHeader.biHeight = -px.height; /* top-down */ - bitmapinfo.bmiHeader.biPlanes = 1; - bitmapinfo.bmiHeader.biBitCount = 32; - bitmapinfo.bmiHeader.biCompression = BI_RGB; - bitmapinfo.bmiHeader.biSizeImage = 0; - bitmapinfo.bmiHeader.biClrUsed = 256; - bitmapinfo.bmiHeader.biClrImportant = 256; - ourbitmap=CreateDIBSection(hDC, &bitmapinfo, - DIB_RGB_COLORS, (void**)&framebuf, 0, 0); - pDC=CreateCompatibleDC(NULL); - old = (HBITMAP__*)SelectObject(pDC, ourbitmap); - DeleteDC(hDC); - } - - { // Copy GUI::PixelBuffer to framebuffer (move to window.cc) - int i,j,k; - for (k=0,i=0;i<(int)px.height;i++) { - for (j=0;j<(int)px.width;j++,k++) { - *(framebuf+k)=RGB(px.buf[(j + i * px.width) * 3 + 2], - px.buf[(j + i * px.width) * 3 + 1], - px.buf[(j + i * px.width) * 3 + 0]); - } - } - } - - PAINTSTRUCT ps; - HDC hdc = BeginPaint(native->m_hwnd, &ps); - BitBlt(hdc, 0, 0, px.width, px.height, pDC, 0, 0, SRCCOPY); - EndPaint(native->m_hwnd, &ps); - - { // Destroy bitmap (move to window.cc) - SelectObject(pDC,old); - DeleteDC(pDC); - DeleteObject(ourbitmap); - - } - } + { + RepaintEvent* repaintEvent = new RepaintEvent(); + repaintEvent->x = 0; + repaintEvent->y = 0; + repaintEvent->width = 100; + repaintEvent->height = 100; + native->event = repaintEvent; + + // Move to window.h (in class) + HDC pDC; + HBITMAP old; + HBITMAP ourbitmap; + int* framebuf; + PixelBuffer& px = window.wpixbuf; + + { // Create bitmap + HDC hDC; + BITMAPINFO bitmapinfo; + hDC = CreateCompatibleDC(nullptr); + bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapinfo.bmiHeader.biWidth = px.width; + bitmapinfo.bmiHeader.biHeight = -px.height; // top-down + bitmapinfo.bmiHeader.biPlanes = 1; + bitmapinfo.bmiHeader.biBitCount = 32; + bitmapinfo.bmiHeader.biCompression = BI_RGB; + bitmapinfo.bmiHeader.biSizeImage = 0; + bitmapinfo.bmiHeader.biClrUsed = 256; + bitmapinfo.bmiHeader.biClrImportant = 256; + ourbitmap = CreateDIBSection(hDC, &bitmapinfo, + DIB_RGB_COLORS, (void**)&framebuf, 0, 0); + pDC=CreateCompatibleDC(nullptr); + old = (HBITMAP__*)SelectObject(pDC, ourbitmap); + DeleteDC(hDC); + } + + { // Copy PixelBuffer to framebuffer + int i, j, k; + for(k = 0, i = 0; i < (int)px.height; ++i) + { + for(j = 0; j < (int)px.width; ++j, ++k) + { + *(framebuf + k) = RGB(px.buf[(j + i * px.width) * 3 + 2], + px.buf[(j + i * px.width) * 3 + 1], + px.buf[(j + i * px.width) * 3 + 0]); + } + } + } + + PAINTSTRUCT ps; + HDC hdc = BeginPaint(native->m_hwnd, &ps); + BitBlt(hdc, 0, 0, px.width, px.height, pDC, 0, 0, SRCCOPY); + EndPaint(native->m_hwnd, &ps); + + { // Destroy bitmap (move to window.cc) + SelectObject(pDC,old); + DeleteDC(pDC); + DeleteObject(ourbitmap); + } + } + return DefWindowProc(hwnd, msg, wp, lp); } return DefWindowProc(hwnd, msg, wp, lp); } -// Delared in eventhandler.cc -LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); - -GUI::NativeWindowWin32::NativeWindowWin32(GUI::Window *window) - : GUI::NativeWindow() +NativeWindowWin32::NativeWindowWin32(Window& window) + : window(window) { - this->window = window; - WNDCLASSEX wcex; WNDID wndId; - m_hwnd = 0; - m_className = NULL; - event = NULL; + std::memset(&wcex, 0, sizeof(wcex)); - memset(&wcex, 0, sizeof(wcex)); - //Time to register a window class. - //Generic flags and everything. cbWndExtra is the size of a pointer to an - // object - we need this in the wndproc handler. - + //Generic flags and everything. cbWndExtra is the size of a pointer to an + // object - we need this in the wndproc handler. + wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_DBLCLKS;//class_style; wcex.lpfnWndProc = (WNDPROC)dialogProc; - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - // Set data: + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + // Set data: wcex.cbWndExtra = sizeof(NativeWindowWin32*); // Size of data. - wcex.hInstance = GetModuleHandle(NULL); + wcex.hInstance = GetModuleHandle(nullptr); - // if(ex_style && WS_EX_TRANSPARENT == WS_EX_TRANSPARENT) { - // wcex.hbrBackground = NULL; - // } else { - wcex.hbrBackground = NULL;//(HBRUSH) COLOR_BACKGROUND + 1; - // } - - wcex.lpszClassName = m_className = strdup("DrumGizmoClass"); + // if(ex_style && WS_EX_TRANSPARENT == WS_EX_TRANSPARENT) { + // wcex.hbrBackground = nullptr; + // } else { + wcex.hbrBackground = nullptr;//(HBRUSH) COLOR_BACKGROUND + 1; + // } + + const char* name = "DrumGizmoClass"; + char* c_name = (char*)malloc(strlen(name) + 1); + strcpy(c_name, name); + wcex.lpszClassName = m_className = c_name; RegisterClassEx(&wcex); - /* + /* if(parent) { style = style | WS_CHILD; wndId = parent->getWndId(); } else { - */ - //style = style | WS_OVERLAPPEDWINDOW; - wndId = 0; - // } + */ + //style = style | WS_OVERLAPPEDWINDOW; + wndId = 0; + // } m_hwnd = CreateWindowEx(0/*ex_style*/, m_className, - "DGBasisWidget", - (WS_OVERLAPPEDWINDOW | WS_VISIBLE), - window->x(), window->y(), - window->width(), window->height(), - wndId, NULL, - GetModuleHandle(NULL), NULL); + "DGBasisWidget", + (WS_OVERLAPPEDWINDOW | WS_VISIBLE), + window.x(), window.y(), + window.width(), window.height(), + wndId, nullptr, + GetModuleHandle(nullptr), nullptr); SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); } -GUI::NativeWindowWin32::~NativeWindowWin32() +NativeWindowWin32::~NativeWindowWin32() { - UnregisterClass(m_className, GetModuleHandle(NULL)); + UnregisterClass(m_className, GetModuleHandle(nullptr)); free(m_className); } -void GUI::NativeWindowWin32::setFixedSize(int width, int height) +void NativeWindowWin32::setFixedSize(int width, int height) { - resize(width, height); - LONG style = GetWindowLong(m_hwnd, GWL_STYLE); - style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); - SetWindowLong(m_hwnd, GWL_STYLE, style); + resize(width, height); + LONG style = GetWindowLong(m_hwnd, GWL_STYLE); + style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); + SetWindowLong(m_hwnd, GWL_STYLE, style); } -void GUI::NativeWindowWin32::resize(int width, int height) +void NativeWindowWin32::resize(int width, int height) { - SetWindowPos(m_hwnd, NULL, -1, -1, (int)width, (int)height, SWP_NOMOVE); - RECT r; - GetClientRect(m_hwnd, &r); - int w = width - r.right; - int h = height - r.bottom; + SetWindowPos(m_hwnd, nullptr, -1, -1, (int)width, (int)height, SWP_NOMOVE); + RECT r; + GetClientRect(m_hwnd, &r); + int w = width - r.right; + int h = height - r.bottom; - SetWindowPos(m_hwnd, NULL, -1, -1, width + w, height + h, SWP_NOMOVE); + SetWindowPos(m_hwnd, nullptr, -1, -1, width + w, height + h, SWP_NOMOVE); } -void GUI::NativeWindowWin32::move(int x, int y) +void NativeWindowWin32::move(int x, int y) { - SetWindowPos(m_hwnd, NULL, (int)x, (int)y, -1, -1, SWP_NOSIZE); + SetWindowPos(m_hwnd, nullptr, (int)x, (int)y, -1, -1, SWP_NOSIZE); } -void GUI::NativeWindowWin32::show() +void NativeWindowWin32::show() { - ShowWindow(m_hwnd, SW_SHOW); + ShowWindow(m_hwnd, SW_SHOW); } -void GUI::NativeWindowWin32::handleBuffer() +void NativeWindowWin32::handleBuffer() { } -void GUI::NativeWindowWin32::hide() +void NativeWindowWin32::hide() { - ShowWindow(m_hwnd, SW_HIDE); + ShowWindow(m_hwnd, SW_HIDE); } -void GUI::NativeWindowWin32::redraw() +void NativeWindowWin32::redraw() { - RedrawWindow(m_hwnd, NULL, NULL, RDW_ERASE|RDW_INVALIDATE); - UpdateWindow(m_hwnd); + RedrawWindow(m_hwnd, nullptr, nullptr, RDW_ERASE|RDW_INVALIDATE); + UpdateWindow(m_hwnd); } -void GUI::NativeWindowWin32::setCaption(const std::string &caption) +void NativeWindowWin32::setCaption(const std::string &caption) { - SetWindowText(m_hwnd, caption.c_str()); + SetWindowText(m_hwnd, caption.c_str()); +} + +void NativeWindowWin32::grabMouse(bool grab) +{ + if(grab) + { + SetCapture(m_hwnd); + } + else + { + ReleaseCapture(); + } } -void GUI::NativeWindowWin32::grabMouse(bool grab) +bool NativeWindowWin32::hasEvent() { - if(grab) SetCapture(m_hwnd); - else ReleaseCapture(); + MSG msg; + return PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE) != 0; } -bool GUI::NativeWindowWin32::hasEvent() +Event* NativeWindowWin32::getNextEvent() { - MSG msg; - return PeekMessage(&msg, NULL, 0, 0, 0) != 0; + Event* event = nullptr; + + MSG msg; + if(GetMessage(&msg, nullptr, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + event = this->event; + this->event = nullptr; + + return event; } -GUI::Event *GUI::NativeWindowWin32::getNextEvent() +Event* NativeWindowWin32::peekNextEvent() { - Event *event = NULL; + Event* event = nullptr; - MSG msg; - if(GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + MSG msg; + if(PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); } - event = this->event; - this->event = NULL; + event = this->event; + this->event = nullptr; - return event; + return event; } -#endif/*WIN32*/ +} // GUI:: diff --git a/plugingui/nativewindow_win32.h b/plugingui/nativewindow_win32.h index 6afc7b1..fa4b6bc 100644 --- a/plugingui/nativewindow_win32.h +++ b/plugingui/nativewindow_win32.h @@ -24,13 +24,11 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_NATIVEWINDOW_WIN32_H__ -#define __DRUMGIZMO_NATIVEWINDOW_WIN32_H__ - -#ifdef WIN32 +#pragma once #include "nativewindow.h" +#define WIN32_LEAN_AND_MEAN #include <windows.h> typedef HWND WNDID; @@ -41,31 +39,30 @@ class Event; class NativeWindowWin32 : public NativeWindow { public: - NativeWindowWin32(GUI::Window *window); - ~NativeWindowWin32(); + NativeWindowWin32(Window& window); + ~NativeWindowWin32(); - void setFixedSize(int width, int height); - void resize(int width, int height); - void move(int x, int y); - void show(); - void setCaption(const std::string &caption); - void hide(); - void handleBuffer(); - void redraw(); - void grabMouse(bool grab); + void setFixedSize(int width, int height) override; + void resize(int width, int height) override; + void move(int x, int y) override; + void show() override; + void setCaption(const std::string &caption) override; + void hide() override; + void handleBuffer() override; + void redraw() override; + void grabMouse(bool grab) override; - bool hasEvent(); - Event *getNextEvent(); + bool hasEvent() override; + Event* getNextEvent() override; + Event* peekNextEvent() override; - // Needed by dialogProc - GUI::Window *window; - WNDID m_hwnd; - char *m_className; - Event *event; -}; +private: + static LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); + Window& window; + WNDID m_hwnd = 0; + char* m_className = nullptr; + Event* event = nullptr; }; -#endif/*WIN32*/ - -#endif/*__DRUMGIZMO_NATIVEWINDOW_WIN32_H__*/ +} // GUI:: diff --git a/plugingui/nativewindow_x11.cc b/plugingui/nativewindow_x11.cc index cb6cf73..a0316b9 100644 --- a/plugingui/nativewindow_x11.cc +++ b/plugingui/nativewindow_x11.cc @@ -26,105 +26,152 @@ */ #include "nativewindow_x11.h" -#ifdef X11 #include <X11/Xutil.h> #include <stdlib.h> +#include <hugin.hpp> + #include "window.h" -GUI::NativeWindowX11::NativeWindowX11(GUI::Window *window) - : GUI::NativeWindow() +namespace GUI { + +NativeWindowX11::NativeWindowX11(Window& window) + : buffer(nullptr) + , window(window) { - display = XOpenDisplay(NULL); - - this->window = window; - buffer = NULL; - - // Get some colors - int blackColor = BlackPixel(display, DefaultScreen(display)); - - ::Window w = DefaultRootWindow(display); - - // Create the window - xwindow = XCreateSimpleWindow(display, - w, - window->x(), window->y(), - window->width(), window->height(), - 0, - blackColor, blackColor); - - XSelectInput(display, xwindow, - StructureNotifyMask | - PointerMotionMask | - ButtonPressMask | - ButtonReleaseMask | - KeyPressMask | - KeyReleaseMask| - ExposureMask | - StructureNotifyMask | - SubstructureNotifyMask); - - // register interest in the delete window message - wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false); - XSetWMProtocols(display, xwindow, &wmDeleteMessage, 1); - - // "Map" the window (that is, make it appear on the screen) - XMapWindow(display, xwindow); - - // Create a "Graphics Context" - gc = XCreateGC(display, xwindow, 0, NULL); + auto status = XInitThreads(); + if(status) + { + ERR(X11, "Could not initialise threaded Xlib calls (XInitThreads)"); + } + + display = XOpenDisplay(nullptr); + if(display == nullptr) + { + ERR(X11, "XOpenDisplay failed"); + return; + } + + screen = DefaultScreen(display); + + // Get some colors + int blackColor = BlackPixel(display, screen); + + ::Window rootWindow = DefaultRootWindow(display); + + // Create the window + unsigned long border = 0; + xwindow = XCreateSimpleWindow(display, + rootWindow, + window.x(), window.y(), + window.width(), window.height(), + border, + blackColor, blackColor); + + long mask = (StructureNotifyMask | + PointerMotionMask | + ButtonPressMask | + ButtonReleaseMask | + KeyPressMask | + KeyReleaseMask| + ExposureMask | + StructureNotifyMask | + SubstructureNotifyMask); + XSelectInput(display, xwindow, mask); + + // Register the delete window message: + wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", false); + + Atom protocols[] = { wmDeleteMessage }; + int count = sizeof(protocols)/sizeof(Atom); + XSetWMProtocols(display, xwindow, protocols, count); + + // "Map" the window (that is, make it appear on the screen) + XMapWindow(display, xwindow); + + // Create a "Graphics Context" + gc = XCreateGC(display, xwindow, 0, nullptr); } -GUI::NativeWindowX11::~NativeWindowX11() +NativeWindowX11::~NativeWindowX11() { - XDestroyWindow(display, xwindow); - //widgets.erase(window); - XCloseDisplay(display); + if(display == nullptr) + { + return; + } + + XDestroyWindow(display, xwindow); + XCloseDisplay(display); } -void GUI::NativeWindowX11::setFixedSize(int width, int height) +void NativeWindowX11::setFixedSize(int width, int height) { - resize(width, height); - - XSizeHints *size_hints; - size_hints = XAllocSizeHints(); - - if(size_hints == NULL) { - //fprintf(stderr,"XMallocSizeHints() failed\n"); - //exit(1); - return; - } - - size_hints->flags = USPosition | PMinSize | PMaxSize; - size_hints->min_width = size_hints->max_width = width; - size_hints->min_height = size_hints->max_height = height; - /* - size_hints->min_aspect.x = window->width()/window->height(); - size_hints->max_aspect.x = window->width()/window->height(); - size_hints->min_aspect.y = window->width()/window->height(); - size_hints->max_aspect.y = size_hints->min_aspect.y; - */ - XSetWMNormalHints(display, xwindow, size_hints); + if(display == nullptr) + { + return; + } + + resize(width, height); + + XSizeHints* size_hints; + size_hints = XAllocSizeHints(); + + if(size_hints == nullptr) + { + ERR(X11,"XMallocSizeHints() failed"); + return; + } + + size_hints->flags = USPosition | PMinSize | PMaxSize; + size_hints->min_width = size_hints->max_width = width; + size_hints->min_height = size_hints->max_height = height; + + //size_hints->min_aspect.x = (float)window.width()/(float)window.height(); + //size_hints->max_aspect.x = (float)window.width()/(float)window.height(); + //size_hints->min_aspect.y = (float)window.width()/(float)window.height(); + //size_hints->max_aspect.y = size_hints->min_aspect.y; + + XSetWMNormalHints(display, xwindow, size_hints); } -void GUI::NativeWindowX11::resize(int width, int height) +void NativeWindowX11::resize(int width, int height) { - XResizeWindow(display, xwindow, width, height); + if(display == nullptr) + { + return; + } + + XResizeWindow(display, xwindow, width, height); } -void GUI::NativeWindowX11::move(int x, int y) +void NativeWindowX11::move(int x, int y) { - XMoveWindow(display, xwindow, x, y); + if(display == nullptr) + { + return; + } + + XMoveWindow(display, xwindow, x, y); } -void GUI::NativeWindowX11::show() +void NativeWindowX11::show() { - XMapWindow(display, xwindow); + if(display == nullptr) + { + return; + } + + XMapWindow(display, xwindow); } -void GUI::NativeWindowX11::hide() +void NativeWindowX11::hide() { - XUnmapWindow(display, xwindow); + if(display == nullptr) + { + return; + } + + XUnmapWindow(display, xwindow); } static int get_byte_order (void) @@ -135,254 +182,345 @@ static int get_byte_order (void) } order; order.s = 1; - if ((1 == order.c[0])) { + if((1 == order.c[0])) + { return LSBFirst; - } else { + } + else + { return MSBFirst; } } -static XImage *create_image_from_buffer(Display *dis, int screen, - unsigned char *buf, - int width, int height) +XImage* NativeWindowX11::createImageFromBuffer(unsigned char* buf, + int width, int height) { int depth; - XImage *img = NULL; - Visual *vis; + XImage* img = nullptr; + Visual* vis; double rRatio; double gRatio; double bRatio; - int outIndex = 0; + int outIndex = 0; int i; int numBufBytes = (3 * (width * height)); - - depth = DefaultDepth(dis, screen); - vis = DefaultVisual(dis, screen); + + depth = DefaultDepth(display, screen); + vis = DefaultVisual(display, screen); rRatio = vis->red_mask / 255.0; gRatio = vis->green_mask / 255.0; bRatio = vis->blue_mask / 255.0; - - if (depth >= 24) { + + if(depth >= 24) + { size_t numNewBufBytes = (4 * (width * height)); u_int32_t *newBuf = (u_int32_t *)malloc (numNewBufBytes); - - for (i = 0; i < numBufBytes; ++i) { + + for(i = 0; i < numBufBytes; ++i) + { unsigned int r, g, b; r = (buf[i] * rRatio); ++i; g = (buf[i] * gRatio); ++i; b = (buf[i] * bRatio); - - r &= vis->red_mask; - g &= vis->green_mask; - b &= vis->blue_mask; - - newBuf[outIndex] = r | g | b; - ++outIndex; - } - - img = XCreateImage (dis, - CopyFromParent, depth, - ZPixmap, 0, - (char *) newBuf, - width, height, - 32, 0 - ); - - } else if (depth >= 15) { - size_t numNewBufBytes = (2 * (width * height)); - u_int16_t *newBuf = (u_int16_t *)malloc (numNewBufBytes); - - for (i = 0; i < numBufBytes; ++i) { - unsigned int r, g, b; - r = (buf[i] * rRatio); - ++i; - g = (buf[i] * gRatio); - ++i; - b = (buf[i] * bRatio); - r &= vis->red_mask; g &= vis->green_mask; b &= vis->blue_mask; - + newBuf[outIndex] = r | g | b; ++outIndex; - } - - img = XCreateImage(dis, CopyFromParent, depth, ZPixmap, 0, (char *) newBuf, - width, height, 16, 0); - } else { - //fprintf (stderr, "This program does not support displays with a depth less than 15."); - return NULL; + } + + img = XCreateImage (display, + CopyFromParent, depth, + ZPixmap, 0, + (char*) newBuf, + width, height, + 32, 0); + } + else + { + if(depth >= 15) + { + size_t numNewBufBytes = (2 * (width * height)); + u_int16_t* newBuf = (u_int16_t*)malloc (numNewBufBytes); + + for(i = 0; i < numBufBytes; ++i) + { + unsigned int r, g, b; + + r = (buf[i] * rRatio); + ++i; + g = (buf[i] * gRatio); + ++i; + b = (buf[i] * bRatio); + + r &= vis->red_mask; + g &= vis->green_mask; + b &= vis->blue_mask; + + newBuf[outIndex] = r | g | b; + ++outIndex; + } + + img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, + (char*)newBuf, width, height, 16, 0); + } + else + { + //fprintf (stderr, "This program does not support displays with a depth less than 15."); + return nullptr; + } } XInitImage (img); - /*Set the client's byte order, so that XPutImage knows what to do with the data.*/ - /*The default in a new X image is the server's format, which may not be what we want.*/ - if ((LSBFirst == get_byte_order ())) { + + // Set the client's byte order, so that XPutImage knows what + // to do with the data. + // The default in a new X image is the server's format, which + // may not be what we want. + if((LSBFirst == get_byte_order ())) + { img->byte_order = LSBFirst; - } else { + } + else + { img->byte_order = MSBFirst; } - - /*The bitmap_bit_order doesn't matter with ZPixmap images.*/ + + // The bitmap_bit_order doesn't matter with ZPixmap images. img->bitmap_bit_order = MSBFirst; return img; -} +} -void GUI::NativeWindowX11::handleBuffer() +void NativeWindowX11::handleBuffer() { - if(buffer) XDestroyImage(buffer); - buffer = - create_image_from_buffer(display, DefaultScreen(display), - window->wpixbuf.buf, - window->wpixbuf.width, - window->wpixbuf.height); + if(buffer) + { + XDestroyImage(buffer); + } + + buffer = createImageFromBuffer(window.wpixbuf.buf, + window.wpixbuf.width, + window.wpixbuf.height); } -void GUI::NativeWindowX11::redraw() +void NativeWindowX11::redraw() { - // http://stackoverflow.com/questions/6384987/load-image-onto-a-window-using-xlib - if(buffer == NULL) window->updateBuffer(); - XPutImage(display, xwindow, gc, buffer, 0, 0, 0, 0, - window->width(), window->height()); - XFlush(display); + if(display == nullptr) + { + return; + } + + if(buffer == nullptr) + { + window.updateBuffer(); + } + + XPutImage(display, xwindow, gc, buffer, 0, 0, 0, 0, + window.width(), window.height()); + XFlush(display); +} + +void NativeWindowX11::setCaption(const std::string &caption) +{ + if(display == nullptr) + { + return; + } + + XStoreName(display, xwindow, caption.c_str()); } -void GUI::NativeWindowX11::setCaption(const std::string &caption) +void NativeWindowX11::grabMouse(bool grab) { - XStoreName(display, xwindow, caption.c_str()); + (void)grab; + // Don't need to do anything on this platform... } -void GUI::NativeWindowX11::grabMouse(bool grab) +bool NativeWindowX11::hasEvent() { - (void)grab; - // Don't need to do anything on this platoform... + if(display == nullptr) + { + return false; + } + + return XPending(display); } -bool GUI::NativeWindowX11::hasEvent() +Event* NativeWindowX11::getNextEvent() { - return XPending(display); + if(display == nullptr) + { + return nullptr; + } + + XEvent xEvent; + XNextEvent(display, &xEvent); + return translateXMessage(xEvent); } -GUI::Event *GUI::NativeWindowX11::getNextEvent() +Event* NativeWindowX11::peekNextEvent() { - Event *event = NULL; - - XEvent xe; - XNextEvent(display, &xe); - - if(xe.type == MotionNotify) { - while(true) { // Hack to make sure only the last event is played. - if(!hasEvent()) break; - XEvent nxe; - XPeekEvent(display, &nxe); - if(nxe.type != MotionNotify) break; - XNextEvent(display, &xe); - } - - MouseMoveEvent *e = new MouseMoveEvent(); - e->window_id = xe.xmotion.window; - e->x = xe.xmotion.x; - e->y = xe.xmotion.y; - event = e; - } - - if(xe.type == Expose && xe.xexpose.count == 0) { - RepaintEvent *e = new RepaintEvent(); - e->window_id = xe.xexpose.window; - e->x = xe.xexpose.x; - e->y = xe.xexpose.y; - e->width = xe.xexpose.width; - e->height = xe.xexpose.height; - event = e; - } - - if(xe.type == ConfigureNotify) { - ResizeEvent *e = new ResizeEvent(); - e->window_id = xe.xconfigure.window; - // e->x = xe.xconfigure.x; - // e->y = xe.xconfigure.y; - e->width = xe.xconfigure.width; - e->height = xe.xconfigure.height; - event = e; - } - - if(xe.type == ButtonPress || xe.type == ButtonRelease) { - if(xe.xbutton.button == 4 || xe.xbutton.button == 5) { - int scroll = 1; - while(true) { // Hack to make sure only the last event is played. - if(!hasEvent()) break; - XEvent nxe; - XPeekEvent(display, &nxe); - if(nxe.type != ButtonPress && nxe.type != ButtonRelease) break; - scroll += 1; - XNextEvent(display, &xe); - } - ScrollEvent *e = new ScrollEvent(); - e->window_id = xe.xbutton.window; - e->x = xe.xbutton.x; - e->y = xe.xbutton.y; - e->delta = scroll * (xe.xbutton.button==4?-1:1); - event = e; - } else { - ButtonEvent *e = new ButtonEvent(); - e->window_id = xe.xbutton.window; - e->x = xe.xbutton.x; - e->y = xe.xbutton.y; - e->button = 0; - e->direction = xe.type == ButtonPress?1:-1; - e->doubleclick = - xe.type == ButtonPress && (xe.xbutton.time - last_click) < 200; - - if(xe.type == ButtonPress) last_click = xe.xbutton.time; - event = e; - } - } - - if(xe.type == KeyPress || xe.type == KeyRelease) { - //printf("key: %d\n", xe.xkey.keycode); - KeyEvent *e = new KeyEvent(); - e->window_id = xe.xkey.window; - - switch(xe.xkey.keycode) { - case 113: e->keycode = KeyEvent::KEY_LEFT; break; - case 114: e->keycode = KeyEvent::KEY_RIGHT; break; - case 111: e->keycode = KeyEvent::KEY_UP; break; - case 116: e->keycode = KeyEvent::KEY_DOWN; break; - case 119: e->keycode = KeyEvent::KEY_DELETE; break; - case 22: e->keycode = KeyEvent::KEY_BACKSPACE; break; - case 110: e->keycode = KeyEvent::KEY_HOME; break; - case 115: e->keycode = KeyEvent::KEY_END; break; - case 117: e->keycode = KeyEvent::KEY_PGDOWN; break; - case 112: e->keycode = KeyEvent::KEY_PGUP; break; - case 36: e->keycode = KeyEvent::KEY_ENTER; break; - default: e->keycode = KeyEvent::KEY_UNKNOWN; break; - } - - char buf[1024]; - int sz = XLookupString(&xe.xkey, buf, sizeof(buf), NULL, NULL); - if(sz && e->keycode == KeyEvent::KEY_UNKNOWN) { - e->keycode = KeyEvent::KEY_CHARACTER; - } - e->text.append(buf, sz); - - e->direction = xe.type == KeyPress?1:-1; - event = e; - } - - if(xe.type == ClientMessage && - (unsigned int)xe.xclient.data.l[0] == wmDeleteMessage) { - CloseEvent *e = new CloseEvent(); - event = e; - } - - return event; + if(display == nullptr) + { + return nullptr; + } + + XEvent peekXEvent; + XPeekEvent(display, &peekXEvent); + return translateXMessage(peekXEvent, true); } -#endif/*X11*/ + Event* NativeWindowX11::translateXMessage(XEvent& xevent, bool peek) +{ + Event* event = nullptr; + + switch(xevent.type) { + case MotionNotify: + { + auto mouseMoveEvent = new MouseMoveEvent(); + mouseMoveEvent->window_id = xevent.xmotion.window; + mouseMoveEvent->x = xevent.xmotion.x; + mouseMoveEvent->y = xevent.xmotion.y; + event = mouseMoveEvent; + } + break; + + case Expose: + if(xevent.xexpose.count == 0) + { + auto repaintEvent = new RepaintEvent(); + repaintEvent->window_id = xevent.xexpose.window; + repaintEvent->x = xevent.xexpose.x; + repaintEvent->y = xevent.xexpose.y; + repaintEvent->width = xevent.xexpose.width; + repaintEvent->height = xevent.xexpose.height; + event = repaintEvent; + } + break; + + case ConfigureNotify: + { + auto resizeEvent = new ResizeEvent(); + resizeEvent->window_id = xevent.xconfigure.window; + //resizeEvent->x = xevent.xconfigure.x; + //resizeEvent->y = xevent.xconfigure.y; + resizeEvent->width = xevent.xconfigure.width; + resizeEvent->height = xevent.xconfigure.height; + event = resizeEvent; + } + break; + + case ButtonPress: + case ButtonRelease: + { + if((xevent.xbutton.button == 4) || (xevent.xbutton.button == 5)) + { + int scroll = 1; + auto scrollEvent = new ScrollEvent(); + scrollEvent->window_id = xevent.xbutton.window; + scrollEvent->x = xevent.xbutton.x; + scrollEvent->y = xevent.xbutton.y; + scrollEvent->delta = scroll * ((xevent.xbutton.button == 4) ? -1 : 1); + event = scrollEvent; + } + else + { + auto buttonEvent = new ButtonEvent(); + buttonEvent->window_id = xevent.xbutton.window; + buttonEvent->x = xevent.xbutton.x; + buttonEvent->y = xevent.xbutton.y; + switch(xevent.xbutton.button) { + case 1: + buttonEvent->button = MouseButton::left; + break; + case 2: + buttonEvent->button = MouseButton::middle; + break; + case 3: + buttonEvent->button = MouseButton::right; + break; + default: + WARN(X11, "Unknown button %d, setting to MouseButton::left\n", + xevent.xbutton.button); + buttonEvent->button = MouseButton::left; + break; + } + + buttonEvent->direction = + (xevent.type == ButtonPress) ? + Direction::down : Direction::up; + + buttonEvent->doubleClick = + (xevent.type == ButtonPress) && + ((xevent.xbutton.time - last_click) < 200); + + if(!peek && (xevent.type == ButtonPress)) + { + last_click = xevent.xbutton.time; + } + event = buttonEvent; + } + } + break; + + case KeyPress: + case KeyRelease: + { + auto keyEvent = new KeyEvent(); + keyEvent->window_id = xevent.xkey.window; + + switch(xevent.xkey.keycode) { + case 113: keyEvent->keycode = Key::left; break; + case 114: keyEvent->keycode = Key::right; break; + case 111: keyEvent->keycode = Key::up; break; + case 116: keyEvent->keycode = Key::down; break; + case 119: keyEvent->keycode = Key::deleteKey; break; + case 22: keyEvent->keycode = Key::backspace; break; + case 110: keyEvent->keycode = Key::home; break; + case 115: keyEvent->keycode = Key::end; break; + case 117: keyEvent->keycode = Key::pageDown; break; + case 112: keyEvent->keycode = Key::pageUp; break; + case 36: keyEvent->keycode = Key::enter; break; + default: keyEvent->keycode = Key::unknown; break; + } + + char stringBuffer[1024]; + int size = XLookupString(&xevent.xkey, stringBuffer, + sizeof(stringBuffer), nullptr, nullptr); + if(size && keyEvent->keycode == Key::unknown) + { + keyEvent->keycode = Key::character; + } + + keyEvent->text.append(stringBuffer, size); + + keyEvent->direction = + (xevent.type == KeyPress) ? Direction::down : Direction::up; + + event = keyEvent; + } + break; + + case ClientMessage: + if(((unsigned int)xevent.xclient.data.l[0] == wmDeleteMessage)) + { + auto closeEvent = new CloseEvent(); + event = closeEvent; + } + break; + + default: + WARN(X11, "Unhandled xevent.type: %d\n", xevent.type); + break; + } + + return event; +} +} // GUI:: diff --git a/plugingui/nativewindow_x11.h b/plugingui/nativewindow_x11.h index 3dcc0bb..134ab6f 100644 --- a/plugingui/nativewindow_x11.h +++ b/plugingui/nativewindow_x11.h @@ -24,11 +24,8 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_NATIVEWINDOW_X11_H__ -#define __DRUMGIZMO_NATIVEWINDOW_X11_H__ -#endif/*__DRUMGIZMO_NATIVEWINDOW_X11_H__*/ +#pragma once -#ifdef X11 #include <X11/Xlib.h> #include "nativewindow.h" @@ -38,35 +35,38 @@ namespace GUI { class Window; class NativeWindowX11 : public NativeWindow { public: - NativeWindowX11(GUI::Window *window); - ~NativeWindowX11(); + NativeWindowX11(Window& window); + ~NativeWindowX11(); - void setFixedSize(int width, int height); - void resize(int width, int height); - void move(int x, int y); - void show(); - void setCaption(const std::string &caption); - void hide(); - void handleBuffer(); - void redraw(); - void grabMouse(bool grab); - - bool hasEvent(); - Event *getNextEvent(); + // From NativeWindow: + void setFixedSize(int width, int height) override; + void resize(int width, int height) override; + void move(int x, int y) override; + void show() override; + void hide() override; + void setCaption(const std::string &caption) override; + void handleBuffer() override; + void redraw() override; + void grabMouse(bool grab) override; + bool hasEvent() override; + Event* getNextEvent() override; + Event* peekNextEvent() override; private: - ::Window xwindow; - GC gc; - XImage *buffer; + Event* translateXMessage(XEvent& xevent, bool peek = false); + XImage* createImageFromBuffer(unsigned char* buf, int width, int height); - GUI::Window *window; + ::Window xwindow{0}; + GC gc{0}; + XImage* buffer{nullptr}; - int last_click; + Window& window; - Display *display; - Atom wmDeleteMessage; -}; + int last_click{0}; + Display* display{nullptr}; + int screen{0}; + Atom wmDeleteMessage{0}; }; -#endif/*X11*/ +} // GUI:: diff --git a/plugingui/notifier.h b/plugingui/notifier.h new file mode 100644 index 0000000..328ab7d --- /dev/null +++ b/plugingui/notifier.h @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * notifier.h + * + * Thu Sep 3 15:48:39 CEST 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include <functional> +#include <vector> +#include <map> +#include <set> +#include <memory> + +namespace aux +{ + template<int> + struct placeholder + { + }; +} + +namespace std +{ + template<int N> + struct is_placeholder<aux::placeholder<N>> + : integral_constant<int, N+1> + { + }; +} + +namespace aux +{ + // std::integer_sequence introduced in C++14 so remove this once we start requiring that. + + template<int... Ns> + struct int_sequence + { + }; + + template<int N, int... Ns> + struct gen_int_sequence + : gen_int_sequence<N-1, N-1, Ns...> + { + }; + + template<int... Ns> + struct gen_int_sequence<0, Ns...> + : int_sequence<Ns...> + { + }; +}; + + +namespace GUI { + +class Listener; +class NotifierBase { +public: + virtual void disconnect(Listener* object) {} +}; + +class Listener { +public: + virtual ~Listener() + { + for(auto signal : signals) + { + signal->disconnect(this); + } + } + + void registerNotifier(NotifierBase* signal) + { + signals.insert(signal); + } + + void unregisterNotifier(NotifierBase* signal) + { + signals.erase(signal); + } + +private: + std::set<NotifierBase*> signals; +}; + +template<typename... Args> +class Notifier : public NotifierBase { +public: + Notifier() {} + + //! \brief When dtor is called it will automatically disconnect all its listeners. + ~Notifier() + { + for(auto& slot : slots) + { + slot.first->unregisterNotifier(this); + } + } + + using callback_type = std::function<void(Args...)>; + + //! \brief Connect object to this Notifier. + template<typename O, typename F> + void connect(O* p, const F& fn) + { + slots[p] = std::move(construct_mem_fn(fn, p, aux::gen_int_sequence<sizeof...(Args)>{})); + if(p && dynamic_cast<Listener*>(p)) + { + dynamic_cast<Listener*>(p)->registerNotifier(this); + } + } + + //! \brief Disconnect object from this Notifier. + void disconnect(Listener* object) + { + slots.erase(object); + } + + //! \brief Activate this notifier by pretending it is a function. + //! Example: Notifier<int> foo; foo(42); + void operator()(Args... args) + { + for(auto& slot : slots) + { + slot.second(args...); + } + } + +private: + std::map<Listener*, callback_type> slots; + + template<typename F, typename O, int... Ns> + callback_type construct_mem_fn(const F& fn, O* p, aux::int_sequence<Ns...>) const + { + return std::bind(fn, p, aux::placeholder<Ns>{}...); + } + +}; + +} // GUI:: + +#define CONNECT(SRC, SIG, TAR, SLO) (SRC)->SIG.connect(TAR, SLO) diff --git a/plugingui/painter.cc b/plugingui/painter.cc index 842ff11..01fae5d 100644 --- a/plugingui/painter.cc +++ b/plugingui/painter.cc @@ -28,461 +28,494 @@ #include "window.h" -#include <string.h> +#include <cmath> -GUI::Painter::Painter(GUI::Widget *widget) -{ - this->widget = widget; - widget->window()->beginPaint(); - pixbuf = &widget->pixbuf; - colour = Colour(0, 0, 0, 0.5); -} +namespace GUI { -GUI::Painter::~Painter() +Painter::Painter(Widget& widget) + : widget(widget) { - widget->window()->endPaint(); - flush(); -} + if(widget.window()) + { + widget.window()->beginPaint(); + } -void GUI::Painter::setColour(Colour colour) -{ - this->colour = colour; + pixbuf = &widget.pixbuf; + colour = Colour(0, 0, 0, 0.5); } -void GUI::Painter::plot(int x, int y, double c) +Painter::~Painter() { - // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1) - pixbuf->addPixel(x, y, - (unsigned char)(colour.red * 255.0), - (unsigned char)(colour.green * 255.0), - (unsigned char)(colour.blue * 255.0), - (unsigned char)(colour.alpha * 255 * c)); + if(widget.window()) + { + widget.window()->endPaint(); + } + flush(); } -#include <math.h> -double GUI::Painter::ipart(double x) +void Painter::setColour(const Colour& colour) { - return floor(x); //integer part of x' + this->colour = colour; } - -double GUI::Painter::round(double x) -{ - return ipart(x + 0.5); -} - -double GUI::Painter::fpart(double x) -{ - return x - ipart(x);//'fractional part of x' -} - -double GUI::Painter::rfpart(double x) + +static void plot(PixelBufferAlpha* pixbuf, const Colour& colour, + int x, int y, double c) { - return 1 - fpart(x); -} + if((x >= (int)pixbuf->width) || (y >= (int)pixbuf->height)) + { + return; + } + + // plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1) + pixbuf->addPixel(x, y, + (unsigned char)(colour.red * 255.0), + (unsigned char)(colour.green * 255.0), + (unsigned char)(colour.blue * 255.0), + (unsigned char)(colour.alpha * 255 * c)); +} -#define SWAP(x, y) { int tmp = x; x = y; y = tmp; } -void GUI::Painter::drawLine(int x0, int y0, int x1, int y1) +static inline double fpart(double x) { - bool steep = abs(y1 - y0) > abs(x1 - x0); - - if(steep) { - SWAP(x0, y0); - SWAP(x1, y1); - } - if(x0 > x1) { - SWAP(x0, x1); - SWAP(y0, y1); - } - - double dx = x1 - x0; - double dy = y1 - y0; - double gradient = dy / dx; - - // Handle first endpoint: - double xend = round(x0); - double yend = y0 + gradient * (xend - x0); - //double xgap = rfpart(x0 + 0.5); - double xpxl1 = xend; //this will be used in the main loop - double ypxl1 = ipart(yend); - - if(steep) { - plot(ypxl1, xpxl1, 1); - //plot(ypxl1, xpxl1, rfpart(yend) * xgap); - //plot(ypxl1+1, xpxl1, fpart(yend) * xgap); - } else { - plot(xpxl1, ypxl1, 1); - //plot(xpxl1, ypxl1 , rfpart(yend) * xgap); - //plot(xpxl1, ypxl1+1, fpart(yend) * xgap); - } - - double intery = yend + gradient; // first y-intersection for the main loop - - // Handle second endpoint: - xend = round(x1); - yend = y1 + gradient * (xend - x1); - //xgap = fpart(x1 + 0.5); - double xpxl2 = xend; //this will be used in the main loop - double ypxl2 = ipart(yend); - - if(steep) { - plot(ypxl2, xpxl2, 1); - //plot(ypxl2 , xpxl2, rfpart(yend) * xgap); - //plot(ypxl2+1, xpxl2, fpart(yend) * xgap); - } else { - plot(xpxl2, ypxl2, 1); - //plot(xpxl2, ypxl2, rfpart(yend) * xgap); - //plot(xpxl2, ypxl2+1, fpart(yend) * xgap); - } - - // main loop - for(int x = xpxl1 + 1; x <= xpxl2 - 1; x++) { - if(steep) { - plot(ipart(intery) , x, rfpart(intery)); - plot(ipart(intery)+1, x, fpart(intery)); - } else { - plot(x, ipart (intery), rfpart(intery)); - plot(x, ipart (intery)+1, fpart(intery)); - } - intery += gradient; - } + return x - std::floor(x);// fractional part of x } -void GUI::Painter::drawRectangle(int x1, int y1, int x2, int y2) +static inline double rfpart(double x) { - drawLine(x1, y1, x2 - 1, y1); - drawLine(x2, y1, x2, y2 - 1); - drawLine(x1 + 1, y2, x2, y2); - drawLine(x1, y1 + 1, x1, y2); + return 1 - fpart(x); // reverse fractional part of x } -void GUI::Painter::drawFilledRectangle(int x1, int y1, int x2, int y2) +void Painter::drawLine(int x0, int y0, int x1, int y1) { - for(int y = y1; y < y2; y++) { - drawLine(x1, y, x2, y); - } + bool steep = abs(y1 - y0) > abs(x1 - x0); + + if(steep) + { + std::swap(x0, y0); + std::swap(x1, y1); + } + if(x0 > x1) + { + std::swap(x0, x1); + std::swap(y0, y1); + } + + double dx = x1 - x0; + double dy = y1 - y0; + double gradient = dy / dx; + + // Handle first endpoint: + double xend = std::round(x0); + double yend = y0 + gradient * (xend - x0); + + double xpxl1 = xend; // this will be used in the main loop + double ypxl1 = std::floor(yend); + + if(steep) + { + plot(pixbuf, colour, ypxl1, xpxl1, 1); + } + else + { + plot(pixbuf, colour, xpxl1, ypxl1, 1); + } + + double intery = yend + gradient; // first y-intersection for the main loop + + // Handle second endpoint: + xend = std::round(x1); + yend = y1 + gradient * (xend - x1); + + double xpxl2 = xend; // this will be used in the main loop + double ypxl2 = std::floor(yend); + + if(steep) + { + plot(pixbuf, colour, ypxl2, xpxl2, 1); + } + else + { + plot(pixbuf, colour, xpxl2, ypxl2, 1); + } + + // main loop + for(int x = xpxl1 + 1; x <= xpxl2 - 1; ++x) + { + if(steep) + { + plot(pixbuf, colour, std::floor(intery) , x, rfpart(intery)); + plot(pixbuf, colour, std::floor(intery)+1, x, fpart(intery)); + } + else + { + plot(pixbuf, colour, x, std::floor(intery), rfpart(intery)); + plot(pixbuf, colour, x, std::floor(intery)+1, fpart(intery)); + } + intery += gradient; + } } -void GUI::Painter::clear() +void Painter::drawRectangle(int x1, int y1, int x2, int y2) { - for(int x = 0; x < (int)pixbuf->width; x++) { - for(int y = 0; y < (int)pixbuf->height; y++) { - pixbuf->setPixel(x, y, 0, 0, 0, 0); - } - } + drawLine(x1, y1, x2 - 1, y1); + drawLine(x2, y1, x2, y2 - 1); + drawLine(x1 + 1, y2, x2, y2); + drawLine(x1, y1 + 1, x1, y2); } -void GUI::Painter::drawText(int x0, int y0, GUI::Font &font, std::string text, - bool nocolour) +void Painter::drawFilledRectangle(int x1, int y1, int x2, int y2) { - PixelBufferAlpha *textbuf = font.render(text); - if(nocolour) { - for(size_t x = 0; x < textbuf->width; x++) { - for(size_t y = 0; y < textbuf->height; y++) { - unsigned char r,g,b,a; - textbuf->pixel(x, y, &r, &g, &b, &a); - pixbuf->addPixel(x + x0, y + y0 - textbuf->height, r,g,b,a); - } - } - } else { - for(size_t x = 0; x < textbuf->width; x++) { - for(size_t y = 0; y < textbuf->height; y++) { - unsigned char r,g,b,a; - textbuf->pixel(x, y, &r, &g, &b, &a); - pixbuf->addPixel(x + x0, y + y0 - textbuf->height, - colour.red * 255, - colour.green * 255, - colour.blue * 255, - colour.alpha * a); - } - } - } - - delete textbuf; + for(int y = y1; y < y2; ++y) + { + drawLine(x1, y, x2, y); + } } -#include <stdio.h> -void GUI::Painter::drawPoint(int x, int y) +void Painter::clear() { - pixbuf->setPixel(x, y, - (unsigned char)(colour.red * 255.0), - (unsigned char)(colour.green * 255.0), - (unsigned char)(colour.blue * 255.0), - (unsigned char)(colour.alpha * 255.0)); + for(int x = 0; x < (int)pixbuf->width; ++x) + { + for(int y = 0; y < (int)pixbuf->height; ++y) + { + pixbuf->setPixel(x, y, 0, 0, 0, 0); + } + } } -#if 0 -static double distance(double r, double y) +void Painter::drawText(int x0, int y0, const Font& font, + const std::string& text, bool nocolour) { - double real_point = sqrt(pow(r, 2) - pow(y, 2)); - return ceil(real_point) - real_point; + PixelBufferAlpha* textbuf = font.render(text); + + y0 -= textbuf->height; // The y0 offset (baseline) is the bottom of the text. + + // If the text offset is outside the buffer; skip it. + if((x0 > (int)pixbuf->width) || (y0 > (int)pixbuf->height)) + { + delete textbuf; + return; + } + + // Make sure we don't try to draw outside the pixbuf. + int renderWidth = textbuf->width; + if(renderWidth > (int)(pixbuf->width - x0)) + { + renderWidth = pixbuf->width - x0; + } + + int renderHeight = textbuf->height; + if(renderHeight > ((int)pixbuf->height - y0)) + { + renderHeight = ((int)pixbuf->height - y0); + } + + if(nocolour) + { + for(int y = 0; y < renderHeight; ++y) + { + for(int x = 0; x < renderWidth; ++x) + { + unsigned char r, g, b, a; + textbuf->pixel(x, y, &r, &g, &b, &a); + pixbuf->addPixel(x + x0, y + y0, r, g, b, a); + } + } + } + else + { + for(int y = 0; y < renderHeight; ++y) + { + for(int x = 0; x < renderWidth; ++x) + { + unsigned char r,g,b,a; + textbuf->pixel(x, y, &r, &g, &b, &a); + pixbuf->addPixel(x + x0, y + y0, + colour.red * 255, + colour.green * 255, + colour.blue * 255, + colour.alpha * a); + } + } + } + + delete textbuf; } -double new_color(double i) { - return i * 127; +void Painter::drawPoint(int x, int y) +{ + pixbuf->setPixel(x, y, + (unsigned char)(colour.red * 255.0), + (unsigned char)(colour.green * 255.0), + (unsigned char)(colour.blue * 255.0), + (unsigned char)(colour.alpha * 255.0)); } -void GUI::Painter::drawCircle(int cx, int cy, double radius) +static void plot4points(Painter *p, int cx, int cy, int x, int y) { - // wu_circle($image, $r, $color, $offset_x = null, $offset_y = null) { - //$red = $color["red"]; - //$green = $color["green"]; - //$blue = $color["blue"]; - int offset_x = cx; - int offset_y = cy; - int x = radius; - // int xx = radius; - int y = -1; - // int yy = -1; - double t = 0; - //$color = imagecolorallocate($image, $red, $green, $blue); - while(x > y) { - y++; - double current_distance = distance(radius, y); - if(current_distance < t) { - x--; - } - - double trasparency = new_color(current_distance); - double alpha = trasparency; - double alpha2 = 127.0 - trasparency; - - double color = 1; - - plot(x + offset_x, y + offset_y, color); - plot(x + offset_x - 1, y + offset_y, alpha2 ); - plot(x + offset_x + 1, y + offset_y, alpha ); - - plot(y + offset_x, x + offset_y, color); - plot(y + offset_x, x + offset_y - 1, alpha2); - plot(y + offset_x, x + offset_y + 1, alpha); - - plot(offset_x - x , y + offset_y, color); - plot(offset_x - x + 1, y + offset_y, alpha2); - plot(offset_x - x - 1, y + offset_y, alpha); - - plot(offset_x - y, x + offset_y, color); - plot(offset_x - y, x + offset_y - 1, alpha2); - plot(offset_x - y, x + offset_y + 1, alpha); - - plot(x + offset_x, offset_y - y, color); - plot(x + offset_x - 1, offset_y - y, alpha2); - plot(x + offset_x + 1, offset_y - y, alpha); - - plot(y + offset_x, offset_y - x, color); - plot(y + offset_x, offset_y - x - 1, alpha); - plot(y + offset_x, offset_y - x + 1, alpha2); - - plot(offset_x - y, offset_y - x, color); - plot(offset_x - y, offset_y - x - 1, alpha); - plot(offset_x - y, offset_y - x + 1, alpha2); - - plot(offset_x - x, offset_y - y, color); - plot(offset_x - x - 1, offset_y - y, alpha); - plot(offset_x - x + 1, offset_y - y, alpha2); - - t = current_distance; - } + p->drawPoint(cx + x, cy + y); + if(x != 0) + { + p->drawPoint(cx - x, cy + y); + } + + if(y != 0) + { + p->drawPoint(cx + x, cy - y); + } + + if(x != 0 && y != 0) + { + p->drawPoint(cx - x, cy - y); + } } -#else -static void plot4points(GUI::Painter *p, int cx, int cy, int x, int y) + +void Painter::drawCircle(int cx, int cy, double radius) { - p->drawPoint(cx + x, cy + y); - if(x != 0) p->drawPoint(cx - x, cy + y); - if(y != 0) p->drawPoint(cx + x, cy - y); - if(x != 0 && y != 0) p->drawPoint(cx - x, cy - y); + int error = -radius; + int x = radius; + int y = 0; + + while(x >= y) + { + plot4points(this, cx, cy, x, y); + + if(x != y) + { + plot4points(this, cx, cy, y, x); + } + + error += y; + ++y; + error += y; + + if(error >= 0) + { + --x; + error -= x; + error -= x; + } + } } -void GUI::Painter::drawCircle(int cx, int cy, double radius) +static void plot4lines(Painter *p, int cx, int cy, int x, int y) { - int error = -radius; - int x = radius; - int y = 0; - - while(x >= y) { - plot4points(this, cx, cy, x, y); - if(x != y) plot4points(this, cx, cy, y, x); - - error += y; - ++y; - error += y; - - if(error >= 0) { - --x; - error -= x; - error -= x; - } - } + p->drawLine(cx + x, cy + y, cx - x, cy + y); + if(x != 0) + { + p->drawLine(cx - x, cy + y, cx + x, cy + y); + } + + if(y != 0) + { + p->drawLine(cx + x, cy - y, cx - x, cy - y); + } + + if(x != 0 && y != 0) + { + p->drawLine(cx - x, cy - y, cx + x, cy - y); + } } -#endif -static void plot4lines(GUI::Painter *p, int cx, int cy, int x, int y) +void Painter::drawFilledCircle(int cx, int cy, int radius) { - p->drawLine(cx + x, cy + y, cx - x, cy + y); - if(x != 0) p->drawLine(cx - x, cy + y, cx + x, cy + y); - if(y != 0) p->drawLine(cx + x, cy - y, cx - x, cy - y); - if(x != 0 && y != 0) p->drawLine(cx - x, cy - y, cx + x, cy - y); + int error = -radius; + int x = radius; + int y = 0; + + while(x >= y) + { + plot4lines(this, cx, cy, x, y); + + if(x != y) + { + plot4lines(this, cx, cy, y, x); + } + + error += y; + ++y; + error += y; + + if(error >= 0) + { + --x; + error -= x; + error -= x; + } + } } -void GUI::Painter::drawFilledCircle(int cx, int cy, int radius) +void Painter::drawImage(int x0, int y0, const Image& image) { - int error = -radius; - int x = radius; - int y = 0; - - while(x >= y) { - plot4lines(this, cx, cy, x, y); - if(x != y) plot4lines(this, cx, cy, y, x); - - error += y; - ++y; - error += y; - - if(error >= 0) { - --x; - error -= x; - error -= x; - } - } + size_t fw = image.width(); + size_t fh = image.height(); + + // Make sure we don't try to draw outside the pixbuf. + if(fw > (pixbuf->width - x0)) + { + fw = (pixbuf->width - x0); + } + + if(fh > (pixbuf->height - y0)) + { + fh = (pixbuf->height - y0); + } + + for(size_t y = 0; y < fh; ++y) + { + for(size_t x = 0; x < fw; ++x) + { + Colour c = image.getPixel(x, y); + pixbuf->addPixel(x0 + x, y0 + y, c); + } + } } -void GUI::Painter::drawImage(int x0, int y0, GUI::Image *image) +void Painter::drawImageStretched(int x0, int y0, const Image& image, + int width, int height) { - size_t fw = image->width(); - size_t fh = image->height(); - - for(size_t x = 0; x < fw; x++) { - for(size_t y = 0; y < fh; y++) { - GUI::Colour c = image->getPixel(x, y); - pixbuf->addPixel(x0 + x, y0 + y, c); - } - } + if((width < 1) || (height < 1)) + { + return; + } + + float fw = image.width(); + float fh = image.height(); + + // Make sure we don't try to draw outside the pixbuf. + if(width > (int)(pixbuf->width - x0)) + { + width = pixbuf->width - x0; + } + + if(height > (int)(pixbuf->height - y0)) + { + height = pixbuf->height - y0; + } + + for(int y = 0; y < height; ++y) + { + for(int x = 0; x < width; ++x) + { + int lx = ((float)x / (float)width) * fw; + int ly = ((float)y / (float)height) * fh; + Colour c = image.getPixel(lx, ly); + pixbuf->addPixel(x0 + x, y0 + y, c); + } + } } -void GUI::Painter::drawImageStretched(int x0, int y0, GUI::Image *image, - int w, int h) +void Painter::drawBox(int x, int y, const Box& box, int width, int height) { - if(w < 1 || h < 1) return; - - float fw = image->width(); - float fh = image->height(); - - for(int x = 0; x < w; x++) { - for(int y = 0; y < h; y++) { - int lx = ((float)x/(float)w)*fw; - int ly = ((float)y/(float)h)*fh; - GUI::Colour c = image->getPixel(lx, ly); - pixbuf->addPixel(x0 + x, y0 + y, c); - } - } + int dx = x; + int dy = y; + + // Top: + drawImage(dx, dy, *box.topLeft); + + dx += box.topLeft->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.top, + width - box.topRight->width() - box.topLeft->width(), + box.top->height()); + + dx = x + width - box.topRight->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImage(dx, dy, *box.topRight); + + // Center: + dy = y + box.topLeft->height(); + dx = x + box.left->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.center, + width - box.left->width() - box.right->width(), + height - box.topLeft->height() - box.bottomLeft->height()); + + // Mid: + dx = x; + dy = y + box.topLeft->height(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.left, box.left->width(), + height - box.topLeft->height() - box.bottomLeft->height()); + + dx = x + width - box.right->width(); + dy = y + box.topRight->height(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.right, + box.right->width(), + height - box.topRight->height() - box.bottomRight->height()); + + // Bottom: + dx = x; + dy = y + height - box.bottomLeft->height(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImage(dx, dy, *box.bottomLeft); + + dx += box.bottomLeft->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImageStretched(dx, dy, *box.bottom, + width - box.bottomRight->width() - box.bottomLeft->width(), + box.bottom->height()); + + dx = x + width - box.bottomRight->width(); + if((dx < 0) || (dy < 0)) + { + return; + } + + drawImage(dx, dy, *box.bottomRight); } -void GUI::Painter::drawBox(int x, int y, Box *box, int width, int height) +void Painter::drawBar(int x, int y, const Bar& bar, int width, int height) { - int dx = x; - int dy = y; - - // Top: - - drawImage(dx, dy, box->topLeft); - - dx += box->topLeft->width(); - if(dx < 0 || dy < 0) return; - - drawImageStretched(dx, dy, box->top, - width - box->topRight->width() - box->topLeft->width(), - box->top->height()); - - dx = x + width - box->topRight->width(); - if(dx < 0 || dy < 0) return; + if(width < ((int)bar.left->width() + (int)bar.right->width() + 1)) + { + width = bar.left->width() + bar.right->width() + 1; + } - drawImage(dx, dy, box->topRight); + drawImageStretched(x, y, *bar.left, bar.left->width(), height); - // Center - dy = y + box->topLeft->height(); - dx = x + box->left->width(); - if(dx < 0 || dy < 0) return; + drawImageStretched(x + bar.left->width(), y, *bar.center, + width - bar.left->width() - bar.right->width(), height); - drawImageStretched(dx, dy, box->center, - width - box->left->width() - box->right->width(), - height - box->topLeft->height() - box->bottomLeft->height()); - - // Mid: - dx = x; - dy = y + box->topLeft->height(); - if(dx < 0 || dy < 0) return; - - drawImageStretched(dx, dy, box->left, box->left->width(), - height - box->topLeft->height() - box->bottomLeft->height()); - - dx = x + width - box->right->width(); - dy = y + box->topRight->height(); - if(dx < 0 || dy < 0) return; - - drawImageStretched(dx, dy, box->right, - box->right->width(), - height - box->topRight->height() - box->bottomRight->height()); - - // Bottom: - dx = x; - dy = y + height - box->bottomLeft->height(); - if(dx < 0 || dy < 0) return; - - drawImage(dx, dy, box->bottomLeft); - - dx += box->bottomLeft->width(); - if(dx < 0 || dy < 0) return; - - drawImageStretched(dx, dy, box->bottom, - width - box->bottomRight->width() - box->bottomLeft->width(), - box->bottom->height()); - - dx = x + width - box->bottomRight->width(); - if(dx < 0 || dy < 0) return; - - drawImage(dx, dy, box->bottomRight); -} - -void GUI::Painter::drawBar(int x, int y, Bar *bar, int width, int height) -{ - if(width < ((int)bar->left->width() + (int)bar->right->width() + 1)) { - width = bar->left->width() + bar->right->width() + 1; - } - drawImageStretched(x, y, - bar->left, - bar->left->width(), height); - - drawImageStretched(x + bar->left->width(), y, - bar->center, - width - bar->left->width() - bar->right->width(), height); - - drawImageStretched(x + width - bar->left->width(), y, - bar->right, - bar->right->width(), height); + drawImageStretched(x + width - bar.left->width(), y, *bar.right, + bar.right->width(), height); } -void GUI::Painter::flush() +void Painter::flush() { #ifdef X11 - // Send the "DrawLine" request to the server - //XFlush(gctx->display); + // Send the "DrawLine" request to the server + //XFlush(gctx->display); #endif/*X11*/ } -#ifdef TEST_PAINTER -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_PAINTER*/ +} // GUI:: diff --git a/plugingui/painter.h b/plugingui/painter.h index 0a93f50..78f1560 100644 --- a/plugingui/painter.h +++ b/plugingui/painter.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_PAINTER_H__ -#define __DRUMGIZMO_PAINTER_H__ +#pragma once #include <string> @@ -39,59 +38,51 @@ namespace GUI { class Painter { public: - Painter(Widget *widget); - ~Painter(); + Painter(Widget& widget); + ~Painter(); - void flush(); + void flush(); - void setColour(Colour colour); + void setColour(const Colour& colour); - void drawLine(int x1, int y1, int x2, int y2); - void drawText(int x, int y, Font &font, std::string text, - bool nocolour = false); - void drawRectangle(int x1, int y1, int x2, int y2); - void drawFilledRectangle(int x1, int y1, int x2, int y2); - void drawPoint(int x, int y); - void drawCircle(int x, int y, double r); - void drawFilledCircle(int x, int y, int r); - void drawImage(int x, int y, Image *image); - void drawImageStretched(int x0, int y0, GUI::Image *image, - int width, int height); + void drawLine(int x1, int y1, int x2, int y2); + void drawText(int x, int y, const Font& font, const std::string& text, + bool nocolour = false); + void drawRectangle(int x1, int y1, int x2, int y2); + void drawFilledRectangle(int x1, int y1, int x2, int y2); + void drawPoint(int x, int y); + void drawCircle(int x, int y, double r); + void drawFilledCircle(int x, int y, int r); + void drawImage(int x, int y, const Image& image); + void drawImageStretched(int x, int y, const Image& image, + int width, int height); - typedef struct { - Image *topLeft; - Image *top; - Image *topRight; - Image *left; - Image *right; - Image *bottomLeft; - Image *bottom; - Image *bottomRight; - Image *center; - } Box; - void drawBox(int x, int y, Box *box, int width, int height); + typedef struct { + Image* topLeft; + Image* top; + Image* topRight; + Image* left; + Image* right; + Image* bottomLeft; + Image* bottom; + Image* bottomRight; + Image* center; + } Box; + void drawBox(int x, int y, const Box& box, int width, int height); - typedef struct { - Image *left; - Image *right; - Image *center; - } Bar; - void drawBar(int x, int y, Bar *bar, int width, int height); + typedef struct { + Image* left; + Image* right; + Image* center; + } Bar; + void drawBar(int x, int y, const Bar& bar, int width, int height); - void clear(); + void clear(); private: - void plot(int x, int y, double c); - double ipart(double x); - double round(double x); - double fpart(double x); - double rfpart(double x); - - Widget *widget; - PixelBufferAlpha *pixbuf; - Colour colour; -}; - + Widget& widget; + PixelBufferAlpha* pixbuf; + Colour colour; }; -#endif/*__DRUMGIZMO_PAINTER_H__*/ +} // GUI:: diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc index 2a6bf6f..962091e 100644 --- a/plugingui/pixelbuffer.cc +++ b/plugingui/pixelbuffer.cc @@ -26,155 +26,140 @@ */ #include "pixelbuffer.h" -#include <stdio.h> +#include <cassert> -GUI::PixelBuffer::PixelBuffer(size_t width, size_t height) +namespace GUI { + +PixelBuffer::PixelBuffer(size_t width, size_t height) + : buf(nullptr) { - buf = NULL; - realloc(width, height); + realloc(width, height); } -GUI::PixelBuffer::~PixelBuffer() +PixelBuffer::~PixelBuffer() { - if(buf) free(buf); + free(buf); } -void GUI::PixelBuffer::realloc(size_t width, size_t height) +void PixelBuffer::realloc(size_t width, size_t height) { - if(buf) free(buf); - buf = (unsigned char *)calloc(width * height, 3); - this->width = width; - this->height = height; + free(buf); + buf = (unsigned char *)calloc(width * height, 3); + this->width = width; + this->height = height; } -#define PX(k) (x + y * width) * 3 + k -void GUI::PixelBuffer::setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha) +#define PX(k) ((x + y * width) * 3 + k) +void PixelBuffer::setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha) { - if(x >= width || y >= height) return; - /* - float a,b; - getAlpha(alpha, 255, a, b); - - buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b); - buf[PX(0)] /= (a + b); - buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b); - buf[PX(1)] /= (a + b); - buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b); - buf[PX(2)] /= (a + b); - */ - unsigned int a = alpha; - unsigned int b = 255 - alpha; - - buf[PX(0)] = (unsigned char)(((int)red * a + (int)buf[PX(0)] * b) / 255); - buf[PX(1)] = (unsigned char)(((int)green * a + (int)buf[PX(1)] * b) / 255); - buf[PX(2)] = (unsigned char)(((int)blue * a + (int)buf[PX(2)] * b) / 255); + assert(x < width); + assert(y < height); + + unsigned int a = alpha; + unsigned int b = 255 - alpha; + + buf[PX(0)] = (unsigned char)(((int)red * a + (int)buf[PX(0)] * b) / 255); + buf[PX(1)] = (unsigned char)(((int)green * a + (int)buf[PX(1)] * b) / 255); + buf[PX(2)] = (unsigned char)(((int)blue * a + (int)buf[PX(2)] * b) / 255); } -static int idx = 0; -GUI::PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height) +PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height) + : buf(nullptr) + , x(0) + , y(0) { - this->idx = ::idx++; - buf = NULL; - x = y = 10; - realloc(width, height); + realloc(width, height); } -GUI::PixelBufferAlpha::~PixelBufferAlpha() +PixelBufferAlpha::~PixelBufferAlpha() { - if(buf) free(buf); + free(buf); } -void GUI::PixelBufferAlpha::realloc(size_t width, size_t height) +void PixelBufferAlpha::realloc(size_t width, size_t height) { - if(buf) free(buf); - buf = (unsigned char *)calloc(width * height, 4); - this->width = width; - this->height = height; + free(buf); + buf = (unsigned char *)calloc(width * height, 4); + this->width = width; + this->height = height; } #undef PX -#define PX(k) (x + y * width) * 4 + k -void GUI::PixelBufferAlpha::setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha) +#define PX(k) ((x + y * width) * 4 + k) +void PixelBufferAlpha::setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha) { - if(x >= width || y >= height) return; + assert(x < width); + assert(y < height); - buf[PX(0)] = red; - buf[PX(1)] = green; - buf[PX(2)] = blue; - buf[PX(3)] = alpha; + buf[PX(0)] = red; + buf[PX(1)] = green; + buf[PX(2)] = blue; + buf[PX(3)] = alpha; } // http://en.wikipedia.org/wiki/Alpha_compositing -static void getAlpha(unsigned char _a, unsigned char _b, float &a, float &b) +static inline void getAlpha(unsigned char _a, unsigned char _b, + float &a, float &b) { - a = _a / 255.0; - b = _b / 255.0; - b *= (1-a); + a = _a / 255.0; + b = _b / 255.0; + b *= (1 - a); } -void GUI::PixelBufferAlpha::addPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha) +void PixelBufferAlpha::addPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha) { - if(x >= width || y >= height) return; + assert(x < width); + assert(y < height); - if(alpha == 0) return; + if(alpha == 0) + { + return; + } - float a,b; - getAlpha(alpha, buf[PX(3)], a, b); + float a, b; + getAlpha(alpha, buf[PX(3)], a, b); - buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b); - buf[PX(0)] /= (a + b); - buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b); - buf[PX(1)] /= (a + b); - buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b); - buf[PX(2)] /= (a + b); + buf[PX(0)] = (unsigned char)((float)red * a + (float)buf[PX(0)] * b); + buf[PX(0)] /= (a + b); + buf[PX(1)] = (unsigned char)((float)green * a + (float)buf[PX(1)] * b); + buf[PX(1)] /= (a + b); + buf[PX(2)] = (unsigned char)((float)blue * a + (float)buf[PX(2)] * b); + buf[PX(2)] /= (a + b); - buf[PX(3)] = (a + b) * 255; + buf[PX(3)] = (a + b) * 255; } -void GUI::PixelBufferAlpha::addPixel(size_t x, size_t y, GUI::Colour c) +void PixelBufferAlpha::addPixel(size_t x, size_t y, Colour c) { - addPixel(x, y, c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255); + addPixel(x, y, c.red * 255, c.green * 255, c.blue * 255, c.alpha * 255); } -void GUI::PixelBufferAlpha::pixel(size_t x, size_t y, - unsigned char *red, - unsigned char *green, - unsigned char *blue, - unsigned char *alpha) +void PixelBufferAlpha::pixel(size_t x, size_t y, + unsigned char* red, + unsigned char* green, + unsigned char* blue, + unsigned char* alpha) { - if(x >= width || y >= height) return; - *red = buf[PX(0)]; - *green = buf[PX(1)]; - *blue = buf[PX(2)]; - *alpha = buf[PX(3)]; -} - -#ifdef TEST_PIXELBUFFER -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; + assert(x < width); + assert(y < height); -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; + *red = buf[PX(0)]; + *green = buf[PX(1)]; + *blue = buf[PX(2)]; + *alpha = buf[PX(3)]; +} -#endif/*TEST_PIXELBUFFER*/ +} // GUI:: diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h index 2785eb1..d955c1a 100644 --- a/plugingui/pixelbuffer.h +++ b/plugingui/pixelbuffer.h @@ -24,68 +24,64 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_PIXELBUFFER_H__ -#define __DRUMGIZMO_PIXELBUFFER_H__ - -#include <stdlib.h> +#pragma once #include "colour.h" +#include <stdlib.h> + namespace GUI { class PixelBuffer { public: - PixelBuffer(size_t width, size_t height); - ~PixelBuffer(); + PixelBuffer(size_t width, size_t height); + ~PixelBuffer(); - void realloc(size_t width, size_t height); + void realloc(size_t width, size_t height); - void setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha); + void setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha); - unsigned char *buf; - size_t width; - size_t height; + unsigned char* buf; + size_t width; + size_t height; }; class PixelBufferAlpha { public: - PixelBufferAlpha(size_t width, size_t height); - ~PixelBufferAlpha(); - - int idx; - size_t x, y; - - void realloc(size_t width, size_t height); - - void setPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha); - - void addPixel(size_t x, size_t y, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char alpha); - - void addPixel(size_t x, size_t y, Colour c); - - void pixel(size_t x, size_t y, - unsigned char *red, - unsigned char *green, - unsigned char *blue, - unsigned char *alpha); - - unsigned char *buf; - size_t width; - size_t height; -}; - + PixelBufferAlpha(size_t width, size_t height); + ~PixelBufferAlpha(); + + void realloc(size_t width, size_t height); + + void setPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha); + + void addPixel(size_t x, size_t y, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char alpha); + + void addPixel(size_t x, size_t y, Colour c); + + void pixel(size_t x, size_t y, + unsigned char* red, + unsigned char* green, + unsigned char* blue, + unsigned char* alpha); + + unsigned char* buf; + size_t width; + size_t height; + size_t x; + size_t y; }; -#endif/*__DRUMGIZMO_PIXELBUFFER_H__*/ +} // GUI:: diff --git a/plugingui/pluginconfig.cc b/plugingui/pluginconfig.cc index d4c4477..77cb4ba 100644 --- a/plugingui/pluginconfig.cc +++ b/plugingui/pluginconfig.cc @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * config.cc + * pluginconfig.cc * * Tue Jun 3 13:54:05 CEST 2014 * Copyright 2014 Jonas Suhr Christensen @@ -27,11 +27,13 @@ #include "pluginconfig.h" #include <hugin.hpp> - + #define CONFIGFILENAME "plugingui.conf" +namespace GUI { + Config::Config() - : ConfigFile(CONFIGFILENAME) + : ConfigFile(CONFIGFILENAME) { } @@ -41,23 +43,26 @@ Config::~Config() bool Config::load() { - lastkit.clear(); - lastmidimap.clear(); + lastkit.clear(); + lastmidimap.clear(); - if(!ConfigFile::load()) { - return false; - } + if(!ConfigFile::load()) + { + return false; + } - lastkit = getValue("lastkit"); - lastmidimap = getValue("lastmidimap"); + lastkit = getValue("lastkit"); + lastmidimap = getValue("lastmidimap"); - return true; + return true; } bool Config::save() { - setValue("lastkit", lastkit); - setValue("lastmidimap", lastmidimap); + setValue("lastkit", lastkit); + setValue("lastmidimap", lastmidimap); - return ConfigFile::save(); + return ConfigFile::save(); } + +} // GUI:: diff --git a/plugingui/pluginconfig.h b/plugingui/pluginconfig.h index 9bef1f0..a249eb2 100644 --- a/plugingui/pluginconfig.h +++ b/plugingui/pluginconfig.h @@ -1,6 +1,6 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** - * config.h + * pluginconfig.h * * Tue Jun 3 13:51:29 CEST 2014 * Copyright 2014 Jonas Suhr Christensen @@ -24,21 +24,22 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_CONFIG_H__ -#define __DRUMGIZMO_CONFIG_H__ +#pragma once #include <configfile.h> +namespace GUI { + class Config : public ConfigFile { public: - Config(); - ~Config(); + Config(); + ~Config(); - bool load(); - bool save(); + bool load(); + bool save(); - std::string lastkit; - std::string lastmidimap; + std::string lastkit; + std::string lastmidimap; }; -#endif/*__DRUMGIZMO_CONFIG_H__*/ +} // GUI:: diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index 170f4f9..a56818c 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -27,533 +27,222 @@ #include "plugingui.h" #include <hugin.hpp> -#include <stdio.h> - -#include "knob.h" -#include "verticalline.h" -#include "../version.h" #include "pluginconfig.h" #include "messagehandler.h" -static void checkClick(void *ptr) -{ - PluginGUI *gui = (PluginGUI*)ptr; - - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, - gui->check->checked()); - msghandler.sendMessage(MSGRCV_ENGINE, msg); -} - -static void knobChange(void *ptr) -{ - PluginGUI *gui = (PluginGUI*)ptr; - - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, - gui->knob->value()); - - msghandler.sendMessage(MSGRCV_ENGINE, msg); - -#ifdef STANDALONE - int i = gui->knob->value() * 4; - switch(i) { - case 0: gui->progress->setState(GUI::ProgressBar::off); break; - case 1: gui->progress->setState(GUI::ProgressBar::blue); break; - case 2: gui->progress->setState(GUI::ProgressBar::green); break; - case 3: gui->progress->setState(GUI::ProgressBar::red); break; - default: break; - } -#endif -} - -static void knobChange2(void *ptr) -{ - PluginGUI *gui = (PluginGUI*)ptr; - - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, - gui->knob2->value()); - msghandler.sendMessage(MSGRCV_ENGINE, msg); - -#ifdef STANDALONE - gui->progress->setProgress(gui->knob2->value()); -#endif -} - -//static void quit(void *ptr) { -// PluginGUI *gui = (PluginGUI*)ptr; -// -// gui->stopThread(); -//} - -GUI::FileBrowser *fb; -static void selectKitFile(void *ptr, std::string filename) -{ - PluginGUI *gui = (PluginGUI*)ptr; - - gui->lineedit->setText(filename); - - fb->hide(); - - std::string drumkit = gui->lineedit->text(); - - gui->config->lastkit = drumkit; - gui->config->save(); - - gui->progress->setProgress(0); - gui->progress->setState(GUI::ProgressBar::blue); - - LoadDrumKitMessage *msg = new LoadDrumKitMessage(); - msg->drumkitfile = drumkit; - - msghandler.sendMessage(MSGRCV_ENGINE, msg); -} - -static void kitBrowseClick(void *ptr) -{ - PluginGUI *gui = (PluginGUI*)ptr; - - std::string path = gui->lineedit->text(); - if(path == "") path = gui->config->lastkit; - if(path == "") path = gui->lineedit2->text(); - - fb->setPath(path); - fb->registerFileSelectHandler(selectKitFile, gui); - fb->show(); -} - -static void selectMapFile(void *ptr, std::string filename) -{ - PluginGUI *gui = (PluginGUI*)ptr; - - gui->lineedit2->setText(filename); - fb->hide(); - - std::string midimap = gui->lineedit2->text(); - - gui->config->lastmidimap = midimap; - gui->config->save(); - - LoadMidimapMessage *msg = new LoadMidimapMessage(); - msg->midimapfile = midimap; - msghandler.sendMessage(MSGRCV_ENGINE, msg); - - /* - if(gui->changeMidimapHandler) - gui->changeMidimapHandler(gui->changeMidimapPtr, midimap.c_str()); - gui->progress2->setState(GUI::ProgressBar::green); - */ -} - -static void midimapBrowseClick(void *ptr) -{ - PluginGUI *gui = (PluginGUI*)ptr; - - std::string path = gui->lineedit2->text(); - if(path == "") path = gui->config->lastmidimap; - if(path == "") path = gui->lineedit->text(); - - fb->setPath(path); - fb->registerFileSelectHandler(selectMapFile, gui); - fb->show(); -} - -/* -void closeClick(void *ptr) -{ - PluginGUI *gui = (PluginGUI*)ptr; - if(gui->windowClosedHandler) gui->windowClosedHandler(gui->windowClosedPtr); -} -*/ +namespace GUI { PluginGUI::PluginGUI() - : MessageReceiver(MSGRCV_UI) - , initialised(false) - , sem("plugingui") + : MessageReceiver(MSGRCV_UI) { - windowClosedHandler = NULL; - changeMidimapHandler = NULL; - - window = NULL; - - running = true; - closing = false; - #ifdef USE_THREAD - run(); + run(); #else - init(); + init(); #endif/*USE_THREAD*/ - sem.wait(); + sem.wait(); } PluginGUI::~PluginGUI() { - stopThread(); + stopThread(); } -void PluginGUI::stopThread() -{ - if(running) { - running = false; - wait_stop(); - } -} - - void PluginGUI::handleMessage(Message *msg) { - GUI::Painter p(window);// Make sure we only redraw buffer one time. - - switch(msg->type()) { - case Message::LoadStatus: - { - LoadStatusMessage *ls = (LoadStatusMessage*)msg; - progress->setProgress((float)ls->numer_of_files_loaded / - (float)ls->number_of_files); - if(ls->numer_of_files_loaded == ls->number_of_files) { - progress->setState(GUI::ProgressBar::green); - } - } - break; - case Message::LoadStatusMidimap: - { - LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; - progress2->setProgress(1); - if(ls->success) { - progress2->setState(GUI::ProgressBar::green); - } else { - progress2->setState(GUI::ProgressBar::red); - } - } - break; - case Message::EngineSettingsMessage: - { - EngineSettingsMessage *settings = (EngineSettingsMessage *)msg; - lineedit->setText(settings->drumkitfile); - if(settings->drumkit_loaded) { - progress->setProgress(1); - progress->setState(GUI::ProgressBar::green); - } else { - progress->setProgress(0); - progress->setState(GUI::ProgressBar::blue); - } - lineedit2->setText(settings->midimapfile); - if(settings->midimap_loaded) { - progress2->setProgress(1); - progress2->setState(GUI::ProgressBar::green); - } else { - progress2->setProgress(0); - progress2->setState(GUI::ProgressBar::blue); - } - check->setChecked(settings->enable_velocity_modifier); - knob->setValue(settings->velocity_modifier_weight); - knob2->setValue(settings->velocity_modifier_falloff); - - } - default: - break; - } + Painter p(*window);// Make sure we only redraw buffer once (set refcount to 1) + + switch(msg->type()) { + case Message::LoadStatus: + { + LoadStatusMessage *ls = (LoadStatusMessage*)msg; + window->drumkitFileProgress->setProgress((float)ls->numer_of_files_loaded / + (float)ls->number_of_files); + if(ls->numer_of_files_loaded == ls->number_of_files) + { + window->drumkitFileProgress->setState(ProgressBarState::Green); + } + } + break; + case Message::LoadStatusMidimap: + { + LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; + window->midimapFileProgress->setProgress(1); + if(ls->success) + { + window->midimapFileProgress->setState(ProgressBarState::Green); + } + else + { + window->midimapFileProgress->setState(ProgressBarState::Red); + } + } + break; + case Message::EngineSettingsMessage: + { + EngineSettingsMessage *settings = (EngineSettingsMessage *)msg; + window->lineedit->setText(settings->drumkitfile); + if(settings->drumkit_loaded) + { + window->drumkitFileProgress->setProgress(1); + window->drumkitFileProgress->setState(ProgressBarState::Green); + } + else + { + window->drumkitFileProgress->setProgress(0); + window->drumkitFileProgress->setState(ProgressBarState::Blue); + } + window->lineedit2->setText(settings->midimapfile); + if(settings->midimap_loaded) + { + window->midimapFileProgress->setProgress(1); + window->midimapFileProgress->setState(ProgressBarState::Green); + } + else + { + window->midimapFileProgress->setProgress(0); + window->midimapFileProgress->setState(ProgressBarState::Blue); + } + window->velocityCheck->setChecked(settings->enable_velocity_modifier); + window->attackKnob->setValue(settings->velocity_modifier_weight); + window->falloffKnob->setValue(settings->velocity_modifier_falloff); + } + default: + break; + } } void PluginGUI::thread_main() { - init(); + init(); - { // Request all engine settings - EngineSettingsMessage *msg = new EngineSettingsMessage(); - msghandler.sendMessage(MSGRCV_ENGINE, msg); - } + { // Request all engine settings + EngineSettingsMessage *msg = new EngineSettingsMessage(); + msghandler.sendMessage(MSGRCV_ENGINE, msg); + } - while(running) { + while(processEvents()) + { #ifdef WIN32 - SleepEx(50, FALSE); + SleepEx(50, FALSE); #else - usleep(50000); + usleep(50000); #endif/*WIN32*/ + } - // DEBUG(gui, "loop"); - - window->eventHandler()->processEvents(); - handleMessages(); - } - - deinit(); + deinit(); } -void PluginGUI::deinit() +bool PluginGUI::processEvents() { - if(config) { - config->save(); - delete config; - } - if(window) delete window; + if(!initialised) + { + return running; + } + + window->eventHandler()->processEvents(); + handleMessages(); + + if(closing) + { + closeNotifier(); + closing = false; + return false; + } + + return running; } -void closeEventHandler(void *ptr) +void PluginGUI::stopThread() { - volatile bool *closing = (volatile bool*)ptr; - *closing = true; + if(running) + { + running = false; + wait_stop(); + } } void PluginGUI::init() { - DEBUG(gui, "init"); - - config = new Config(); - config->load(); - - window = new GUI::Window(); - window->eventHandler()->registerCloseHandler(closeEventHandler, - (void*)&closing); - - window->setFixedSize(370, 330); - window->setCaption("DrumGizmo v" VERSION); - - GUI::Label *lbl_title = new GUI::Label(window); - lbl_title->setText("DrumGizmo"); - lbl_title->move(127, 7); - lbl_title->resize(200, 20); - - GUI::VerticalLine *l1 = new GUI::VerticalLine(window); - l1->move(20, 30); - l1->resize(window->width() - 40, 2); - -#define OFFSET1 17 -#define OFFSET2 38 -#define OFFSET3 20 - -#define XOFFSET 20 - // Drumkit file - { - int y = 37; - GUI::Label *lbl = new GUI::Label(window); - lbl->setText("Drumkit file:"); - lbl->move(XOFFSET - 4, y); - lbl->resize(100, 20); - - y += OFFSET1; - lineedit = new GUI::LineEdit(window); - lineedit->move(XOFFSET, y); - lineedit->resize(243, 29); - lineedit->setReadOnly(true); - - GUI::Button *btn_brw = new GUI::Button(window); - btn_brw->setText("Browse..."); - btn_brw->move(266, y - 6 + 4); - btn_brw->resize(85, 35 + 6 - 4); - btn_brw->registerClickHandler(kitBrowseClick, this); - - y += OFFSET2; - progress = new GUI::ProgressBar(window); - progress->move(XOFFSET, y); - progress->resize(window->width() - 2*XOFFSET, 11); - - y += OFFSET3; - GUI::VerticalLine *l = new GUI::VerticalLine(window); - l->move(XOFFSET, y); - l->resize(window->width() - 2*XOFFSET, 2); - } - - // Midimap file - { - int y = 120; - lbl2 = new GUI::Label(window); - lbl2->setText("Midimap file:"); - lbl2->move(XOFFSET - 4, y); - lbl2->resize(100, 20); - - y += OFFSET1; - lineedit2 = new GUI::LineEdit(window); - lineedit2->move(XOFFSET, y); - lineedit2->resize(243, 29); - lineedit2->setReadOnly(true); - - GUI::Button *btn_brw = new GUI::Button(window); - btn_brw->setText("Browse..."); - btn_brw->move(266, y - 6 + 4); - btn_brw->resize(85, 35 + 6 - 4); - btn_brw->registerClickHandler(midimapBrowseClick, this); - - y += OFFSET2; - progress2 = new GUI::ProgressBar(window); - progress2->move(XOFFSET, y); - progress2->resize(window->width() - 2*XOFFSET, 11); - - y += OFFSET3; - GUI::VerticalLine *l = new GUI::VerticalLine(window); - l->move(XOFFSET, y); - l->resize(window->width() - 2*XOFFSET, 2); - } - - { - int y = 203; -#define OFFSET4 21 - - // Enable Velocity - GUI::Label *lbl_velocity = new GUI::Label(window); - lbl_velocity->resize(78 ,20); - lbl_velocity->move(16, y); - lbl_velocity->setText("Humanizer"); - - check = new GUI::CheckBox(window); - //check->setText("Enable Velocity Modifier"); - check->move(26, y + OFFSET4); - check->resize(59,38); - check->registerClickHandler(checkClick, this); - - // Velocity Weight Modifier: - { - GUI::Label *lbl_weight = new GUI::Label(window); - lbl_weight->setText("Attack"); - lbl_weight->move(107, y); - lbl_weight->resize(100, 20); - - knob = new GUI::Knob(window); - knob->move(109, y + OFFSET4 - 4); - knob->resize(57, 57); - knob->registerClickHandler(knobChange, this); - } - - // Velocity Falloff Modifier: - { - GUI::Label *lbl_falloff = new GUI::Label(window); - lbl_falloff->setText("Release"); - lbl_falloff->move(202 - 17 - 7, y); - lbl_falloff->resize(100, 20); - - knob2 = new GUI::Knob(window); - knob2->move(202 - 13 - 5, y + OFFSET4 - 4); - knob2->resize(57, 57); - knob2->registerClickHandler(knobChange2, this); - } - } - - GUI::VerticalLine *l2 = new GUI::VerticalLine(window); - l2->move(20, 310 - 15 - 9); - l2->resize(window->width() - 40, 2); - - GUI::Label *lbl_version = new GUI::Label(window); - lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. GPLv3 .::."); - lbl_version->move(16, 300); - lbl_version->resize(window->width(), 20); - /* - { - GUI::ComboBox *cmb = new GUI::ComboBox(window); - cmb->addItem("Foo", "Bar"); - cmb->addItem("Hello", "World"); - cmb->move(10,10); - cmb->resize(70, 30); - } - */ - // Create filebrowser - filebrowser = new GUI::FileBrowser(window); - filebrowser->move(0, 0); - filebrowser->resize(window->width() - 1, window->height() - 1); - filebrowser->hide(); - fb = filebrowser; - - // Enable quit button -// GUI::Button *btn_quit = new GUI::Button(window); -// btn_quit->setText("Quit"); -// btn_quit->move(50,280); -// btn_quit->resize(80,80); -// btn_quit->registerClickHandler(quit, this); - - window->show(); - - sem.post(); - - initialised = true; -} + DEBUG(gui, "init"); -void PluginGUI::show() -{ - while(!initialised) usleep(10000); + config = new Config(); + config->load(); + + window = new DGWindow(msghandler, *config); - if(!window) init(); + auto eventHandler = window->eventHandler(); + CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler); - window->show(); + window->show(); + + sem.post(); + + initialised = true; } -void PluginGUI::hide() +void PluginGUI::deinit() { - while(!initialised) usleep(10000); + if(config) + { + config->save(); + delete config; + } - if(window) window->hide(); + if(window) + { + delete window; + } } -void PluginGUI::processEvents() +void PluginGUI::show() { - if(!initialised) return; + while(!initialised) + { + usleep(10000); + } - if(closing) { - if(windowClosedHandler) windowClosedHandler(windowClosedPtr); - closing = false; - } + if(!window) + { + init(); + } -#ifndef USE_THREAD - window->eventHandler()->processEvents(window); -#endif/*USE_THREAD*/ + if(window) + { + window->show(); + } } -void PluginGUI::setWindowClosedCallback(void (*handler)(void *), void *ptr) +void PluginGUI::hide() { - windowClosedHandler = handler; - windowClosedPtr = ptr; -} - -#ifdef STANDALONE - -class Engine : public MessageHandler { -public: - void handleMessage(Message *msg) {} -}; + while(!initialised) + { + usleep(10000); + } + if(window) + { + window->hide(); + } +} -void stop(void *ptr) +void PluginGUI::setWindowClosedCallback(void (*handler)(void *), void* ptr) { - DEBUG(stop, "Stopping...\n"); - bool *running = (bool*)ptr; - *running = false; + windowClosedHandler = handler; + windowClosedPtr = ptr; } -int main() +void PluginGUI::closeEventHandler() { -/* - hug_status_t status = hug_init(HUG_FLAG_OUTPUT_TO_SYSLOG, - HUG_OPTION_SYSLOG_HOST, "192.168.0.10", - HUG_OPTION_SYSLOG_PORT, 514, - HUG_OPTION_END); - - if(status != HUG_STATUS_OK) { - printf("Error: %d\n", status); - return 1; - } -*/ - INFO(example, "We are up and running"); - - bool running = true; - - PluginGUI gui; - gui.setWindowClosedCallback(stop, &running); - - // gui.show(); - - while(running) { - // gui.processEvents(); -#ifdef WIN32 - SleepEx(1000, FALSE); -#else - // usleep(10000); - sleep(1); -#endif - } - - return 0; + closing = true; + closeNotifier(); + // Call old-style notifier if one is registered. + if(windowClosedHandler) + { + windowClosedHandler(windowClosedPtr); + } } -#endif/*STANDALONE*/ +} // GUI:: diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index 39643e1..b57855a 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -24,77 +24,67 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_PLUGINGUI_H__ -#define __DRUMGIZMO_PLUGINGUI_H__ +#pragma once -#include "window.h" +#include "dgwindow.h" #include "eventhandler.h" -#include "label.h" -#include "lineedit.h" -#include "checkbox.h" -#include "button.h" -#include "knob.h" -#include "progressbar.h" #include "pluginconfig.h" -#include "filebrowser.h" #include "thread.h" #include "semaphore.h" #include "messagereceiver.h" +#include "notifier.h" -class PluginGUI : public Thread, public MessageReceiver { +namespace GUI { + +class PluginGUI : public Thread, public MessageReceiver, public Listener { public: - PluginGUI(); - virtual ~PluginGUI(); + PluginGUI(); + virtual ~PluginGUI(); - void thread_main(); - void stopThread(); + void thread_main(); - void init(); - void deinit(); + //! Process all events and messages in queue + //! \return true if not closing, returns false if closing. + bool processEvents(); - void show(); - void hide(); - void processEvents(); - void setWindowClosedCallback(void (*handler)(void *), void *ptr); + void stopThread(); - void handleMessage(Message *msg); + void init(); + void deinit(); - //private: - GUI::Window *window; - GUI::EventHandler *eventhandler; + void show(); + void hide(); - GUI::FileBrowser *filebrowser; - GUI::CheckBox *check; - GUI::Knob *knob; - GUI::Knob *knob2; + void handleMessage(Message* msg); - GUI::Label *lbl; - GUI::LineEdit *lineedit; - GUI::ProgressBar *progress; + DGWindow* window{nullptr}; + EventHandler* eventhandler{nullptr}; - GUI::Label *lbl2; - GUI::LineEdit *lineedit2; - GUI::ProgressBar *progress2; - Config *config; + Config* config{nullptr}; - void (*windowClosedHandler)(void *); - void *windowClosedPtr; + Notifier<> closeNotifier; - void (*changeMidimapHandler)(void *, const char *); - void *changeMidimapPtr; + // Support old interface a little while longer.. + void setWindowClosedCallback(void (*handler)(void*), void* ptr); private: - volatile bool running; - volatile bool closing; - volatile bool initialised; + void closeEventHandler(); + + volatile bool running{true}; + volatile bool closing{false}; + volatile bool initialised{false}; + + Semaphore sem{"plugingui"}; - Semaphore sem; + // For the old-style notifier. + void (*windowClosedHandler)(void *){nullptr}; + void *windowClosedPtr{nullptr}; }; -#endif/*__DRUMGIZMO_PLUGINGUI_H__*/ +} // GUI:: diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc index 3b821bb..6882789 100644 --- a/plugingui/progressbar.cc +++ b/plugingui/progressbar.cc @@ -26,83 +26,101 @@ */ #include "progressbar.h" -#include "painter.h" +namespace GUI { -GUI::ProgressBar::ProgressBar(GUI::Widget *parent) : GUI::Widget(parent) +ProgressBar::ProgressBar(Widget *parent) + : Widget(parent) { - bar_bg.left = new Image(":progress_back_l.png"); - bar_bg.right = new Image(":progress_back_r.png"); - bar_bg.center = new Image(":progress_back_c.png"); + bar_bg.left = new Image(":progress_back_l.png"); + bar_bg.right = new Image(":progress_back_r.png"); + bar_bg.center = new Image(":progress_back_c.png"); - bar_blue.left = new Image(":progress_front_blue_l.png"); - bar_blue.right = new Image(":progress_front_blue_r.png"); - bar_blue.center = new Image(":progress_front_blue_c.png"); + bar_blue.left = new Image(":progress_front_blue_l.png"); + bar_blue.right = new Image(":progress_front_blue_r.png"); + bar_blue.center = new Image(":progress_front_blue_c.png"); - bar_red.left = new Image(":progress_front_red_l.png"); - bar_red.right = new Image(":progress_front_red_r.png"); - bar_red.center = new Image(":progress_front_red_c.png"); + bar_red.left = new Image(":progress_front_red_l.png"); + bar_red.right = new Image(":progress_front_red_r.png"); + bar_red.center = new Image(":progress_front_red_c.png"); - bar_green.left = new Image(":progress_front_green_l.png"); - bar_green.right = new Image(":progress_front_green_r.png"); - bar_green.center = new Image(":progress_front_green_c.png"); + bar_green.left = new Image(":progress_front_green_l.png"); + bar_green.right = new Image(":progress_front_green_r.png"); + bar_green.center = new Image(":progress_front_green_c.png"); - state = blue; - _progress = .5; + state = ProgressBarState::Blue; + _progress = .5; } -void GUI::ProgressBar::setState(GUI::ProgressBar::state_t state) +ProgressBar::~ProgressBar() { - if(this->state != state) { - this->state = state; - repaintEvent(NULL); - } + delete bar_bg.left; + delete bar_bg.right; + delete bar_bg.center; + + delete bar_blue.left; + delete bar_blue.right; + delete bar_blue.center; + + delete bar_red.left; + delete bar_red.right; + delete bar_red.center; + + delete bar_green.left; + delete bar_green.right; + delete bar_green.center; } -float GUI::ProgressBar::progress() +void ProgressBar::setState(ProgressBarState state) { - return _progress; + if(this->state != state) + { + this->state = state; + repaintEvent(nullptr); + } } -void GUI::ProgressBar::setProgress(float progress) +float ProgressBar::progress() { - _progress = progress; - repaintEvent(NULL); + return _progress; } -void GUI::ProgressBar::repaintEvent(GUI::RepaintEvent *e) +void ProgressBar::setProgress(float progress) { - Painter p(this); - - int max = width() * _progress; - - p.clear(); - - int brd = 4; - p.drawBar(0, 0, &bar_bg, width(), height()); - - GUI::Painter::Bar *b = NULL; - switch(state) { - case red: b = &bar_red; break; - case green: b = &bar_green; break; - case blue: b = &bar_blue; break; - default: break; - } - if(b) p.drawBar(brd, 0, b, max - 2*brd, height()); + _progress = progress; + repaintEvent(nullptr); } -#ifdef TEST_PROGRESSBAR -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; +void ProgressBar::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + int max = width() * _progress; + + p.clear(); + + int brd = 4; + p.drawBar(0, 0, bar_bg, width(), height()); + + Painter::Bar* bar = nullptr; + switch(state) { + case ProgressBarState::Red: + bar = &bar_red; + break; + case ProgressBarState::Green: + bar = &bar_green; + break; + case ProgressBarState::Blue: + bar = &bar_blue; + break; + case ProgressBarState::Off: + bar = nullptr; + break; + } + + if(bar) + { + p.drawBar(brd, 0, *bar, max - 2 * brd, height()); + } +} -#endif/*TEST_PROGRESSBAR*/ +} // GUI:: diff --git a/plugingui/progressbar.h b/plugingui/progressbar.h index 9d08a9e..26fbbea 100644 --- a/plugingui/progressbar.h +++ b/plugingui/progressbar.h @@ -24,48 +24,47 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_PROGRESSBAR_H__ -#define __DRUMGIZMO_PROGRESSBAR_H__ +#pragma once #include "widget.h" -#include <string> - #include "guievent.h" #include "painter.h" namespace GUI { +enum class ProgressBarState +{ + Red, + Green, + Blue, + Off +}; + class ProgressBar : public Widget { public: - ProgressBar(Widget *parent); + ProgressBar(Widget *parent); + ~ProgressBar(); - float progress(); - void setProgress(float progress); + float progress(); + void setProgress(float progress); - typedef enum { - red, - green, - blue, - off - } state_t; - void setState(state_t state); + void setState(ProgressBarState state); - //protected: - virtual void repaintEvent(RepaintEvent *e); +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; private: - state_t state; + ProgressBarState state; - Painter::Bar bar_bg; + Painter::Bar bar_bg; - Painter::Bar bar_green; - Painter::Bar bar_blue; - Painter::Bar bar_red; - - float _progress; -}; + Painter::Bar bar_green; + Painter::Bar bar_blue; + Painter::Bar bar_red; + float _progress; }; -#endif/*__DRUMGIZMO_PROGRESSBAR_H__*/ +} // GUI:: diff --git a/plugingui/resource.cc b/plugingui/resource.cc index 80bd51e..c0248c3 100644 --- a/plugingui/resource.cc +++ b/plugingui/resource.cc @@ -26,94 +26,119 @@ */ #include "resource.h" -#include <stdio.h> #include <hugin.hpp> +#include <cstdio> + +// rcgen generated file containing rc_data declaration. #include "resource_data.h" -GUI::Resource::Resource(std::string name) +namespace GUI { + +// Internal resources start with a colon. +static bool nameIsInternal(const std::string& name) +{ + return name.size() && (name[0] == ':'); +} + +Resource::Resource(const std::string& name) { - is_valid = false; - is_internal = false; - - if(name.length() == 0) return; - if(name[0] == ':') { - i_data = NULL; - i_size = 0; - - // Use internal resource: - const rc_data_t *p = rc_data; - while(p->name[0] == ':') { - if(std::string(p->name) == name) { - i_data = p->data; - i_size = p->size; - break; - } - p++; - } - - // We did not find the named resource. - if(i_data == NULL) { - ERR(rc, "Could not find '%s'\n", name.c_str()); - return; - } - - is_internal = true; - } else { - // Read from file: - FILE *fp = fopen(name.c_str(), "r"); - if(!fp) return; - char buf[32]; - while(!feof(fp)) { - size_t sz = fread(buf, 1, sizeof(buf), fp); - e_data.append(buf, sz); - } - fclose(fp); - is_internal = false; + if(nameIsInternal(name)) + { + // Use internal resource: + + // Find internal resource in rc_data. + const rc_data_t* p = rc_data; + while(p->name) // last entry in rc_data has the name := "" + { + if(name == p->name) + { + internalData = p->data; + internalSize = p->size; + break; + } + ++p; + } + + // We did not find the named resource. + if(internalData == nullptr) + { + ERR(rc, "Could not find '%s'\n", name.c_str()); + return; + } + + isInternal = true; + } + else + { + // Read from file: + std::FILE *fp = std::fopen(name.c_str(), "rb"); + if(!fp) + { + return; + } + + // Get the file size + std::fseek(fp, 0, SEEK_END); + size_t filesize = ftell(fp); + + // Reserve space in the string for the data. + externalData.reserve(filesize); + + // Rewind and read... + std::rewind(fp); + + char buffer[32]; + while(!std::feof(fp)) + { + size_t size = std::fread(buffer, 1, sizeof(buffer), fp); + externalData.append(buffer, size); + } + + std::fclose(fp); + + isInternal = false; } - is_valid = true; + isValid = true; } -const char *GUI::Resource::data() +const char *Resource::data() { - if(is_valid == false) return NULL; - if(is_internal) { - return i_data; - } else { - return e_data.data(); - } - return NULL; + if(isValid == false) + { + return nullptr; + } + + if(isInternal) + { + return internalData; + } + else + { + return externalData.data(); + } } -size_t GUI::Resource::size() +size_t Resource::size() { - if(is_valid == false) return 0; - if(is_internal) { - return i_size; - } else { - return e_data.length(); - } - return 0; + if(isValid == false) + { + return 0; + } + + if(isInternal) + { + return internalSize; + } + else + { + return externalData.length(); + } } -bool GUI::Resource::valid() +bool Resource::valid() { - return is_valid; + return isValid; } -#ifdef TEST_RESOURCE -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_RESOURCE*/ +} // GUI:: diff --git a/plugingui/resource.h b/plugingui/resource.h index 4b494f7..2246271 100644 --- a/plugingui/resource.h +++ b/plugingui/resource.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_RESOURCE_H__ -#define __DRUMGIZMO_RESOURCE_H__ +#pragma once #include <string> @@ -33,21 +32,19 @@ namespace GUI { class Resource { public: - Resource(std::string name); + Resource(const std::string& name); - const char *data(); - size_t size(); + const char* data(); + size_t size(); - bool valid(); + bool valid(); -private: - std::string e_data; - bool is_valid; - bool is_internal; - const char *i_data; - size_t i_size; +protected: + std::string externalData; + bool isValid{false}; + bool isInternal{false}; + const char *internalData{nullptr}; + size_t internalSize{0}; }; -}; - -#endif/*__DRUMGIZMO_RESOURCE_H__*/ +} // GUI:: diff --git a/plugingui/resource_data.h b/plugingui/resource_data.h index c81c6cc..5d6392f 100644 --- a/plugingui/resource_data.h +++ b/plugingui/resource_data.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_RESOURCE_DATA_H__ -#define __DRUMGIZMO_RESOURCE_DATA_H__ +#pragma once typedef struct { const char *name; @@ -34,5 +33,3 @@ typedef struct { } rc_data_t; extern const rc_data_t rc_data[]; - -#endif/*__DRUMGIZMO_RESOURCE_DATA_H__*/ diff --git a/plugingui/scrollbar.cc b/plugingui/scrollbar.cc index 07dc36b..2a9d3fd 100644 --- a/plugingui/scrollbar.cc +++ b/plugingui/scrollbar.cc @@ -30,156 +30,180 @@ #include "painter.h" -GUI::ScrollBar::ScrollBar(GUI::Widget *parent) - : GUI::Widget(parent), bg_img(":widget_c.png") +namespace GUI { + +ScrollBar::ScrollBar(Widget *parent) + : Widget(parent) + , bg_img(":widget_c.png") { - handler = NULL; - ptr = NULL; } -void GUI::ScrollBar::setRange(int r) +void ScrollBar::setRange(int r) { - DEBUG(scroll, "%d\n", r); - ran = r; - setValue(value()); - repaintEvent(NULL); + rangeValue = r; + setValue(value()); + repaintEvent(nullptr); } -int GUI::ScrollBar::range() +int ScrollBar::range() { - return ran; + return rangeValue; } -void GUI::ScrollBar::setMaximum(int m) +void ScrollBar::setMaximum(int m) { - DEBUG(scroll, "%d\n", m); - max = m; - if(max < ran) ran = max; - setValue(value()); - repaintEvent(NULL); + maxValue = m; + if(maxValue < rangeValue) + { + rangeValue = maxValue; + } + setValue(value()); + repaintEvent(nullptr); } -int GUI::ScrollBar::maximum() +int ScrollBar::maximum() { - return max; + return maxValue; } -void GUI::ScrollBar::setValue(int value) +void ScrollBar::addValue(int delta) { - val = value; - if(val > max - ran) val = max - ran; - if(val < 0) val = 0; - - if(handler) handler(ptr); - - repaintEvent(NULL); + setValue(value() + delta); } -int GUI::ScrollBar::value() +void ScrollBar::setValue(int value) { - return val; + if(value > (maxValue - rangeValue)) + { + value = maxValue - rangeValue; + } + + if(value < 0) + { + value = 0; + } + + if(currentValue == value) + { + return; + } + + currentValue = value; + + valueChangeNotifier(value); + + repaintEvent(nullptr); } -void GUI::ScrollBar::registerValueChangeHandler(void (*handler)(void *), - void *ptr) +int ScrollBar::value() { - this->handler = handler; - this->ptr = ptr; + return currentValue; } -static void drawArrow(GUI::Painter &p, int x, int y, int w, int h) +//! Draw an up/down arrow at (x,y) with the bounding box size (w,h) +//! If h is negative the arrow will point down, if positive it will point up. +static void drawArrow(Painter &p, int x, int y, int w, int h) { - if(h < 0) y -= h; + if(h < 0) + { + y -= h; + } - p.drawLine(x, y, x+(w/2), y+h); - p.drawLine(x+(w/2), y+h, x+w, y); + p.drawLine(x, y, x + (w / 2), y + h); + p.drawLine(x + (w / 2), y + h, x + w, y); - y++; - p.drawLine(x, y, x+(w/2), y+h); - p.drawLine(x+(w/2), y+h, x+w, y); + ++y; + p.drawLine(x, y, x + (w / 2), y + h); + p.drawLine(x + (w / 2), y + h, x + w, y); } -void GUI::ScrollBar::repaintEvent(RepaintEvent *e) +void ScrollBar::repaintEvent(RepaintEvent* repaintEvent) { - GUI::Painter p(this); + Painter p(*this); - p.clear(); + p.clear(); - p.drawImageStretched(0, 0, &bg_img, width(), height()); + p.drawImageStretched(0, 0, bg_img, width(), height()); - p.setColour(GUI::Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); - if(!max) return; + p.setColour(Colour(183.0/255.0, 219.0/255.0 , 255.0/255.0, 1)); + if(!maxValue) + { + return; + } - { - int h = height() - 2 * width() - 3; - int offset = width() + 2; + { + int h = height() - 2 * width() - 3; + int offset = width() + 2; - int y_val1 = (val * h) / max; - int y_val2 = ((val + ran) * h) / max; + int y_val1 = (currentValue * h) / maxValue; + int y_val2 = ((currentValue + rangeValue) * h) / maxValue; - p.drawFilledRectangle(2, y_val1 + offset, width() - 1, y_val2 + offset); - } + p.drawFilledRectangle(2, y_val1 + offset, width() - 1, y_val2 + offset); + } - p.drawLine(0, 0, 0, height()); + p.drawLine(0, 0, 0, height()); - drawArrow(p, width()/4, width()/4, width()/2, -1 * (width()/3)); - p.drawLine(0, width(), width(), width()); + drawArrow(p, width()/4, width()/4, width()/2, -1 * (width()/3)); + p.drawLine(0, width(), width(), width()); - drawArrow(p, width()/4, height() - width() + width()/4, width()/2, width()/3); - p.drawLine(0, height() - width(), width(), height() - width()); + drawArrow(p, width()/4, height() - width() + width()/4, width()/2, width()/3); + p.drawLine(0, height() - width(), width(), height() - width()); } -void GUI::ScrollBar::scrollEvent(ScrollEvent *e) +void ScrollBar::scrollEvent(ScrollEvent* scrollEvent) { - setValue(value() + e->delta); + setValue(value() + scrollEvent->delta); } -void GUI::ScrollBar::mouseMoveEvent(MouseMoveEvent *e) +void ScrollBar::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) { - if(!dragging) return; + if(!dragging) + { + return; + } - float delta = yoffset - e->y; + float delta = yOffset - mouseMoveEvent->y; - int h = height() - 2 * width() - 3; - delta /= (float)h / (float)max; + int h = height() - 2 * width() - 3; + delta /= (float)h / (float)maxValue; - int newval = value_offset - delta; - if(newval != value()) setValue(newval); + int newval = valueOffset - delta; + if(newval != value()) + { + setValue(newval); + } } -void GUI::ScrollBar::buttonEvent(ButtonEvent *e) +void ScrollBar::buttonEvent(ButtonEvent* buttonEvent) { - if(e->y < (int)width() && e->y > 0) { - if(e->direction == -1) setValue(value() - 1); - return; - } - - if(e->y > (int)height() - (int)width() && e->y < (int)height()) { - if(e->direction == -1) setValue(value() + 1); - return; - } - - if(e->direction == 1) { - yoffset = e->y; - value_offset = value(); - } - - dragging = (e->direction == 1); + if((buttonEvent->y < (int)width()) && buttonEvent->y > 0) + { + if(buttonEvent->direction == Direction::down) + { + addValue(-1); + } + + return; + } + + if((buttonEvent->y > ((int)height() - (int)width())) && + (buttonEvent->y < (int)height())) + { + if(buttonEvent->direction == Direction::down) + { + addValue(1); + } + + return; + } + + if(buttonEvent->direction == Direction::down) + { + yOffset = buttonEvent->y; + valueOffset = value(); + } + + dragging = (buttonEvent->direction == Direction::down); } -#ifdef TEST_SCROLLBAR -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_SCROLLBAR*/ +} // GUI:: diff --git a/plugingui/scrollbar.h b/plugingui/scrollbar.h index 52acf9d..99f8377 100644 --- a/plugingui/scrollbar.h +++ b/plugingui/scrollbar.h @@ -24,52 +24,51 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_SCROLLBAR_H__ -#define __DRUMGIZMO_SCROLLBAR_H__ +#pragma once + +#include <limits> #include "widget.h" #include "image.h" +#include "notifier.h" namespace GUI { class ScrollBar : public Widget { + friend class ListBoxBasic; public: - ScrollBar(Widget *parent); - - bool catchMouse() { return true; } + ScrollBar(Widget *parent); - void setRange(int range); - int range(); + void setRange(int range); + int range(); - void setMaximum(int max); - int maximum(); + void setMaximum(int max); + int maximum(); - void setValue(int value); - int value(); + void addValue(int delta); + void setValue(int value); + int value(); - void registerValueChangeHandler(void (*handler)(void *), void *ptr); + Notifier<int> valueChangeNotifier; // (int value) - void repaintEvent(RepaintEvent *e); - void scrollEvent(ScrollEvent *e); - void buttonEvent(ButtonEvent *e); - void mouseMoveEvent(MouseMoveEvent *e); +protected: + // From Widget: + bool catchMouse() override { return true; } + void scrollEvent(ScrollEvent* scrollEvent) override; + void repaintEvent(RepaintEvent* repaintEvent) override; + void buttonEvent(ButtonEvent* buttonEvent) override; + void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; private: - int max; - int val; - int ran; - - int yoffset; - int value_offset; - bool dragging; + int maxValue{100}; + int currentValue{0}; + int rangeValue{10}; - Image bg_img; + int yOffset{0}; + int valueOffset{0}; + bool dragging{false}; - void (*handler)(void *); - void *ptr; + Image bg_img; }; -}; - - -#endif/*__DRUMGIZMO_SCROLLBAR_H__*/ +} // GUI:: diff --git a/plugingui/slider.cc b/plugingui/slider.cc index 953c8e6..a3c10f9 100644 --- a/plugingui/slider.cc +++ b/plugingui/slider.cc @@ -31,128 +31,132 @@ #include <hugin.hpp> #include <stdio.h> -GUI::Slider::Slider(Widget *parent) - : GUI::Widget(parent) -{ - state = up; +namespace GUI { - val = 0.0; - maximum = 1.0; - minimum = 0.0; +Slider::Slider(Widget *parent) + : Widget(parent) +{ + state = State::up; - handler = NULL; - ptr = NULL; + currentValue = 0.0; + maximum = 1.0; + minimum = 0.0; } -void GUI::Slider::setValue(float v) +void Slider::setValue(float newValue) { - val = v; - if(handler) handler(ptr); - repaintEvent(NULL); + currentValue = newValue; + repaintEvent(nullptr); + clickNotifier(); } -float GUI::Slider::value() +float Slider::value() { - return val; + return currentValue; } -void GUI::Slider::registerClickHandler(void (*handler)(void *), void *ptr) +void Slider::repaintEvent(RepaintEvent* repaintEvent) { - this->handler = handler; - this->ptr = ptr; + Painter p(*this); + + float alpha = 0.8; + + int xpos = (int)((currentValue / maximum) * (float)(width() - 1)); + + if(hasKeyboardFocus()) + { + p.setColour(Colour(0.6, alpha)); + } + else + { + p.setColour(Colour(0.5, alpha)); + } + + p.drawFilledRectangle(0,0,width(),height()); + + //p.setColour(Colour(0.1, alpha)); + //p.drawRectangle(0,0,width()-1,height() - 1); + + p.setColour(Colour(1, 0, 0, alpha)); + p.drawLine(xpos, 0, xpos, height() - 1); + + //p.setColour(Colour(0.8, alpha)); + //switch(state) { + //case State::up: + // p.drawLine(0, 0, 0, height() - 1); + // p.drawLine(0, 0, width() - 1, 0); + // break; + //case State::down: + // p.drawLine(width() - 1, 0, width() - 1, height() - 1); + // p.drawLine(width() - 1, height() - 1, 0, height() - 1); + // break; + //} + + p.setColour(Colour(0.3, alpha)); + p.drawPoint(0, height() - 1); + p.drawPoint(width() - 1, 0); } -void GUI::Slider::mouseMoveEvent(MouseMoveEvent *e) +void Slider::buttonEvent(ButtonEvent* buttonEvent) { - if(state == down) { - val = maximum / (float)width() * (float)e->x; - - if(val < 0) val = 0; - if(val > 1) val = 1; - - if(handler) handler(ptr); - repaintEvent(NULL); - } + if(buttonEvent->direction == Direction::down) + { + state = State::down; + currentValue = maximum / (float)width() * (float)buttonEvent->x; + + if(currentValue < 0) + { + currentValue = 0; + } + + if(currentValue > 1) + { + currentValue = 1; + } + + repaintEvent(nullptr); + clickNotifier(); + } + + if(buttonEvent->direction == Direction::up) + { + state = State::up; + currentValue = maximum / (float)width() * (float)buttonEvent->x; + + if(currentValue < 0) + { + currentValue = 0; + } + + if(currentValue > 1) + { + currentValue = 1; + } + + repaintEvent(nullptr); + clickNotifier(); + } } -void GUI::Slider::buttonEvent(ButtonEvent *e) +void Slider::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) { - if(e->direction == 1) { - state = down; - val = maximum / (float)width() * (float)e->x; - - if(val < 0) val = 0; - if(val > 1) val = 1; - - if(handler) handler(ptr); - repaintEvent(NULL); - } - if(e->direction == -1) { - state = up; - val = maximum / (float)width() * (float)e->x; - - if(val < 0) val = 0; - if(val > 1) val = 1; - - repaintEvent(NULL); - clicked(); - if(handler) handler(ptr); - } + if(state == State::down) + { + currentValue = maximum / (float)width() * (float)mouseMoveEvent->x; + + if(currentValue < 0) + { + currentValue = 0; + } + + if(currentValue > 1) + { + currentValue = 1; + } + + repaintEvent(nullptr); + clickNotifier(); + } } -void GUI::Slider::repaintEvent(GUI::RepaintEvent *e) -{ - //DEBUG(slider, "Slider::repaintEvent (%f)\n", val); - - Painter p(this); - - float alpha = 0.8; - - int xpos = (int)((val / maximum) * (float)(width() - 1)); - - if(hasKeyboardFocus()) { - p.setColour(Colour(0.6, alpha)); - } else { - p.setColour(Colour(0.5, alpha)); - } - p.drawFilledRectangle(0,0,width(),height()); - /* - p.setColour(Colour(0.1, alpha)); - p.drawRectangle(0,0,width()-1,height()-1); - */ - p.setColour(Colour(1, 0, 0, alpha)); - p.drawLine(xpos, 0, xpos, height()-1); - /* - p.setColour(Colour(0.8, alpha)); - switch(state) { - case up: - p.drawLine(0,0,0,height()-1); - p.drawLine(0,0,width()-1,0); - break; - case down: - p.drawLine(width()-1,0, width()-1,height()-1); - p.drawLine(width()-1,height()-1,0, height()-1); - break; - } - */ - p.setColour(Colour(0.3, alpha)); - p.drawPoint(0,height()-1); - p.drawPoint(width()-1,0); -} - -#ifdef TEST_SLIDER -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_SLIDER*/ +} // GUI:: diff --git a/plugingui/slider.h b/plugingui/slider.h index f07ccff..01cbd54 100644 --- a/plugingui/slider.h +++ b/plugingui/slider.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_SLIDER_H__ -#define __DRUMGIZMO_SLIDER_H__ +#pragma once #include "widget.h" @@ -33,38 +32,32 @@ namespace GUI { class Slider : public Widget { public: - Slider(Widget *parent); + Slider(Widget* parent); - bool catchMouse() { return true; } + // From Widget: + bool catchMouse() override { return true; } - void setValue(float value); - float value(); + void setValue(float value); + float value(); - void registerClickHandler(void (*handler)(void *), void *ptr); + Notifier<> clickNotifier; - //protected: - virtual void clicked() {} - - virtual void repaintEvent(RepaintEvent *e); - virtual void buttonEvent(ButtonEvent *e); - virtual void mouseMoveEvent(MouseMoveEvent *e); +protected: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + virtual void buttonEvent(ButtonEvent* buttonEvent) override; + virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; private: - typedef enum { - up, - down - } state_t; - - float val; - float maximum; - float minimum; + enum class State { + up, + down + }; - state_t state; - - void (*handler)(void *); - void *ptr; -}; + float currentValue; + float maximum; + float minimum; + State state; }; -#endif/*__DRUMGIZMO_SLIDER_H__*/ +} // GUI:: diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc new file mode 100644 index 0000000..7b1bfec --- /dev/null +++ b/plugingui/testmain.cc @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * testmain.cc + * + * Sun Nov 22 20:06:42 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "plugingui.h" + +#include <hugin.hpp> + +// Dummy Engine class. +class Engine : public MessageHandler { +public: + void handleMessage(Message *msg) {} +}; + +class TestMain : public GUI::Listener { +public: + TestMain() + { + CONNECT(&gui, closeNotifier, this, &TestMain::stop); + } + + void stop() + { + DEBUG(stop, "Stopping...\n"); + running = false; + } + + void run() + { + while(running) + { +#ifdef WIN32 + SleepEx(1000, FALSE); +#else + sleep(1); +#endif + } + } + + bool running = true; + + GUI::PluginGUI gui; +}; + +int main() +{ + INFO(example, "We are up and running"); + + TestMain testMain; + testMain.run(); + + return 0; +} diff --git a/plugingui/textedit.cc b/plugingui/textedit.cc new file mode 100644 index 0000000..7342421 --- /dev/null +++ b/plugingui/textedit.cc @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * lineedit.cc + * + * Tue Oct 21 11:25:26 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "textedit.h" + +#include "window.h" + +#include <assert.h> +#include <list> +#include <hugin.hpp> +#include <stdio.h> + +#define BORDER 10 + +namespace GUI { + +TextEdit::TextEdit(Widget *parent) + : Widget(parent) + , scroll(this) +{ + setReadOnly(true); + + scroll.move(width() - 5, 1); + scroll.resize(20, 100); + CONNECT(&scroll, valueChangeNotifier, this, &TextEdit::scrolled); + + box.topLeft = new Image(":widget_tl.png"); + box.top = new Image(":widget_t.png"); + box.topRight = new Image(":widget_tr.png"); + box.left = new Image(":widget_l.png"); + box.right = new Image(":widget_r.png"); + box.bottomLeft = new Image(":widget_bl.png"); + box.bottom = new Image(":widget_b.png"); + box.bottomRight = new Image(":widget_br.png"); + box.center = new Image(":widget_c.png"); +} + +TextEdit::~TextEdit() +{ + delete box.topLeft; + delete box.top; + delete box.topRight; + delete box.left; + delete box.right; + delete box.bottomLeft; + delete box.bottom; + delete box.bottomRight; + delete box.center; +} + +void TextEdit::resize(int height, int width) +{ + Widget::resize(height, width); + scroll.resize(scroll.width(), height-10); + scroll.move(width-30,7); +} + +void TextEdit::setReadOnly(bool readonly) +{ + this->readonly = readonly; +} + +bool TextEdit::readOnly() +{ + return readonly; +} + +void TextEdit::setText(const std::string& text) +{ + _text = text; + + preprocessText(); + + int ran = height() / font.textHeight(); + + DEBUG(textedit, "Setting range and max of scrollbar to '%d' and '%d'\n", + ran, (int)preprocessedtext.size()); + + scroll.setRange(ran); + scroll.setMaximum(preprocessedtext.size()); + + repaintEvent(nullptr); + + textChangedNotifier(); +} + +std::string TextEdit::text() +{ + return _text; +} + +void TextEdit::preprocessText() +{ + preprocessedtext.clear(); + std::string text = _text; + + { // Handle tab characters + for(size_t i = 0; i < text.length(); ++i) + { + char ch = text.at(i); + if(ch == '\t') + { + text.erase(i, 1); + text.insert(i, 4, ' '); + } + } + } + + std::list<std::string> lines; + { // Handle new line characters + size_t pos = 0; + do + { + pos = text.find("\n"); + lines.push_back(text.substr(0, pos)); + text = text.substr(pos+1); + } + while(pos != std::string::npos); + } + + { // Wrap long lines + std::list<std::string>::iterator it; + for(it = lines.begin(); it != lines.end(); ++it) + { + std::string line = *it; + + for(size_t i = 0; i < line.length(); ++i) + { + size_t linewidth = font.textWidth(line.substr(0, i)); + if(linewidth >= width() - BORDER - 4 + 3 - 10 - scroll.width()) { + preprocessedtext.push_back(line.substr(0, i)); + line = line.substr(i); + i = 0; + } + } + preprocessedtext.push_back(line); + } + } +} + +void TextEdit::repaintEvent(RepaintEvent* repaintEvent) +{ + Painter p(*this); + + p.clear(); + + int w = width(); + int h = height(); + if((w == 0) || (h == 0)) + { + return; + } + + p.drawBox(0, 0, box, w, h); + + p.setColour(Colour(183.0 / 255.0, 219.0 / 255.0 , 255.0 / 255.0, 1)); + + int skip = scroll.value(); + + int ypos = font.textHeight() + 5 + 1 + 1 + 1; + std::list<std::string>::iterator it; + it = preprocessedtext.begin(); + + int c = 0; + for( ; c < skip; c++) + { + ++it; + } + + c = 0; + for( ; it != preprocessedtext.end(); it++) + { + if((c * font.textHeight()) >= (height() - 8 - font.textHeight())) + { + break; + } + + std::string line = *it; + p.drawText(BORDER - 4 + 3, ypos, font, line); + ypos += font.textHeight(); + ++c; + } +} + +void TextEdit::scrolled(int value) +{ + (void)value; + repaintEvent(nullptr); +} + +} // GUI:: diff --git a/plugingui/textedit.h b/plugingui/textedit.h new file mode 100644 index 0000000..d1b4a01 --- /dev/null +++ b/plugingui/textedit.h @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * textedit.h + * + * Tue Oct 21 11:23:58 CEST 2014 + * Copyright 2014 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include <string> +#include <list> + +#include "widget.h" +#include "font.h" +#include "painter.h" +#include "scrollbar.h" + +#include "notifier.h" + +namespace GUI { + +class TextEdit : public Widget { +public: + TextEdit(Widget *parent); + ~TextEdit(); + + // From Widget + bool isFocusable() override { return true; } + void resize(int width, int height) override; + + std::string text(); + void setText(const std::string& text); + + void setReadOnly(bool readonly); + bool readOnly(); + + void preprocessText(); + + Notifier<> textChangedNotifier; + +protected: + // From Widget + virtual void repaintEvent(RepaintEvent* repaintEvent) override; + +private: + void scrolled(int value); + + Painter::Box box; + ScrollBar scroll; + Font font; + + std::string _text; + size_t pos{0}; + + bool readonly{true}; + + std::list< std::string > preprocessedtext; +}; + +} // GUI:: diff --git a/plugingui/verticalline.cc b/plugingui/verticalline.cc index 53d82a6..5bf4afd 100644 --- a/plugingui/verticalline.cc +++ b/plugingui/verticalline.cc @@ -28,14 +28,24 @@ #include "painter.h" -GUI::VerticalLine::VerticalLine(GUI::Widget *parent) - : Widget(parent), vline(":vertline.png") +namespace GUI { + +VerticalLine::VerticalLine(Widget *parent) + : Widget(parent) + , vline(":vertline.png") { } -void GUI::VerticalLine::repaintEvent(RepaintEvent *e) +void VerticalLine::repaintEvent(RepaintEvent* repaintEvent) { - (void)e; - GUI::Painter p(this); - p.drawImageStretched(0, 0, &vline, width(), height()); + if(height() < 2) + { + return; + } + + Painter p(*this); + p.drawImageStretched(0, (height() - vline.height()) / 2, + vline, width(), vline.height()); } + +} // GUI:: diff --git a/plugingui/verticalline.h b/plugingui/verticalline.h index 7c1bc27..1d05eac 100644 --- a/plugingui/verticalline.h +++ b/plugingui/verticalline.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_VERTICALLINE_H__ -#define __DRUMGIZMO_VERTICALLINE_H__ +#pragma once #include "widget.h" #include "image.h" @@ -34,15 +33,14 @@ namespace GUI { class VerticalLine : public Widget { public: - VerticalLine(Widget *parent); + VerticalLine(Widget* parent); - //protected: - virtual void repaintEvent(RepaintEvent *e); +protected: + // From Widget: + virtual void repaintEvent(RepaintEvent* repaintEvent) override; private: - Image vline; + Image vline; }; -}; - -#endif/*__DRUMGIZMO_VERTICALLINE_H__*/ +} // GUI:: diff --git a/plugingui/widget.cc b/plugingui/widget.cc index b3e3cc8..5c8ff46 100644 --- a/plugingui/widget.cc +++ b/plugingui/widget.cc @@ -31,188 +31,191 @@ #include <stdio.h> -GUI::Widget::Widget(Widget *parent) - : pixbuf(1, 1) +namespace GUI { + +Widget::Widget(Widget* parent) + : parent(parent) { - _width = _height = 10; + if(parent) + { + parent->addChild(this); + _window = parent->window(); + } - this->parent = parent; - if(parent) { - parent->addChild(this); - _window = parent->window(); - } - _width = _height = 0; - _visible = true; + _width = _height = 0; + _visible = true; } -GUI::Widget::~Widget() +Widget::~Widget() { - if(parent) parent->removeChild(this); + if(parent) + { + parent->removeChild(this); + } } -void GUI::Widget::show() +void Widget::show() { - setVisible(true); + setVisible(true); } -void GUI::Widget::hide() +void Widget::hide() { - setVisible(false); + setVisible(false); } -void GUI::Widget::setVisible(bool v) +void Widget::setVisible(bool visible) { - _visible = v; - repaintEvent(NULL); + _visible = visible; + repaintEvent(nullptr); } -bool GUI::Widget::visible() +bool Widget::visible() { - return _visible; + return _visible; } -void GUI::Widget::addChild(GUI::Widget *widget) +void Widget::addChild(Widget* widget) { - children.push_back(widget); + children.push_back(widget); } -void GUI::Widget::removeChild(GUI::Widget *widget) +void Widget::removeChild(Widget* widget) { - std::vector<Widget *>::iterator i = children.begin(); - while(i != children.end()) { - if(*i == widget) { - children.erase(i); - return; - } - i++; - } + for(auto i = children.begin(); i != children.end(); ++i) + { + if(*i == widget) + { + children.erase(i); + return; + } + } } -void GUI::Widget::resize(int width, int height) +void Widget::resize(int width, int height) { - if(width < 1 || height < 1) return; - _width = width; - _height = height; - pixbuf.realloc(width, height); + if((width < 1) || (height < 1) || + (((size_t)width == _width) && ((size_t)height == _height))) + { + return; + } + + _width = width; + _height = height; + pixbuf.realloc(width, height); + + sizeChangeNotifier(width, height); } -void GUI::Widget::move(size_t x, size_t y) +void Widget::move(size_t x, size_t y) { - _x = x; - _y = y; + _x = x; + _y = y; } -size_t GUI::Widget::x() { return _x; } -size_t GUI::Widget::y() { return _y; } -size_t GUI::Widget::width() { return _width; } -size_t GUI::Widget::height() { return _height; } - -size_t GUI::Widget::windowX() +int Widget::x() { - size_t window_x = x(); - if(parent) window_x += parent->windowX(); - return window_x; + return _x; } -size_t GUI::Widget::windowY() +int Widget::y() { - size_t window_y = y(); - if(parent) window_y += parent->windowY(); - return window_y; + return _y; } -GUI::Widget *GUI::Widget::find(size_t x, size_t y) +size_t Widget::width() { - std::vector<Widget*>::reverse_iterator i = children.rbegin(); - while(i != children.rend()) { - Widget *w = *i; - if(w->visible()) { - if(w->x() <= x && (w->x() + w->width()) >= x && - w->y() <= y && w->y() + w->height() >= y) - return w->find(x - w->x(), y - w->y()); - } - i++; - } - - if(x > width() /*|| x < 0*/ || y > height() /*|| y < 0*/) return NULL; - return this; + return _width; } -GUI::Window *GUI::Widget::window() +size_t Widget::height() { - return _window; + return _height; } -void GUI::Widget::repaint_r(GUI::RepaintEvent *e) +size_t Widget::windowX() { - Painter p(this); // make sure pixbuf refcount is incremented. + size_t window_x = x(); - repaintEvent(e); + if(parent) + { + window_x += parent->windowX(); + } - std::vector<Widget*>::iterator i = children.begin(); - while(i != children.end()) { - Widget *w = *i; - w->repaint_r(e); - i++; - } + return window_x; } -std::vector<GUI::PixelBufferAlpha *> GUI::Widget::getPixelBuffers() +size_t Widget::windowY() { - std::vector<PixelBufferAlpha *> pbs; - - pixbuf.x = windowX(); - pixbuf.y = windowY(); + size_t window_y = y(); + if(parent) + { + window_y += parent->windowY(); + } - pbs.push_back(&pixbuf); + return window_y; +} - std::vector<Widget*>::iterator i = children.begin(); - while(i != children.end()) { - Widget *w = *i; - if(w->visible()) { - std::vector<PixelBufferAlpha *> pbs0 = w->getPixelBuffers(); - pbs.insert(pbs.end(), pbs0.begin(), pbs0.end()); - } - i++; - } +Widget* Widget::find(int x, int y) +{ + for(auto i = children.rbegin(); i != children.rend(); ++i) + { + Widget* widget = *i; + if(widget->visible()) + { + if((x >= widget->x()) && (x < (widget->x() + (int)widget->width())) && + (y >= widget->y()) && (y < (widget->y() + (int)widget->height()))) + { + return widget->find(x - widget->x(), y - widget->y()); + } + } + } - return pbs; + return this; } -bool GUI::Widget::hasKeyboardFocus() +Window* Widget::window() { - return window()->keyboardFocus() == this; + return _window; } -#ifdef TEST_WIDGET -//deps: window.cc globalcontext.cc -//cflags: -//libs: -#include "test.h" +std::vector<PixelBufferAlpha*> Widget::getPixelBuffers() +{ + std::vector<PixelBufferAlpha*> pixelBuffers; -#include "window.h" + pixbuf.x = windowX(); + pixbuf.y = windowY(); -TEST_BEGIN; + pixelBuffers.push_back(&pixbuf); -GUI::Window w1(NULL); -w1.move(0,0); -w1.resize(100, 100); + for(auto child : children) + { + if(child->visible()) + { + auto childPixelBuffers = child->getPixelBuffers(); + pixelBuffers.insert(pixelBuffers.end(), + childPixelBuffers.begin(), childPixelBuffers.end()); + } + } + + return pixelBuffers; +} -GUI::Widget w2(&w1); -w2.resize(40,40); -w2.move(10,10); +bool Widget::hasKeyboardFocus() +{ + return window()->keyboardFocus() == this; +} -GUI::Widget w3(&w2); -w3.resize(20,20); -w3.move(10,10); +void Widget::repaintChildren(RepaintEvent* repaintEvent) +{ + Painter p(*this); // make sure pixbuf refcount is incremented. -TEST_EQUAL_PTR(w1.find(101,0), NULL, "Miss?"); -TEST_EQUAL_PTR(w1.find(0,0), &w1, "Hit w1?"); -TEST_EQUAL_PTR(w1.find(100,100), &w1, "Hit w1?"); -TEST_EQUAL_PTR(w1.find(0,0), &w1, "Hit w1?"); -TEST_EQUAL_PTR(w1.find(11,11), &w2, "Hit w2?"); -TEST_EQUAL_PTR(w1.find(22,22), &w3, "Hit w3?"); + this->repaintEvent(repaintEvent); -TEST_END; + for(auto child : children) + { + child->repaintChildren(repaintEvent); + } +} -#endif/*TEST_WIDGET*/ +} // GUI:: diff --git a/plugingui/widget.h b/plugingui/widget.h index 47c374e..6bfffb5 100644 --- a/plugingui/widget.h +++ b/plugingui/widget.h @@ -24,11 +24,12 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_WIDGET_H__ -#define __DRUMGIZMO_WIDGET_H__ +#pragma once #include "guievent.h" #include "pixelbuffer.h" +#include "notifier.h" +#include "layout.h" #include <vector> @@ -36,64 +37,69 @@ namespace GUI { class Window; -class Widget { +class Widget : public Listener, public LayoutItem { + friend class Painter; public: - Widget(Widget *parent); - virtual ~Widget(); + Widget(Widget* parent); + virtual ~Widget(); - virtual void show(); - virtual void hide(); + virtual void show(); + virtual void hide(); - virtual void resize(int width, int height); - virtual void move(size_t x, size_t y); + // From LayoutItem + virtual void resize(int width, int height) override; + virtual void move(size_t x, size_t y) override; + virtual int x() override; + virtual int y() override; + virtual size_t width() override; + virtual size_t height() override; - virtual size_t x(); - virtual size_t y(); - virtual size_t windowX(); - virtual size_t windowY(); - virtual size_t width(); - virtual size_t height(); + virtual size_t windowX(); + virtual size_t windowY(); - virtual bool isFocusable() { return false; } - virtual bool catchMouse() { return false; } + virtual bool isFocusable() { return false; } + virtual bool catchMouse() { return false; } - void addChild(Widget *widget); - void removeChild(Widget *widget); + void addChild(Widget* widget); + void removeChild(Widget* widget); - virtual void repaintEvent(RepaintEvent *e) {} - virtual void mouseMoveEvent(MouseMoveEvent *e) {} - virtual void buttonEvent(ButtonEvent *e) {} - virtual void scrollEvent(ScrollEvent *e) {} - virtual void keyEvent(KeyEvent *e) {} + virtual void repaintEvent(RepaintEvent* repaintEvent) {} + virtual void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) {} + virtual void buttonEvent(ButtonEvent* buttonEvent) {} + virtual void scrollEvent(ScrollEvent* scrollEvent) {} + virtual void keyEvent(KeyEvent* keyEvent) {} + virtual void mouseLeaveEvent() {} + virtual void mouseEnterEvent() {} - virtual void mouseLeaveEvent() {} - virtual void mouseEnterEvent() {} + Widget* find(int x, int y); - Widget *find(size_t x, size_t y); + virtual Window* window(); - virtual Window *window(); + std::vector<PixelBufferAlpha*> getPixelBuffers(); - void repaint_r(RepaintEvent *e); + bool hasKeyboardFocus(); - PixelBufferAlpha pixbuf; - std::vector<PixelBufferAlpha *> getPixelBuffers(); + bool visible(); + void setVisible(bool visible); - bool hasKeyboardFocus(); + Notifier<int, int> sizeChangeNotifier; // (int, width, int height) - Widget *parent; +protected: + void repaintChildren(RepaintEvent* repaintEvent); - bool visible(); - void setVisible(bool visible); + PixelBufferAlpha pixbuf{0,0}; -protected: - std::vector<Widget*> children; - Window *_window; - size_t _x, _y, _width, _height; + std::vector<Widget*> children; -private: - bool _visible; -}; + Widget* parent = nullptr; + Window* _window = nullptr; + + int _x{0}; + int _y{0}; + size_t _width{0}; + size_t _height{0}; + bool _visible = true; }; -#endif/*__DRUMGIZMO_WIDGET_H__*/ +} // GUI:: diff --git a/plugingui/window.cc b/plugingui/window.cc index 8337533..9263128 100644 --- a/plugingui/window.cc +++ b/plugingui/window.cc @@ -26,13 +26,8 @@ */ #include "window.h" -#include "painter.h" - -#include <stdio.h> -#include <stdlib.h> - -#include <string.h> #include <hugin.hpp> +#include "painter.h" #ifndef PUGL #ifdef X11 @@ -45,201 +40,230 @@ #include "nativewindow_pugl.h" #endif -GUI::Window::Window() - : Widget(NULL), wpixbuf(100, 100), back(":bg.png"), logo(":logo.png") -{ - _x = _y = 100; - _width = wpixbuf.width; - _height = wpixbuf.height; +namespace GUI { - refcount = 0; - max_refcount = 0; - _keyboardFocus = this; - _buttonDownFocus = NULL; - _mouseFocus = NULL; +Window::Window() + : Widget(nullptr) + , wpixbuf(100, 100) +{ + // Make sure we have a valid size when initialising the NativeWindow + _width = wpixbuf.width; + _height = wpixbuf.height; #ifndef PUGL #ifdef X11 - native = new NativeWindowX11(this); + native = new NativeWindowX11(*this); #endif/*X11*/ #ifdef WIN32 - native = new NativeWindowWin32(this); + native = new NativeWindowWin32(*this); #endif/*WIN32*/ #else/*Use pugl*/ - native = new NativeWindowPugl(this); + native = new NativeWindowPugl(this); #endif - eventhandler = new GUI::EventHandler(native, this); + eventhandler = new EventHandler(*native, *this); } -GUI::Window::~Window() +Window::~Window() { - delete native; - delete eventhandler; + delete native; + delete eventhandler; } -GUI::EventHandler *GUI::Window::eventHandler() +void Window::setFixedSize(int w, int h) { - return eventhandler; + native->setFixedSize(w, h); + resize(w,h); } -void GUI::Window::setCaption(std::string caption) +void Window::setCaption(const std::string& caption) { - native->setCaption(caption); + native->setCaption(caption); } -void GUI::Window::repaintEvent(GUI::RepaintEvent *e) +void Window::resize(int width, int height) { - if(!visible()) return; - - Painter p(this); - p.drawImageStretched(0,0, &back, width(), height()); - p.drawImage(width() - logo.width(), - height() - logo.height(), &logo); + if((width < 1) || (height < 1)) + { + return; + } + + resized(width, height); + Widget::resize(width, height); + native->resize(width, height); } -void GUI::Window::setFixedSize(int w, int h) +void Window::move(size_t x, size_t y) { - native->setFixedSize(w, h); - resize(w,h); + native->move(x, y); + + // Make sure widget corrdinates are updated. + Widget::move(x, y); } -void GUI::Window::resize(int width, int height) +size_t Window::windowX() { - if(width < 1 || height < 1) return; - - // This needs to be done on all platoforms when setFixedSize is introduced. - //#ifdef WIN32 - // Fix to force buffer size reallocation - // FIXME: This should've been done indirectly through a WM_SIZE message in the - // EventHandler... - resized(width, height); - //#endif - - Widget::resize(width, height); - native->resize(width, height); + return 0; } -void GUI::Window::move(size_t x, size_t y) +size_t Window::windowY() { - native->move(x, y); - - // Make sure widget corrds are updated. - Widget::move(x, y); + return 0; } -size_t GUI::Window::x() { return _x; } -size_t GUI::Window::y() { return _y; } -size_t GUI::Window::width() { return _width; } -size_t GUI::Window::height() { return _height; } -size_t GUI::Window::windowX() { return 0; } -size_t GUI::Window::windowY() { return 0; } - -void GUI::Window::show() +void Window::show() { - repaint_r(NULL); - native->show(); + repaintChildren(nullptr); + native->show(); } -void GUI::Window::hide() +void Window::hide() { - native->hide(); + native->hide(); } -GUI::Window *GUI::Window::window() +Window* Window::window() { - return this; + return this; } -void GUI::Window::beginPaint() +EventHandler* Window::eventHandler() { - refcount++; - if(refcount > max_refcount) max_refcount = refcount; + return eventhandler; } -void GUI::Window::endPaint() +Widget* Window::keyboardFocus() { - if(refcount) refcount--; - - if(!refcount) { - if(max_refcount > 1) { // Did we go deep enough for a buffer update? - updateBuffer(); - redraw(); - } - max_refcount = 0; - } + return _keyboardFocus; } -void GUI::Window::updateBuffer() +void Window::setKeyboardFocus(Widget* widget) { - DEBUG(window, "Updating buffer\n"); - memset(wpixbuf.buf, 0, wpixbuf.width * wpixbuf.height * 3); - - std::vector<PixelBufferAlpha *> pl = getPixelBuffers(); - std::vector<PixelBufferAlpha *>::iterator pli = pl.begin(); - while(pli != pl.end()) { - PixelBufferAlpha *pb = *pli; - for(size_t x = 0; x < pb->width; x++) { - for(size_t y = 0; y < pb->height; y++) { - unsigned char r,g,b,a; - pb->pixel(x,y,&r,&g,&b,&a); - wpixbuf.setPixel(x + pb->x, y + pb->y, r, g, b, a); - } - } - pli++; - } - native->handleBuffer(); + auto oldFocusWidget = _keyboardFocus; + _keyboardFocus = widget; + + if(oldFocusWidget) + { + oldFocusWidget->repaintEvent(nullptr); + } + + if(_keyboardFocus) + { + _keyboardFocus->repaintEvent(nullptr); + } } -void GUI::Window::resized(size_t w, size_t h) +Widget* Window::buttonDownFocus() { - if(_width == w && _height == h) return; - - _width = w; - _height = h; - wpixbuf.realloc(w, h); - updateBuffer(); - - pixbuf.realloc(w, h); - repaintEvent(NULL); + return _buttonDownFocus; } -void GUI::Window::redraw() +void Window::setButtonDownFocus(Widget* widget) { - native->redraw(); + _buttonDownFocus = widget; + native->grabMouse(widget != nullptr); } -GUI::Widget *GUI::Window::keyboardFocus() +Widget* Window::mouseFocus() { - return _keyboardFocus; + return _mouseFocus; } -void GUI::Window::setKeyboardFocus(GUI::Widget *widget) +void Window::setMouseFocus(Widget* widget) { - GUI::Widget *old_focus = _keyboardFocus; - _keyboardFocus = widget; + _mouseFocus = widget; + +} - if(old_focus) old_focus->repaintEvent(NULL); - if(_keyboardFocus) _keyboardFocus->repaintEvent(NULL); +void Window::redraw() +{ + native->redraw(); } -GUI::Widget *GUI::Window::buttonDownFocus() +void Window::resized(size_t width, size_t height) { - return _buttonDownFocus; + if((_width == width) && (_height == height)) + { + return; + } + + _width = width; + _height = height; + + wpixbuf.realloc(width, height); + updateBuffer(); + + pixbuf.realloc(width, height); + repaintEvent(nullptr); + + // Notify Widget + sizeChangeNotifier(width, height); } -void GUI::Window::setButtonDownFocus(GUI::Widget *widget) +void Window::updateBuffer() { - _buttonDownFocus = widget; - native->grabMouse(widget != NULL); + //DEBUG(window, "Updating buffer\n"); + for(auto pixelBuffer : getPixelBuffers()) + { + size_t updateWidth = pixelBuffer->width; + size_t updateHeight = pixelBuffer->height; + + // Skip buffer if not inside window. + if((wpixbuf.width < pixelBuffer->x) || (wpixbuf.height < pixelBuffer->y)) + { + continue; + } + + if(updateWidth > (wpixbuf.width - pixelBuffer->x)) + { + updateWidth = (wpixbuf.width - pixelBuffer->x); + } + + if(updateHeight > (wpixbuf.height - pixelBuffer->y)) + { + updateHeight = (wpixbuf.height - pixelBuffer->y); + } + + unsigned char r,g,b,a; + for(size_t y = 0; y < updateHeight; y++) + { + for(size_t x = 0; x < updateWidth; x++) + { + pixelBuffer->pixel(x, y, &r, &g, &b, &a); + wpixbuf.setPixel(x + pixelBuffer->x, y + pixelBuffer->y, r, g, b, a); + } + } + } + + native->handleBuffer(); } -GUI::Widget *GUI::Window::mouseFocus() +void Window::beginPaint() { - return _mouseFocus; + ++refcount; + if(refcount > maxRefcount) + { + maxRefcount = refcount; + } } -void GUI::Window::setMouseFocus(GUI::Widget *widget) +void Window::endPaint() { - _mouseFocus = widget; + if(refcount) + { + --refcount; + } + + if(!refcount) + { + // Did we go deep enough for a buffer update? + if(maxRefcount > 1) + { + updateBuffer(); + redraw(); + } + maxRefcount = 0; + } } + +} // GUI:: diff --git a/plugingui/window.h b/plugingui/window.h index f8deef0..1fffbb6 100644 --- a/plugingui/window.h +++ b/plugingui/window.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_WINDOW_H__ -#define __DRUMGIZMO_WINDOW_H__ +#pragma once #include "widget.h" @@ -38,68 +37,60 @@ namespace GUI { class Window : public Widget { public: - Window(); - ~Window(); + Window(); + ~Window(); - void show(); - void hide(); + void setFixedSize(int width, int height); + void setCaption(const std::string& caption); - void setFixedSize(int width, int height); - void resize(int width, int height); - void move(size_t x, size_t y); + // From Widget: + void resize(int width, int height) override; + void move(size_t x, size_t y) override; + size_t windowX() override; + size_t windowY() override; + void show() override; + void hide() override; + Window* window() override; - size_t x(); - size_t y(); - size_t windowX(); - size_t windowY(); - size_t width(); - size_t height(); + EventHandler* eventHandler(); - void setCaption(std::string caption); + Widget* keyboardFocus(); + void setKeyboardFocus(Widget* widget); - void addChild(Widget *widget); + Widget* buttonDownFocus(); + void setButtonDownFocus(Widget* widget); - void repaintEvent(GUI::RepaintEvent *e); - - void beginPaint(); - void endPaint(); - - Window *window(); - - EventHandler *eventHandler(); - - // handlers - virtual void redraw(); - void resized(size_t w, size_t h); - - Widget *keyboardFocus(); - void setKeyboardFocus(Widget *widget); - - Widget *buttonDownFocus(); - void setButtonDownFocus(Widget *widget); - - Widget *mouseFocus(); - void setMouseFocus(Widget *widget); - - PixelBuffer wpixbuf; - void updateBuffer(); + Widget* mouseFocus(); + void setMouseFocus(Widget* widget); protected: - size_t refcount; + // For the EventHandler + friend class EventHandler; + void redraw(); + void resized(size_t w, size_t h); + void updateBuffer(); - Widget *_keyboardFocus; - Widget *_buttonDownFocus; - Widget *_mouseFocus; + // For the Painter + friend class Painter; + void beginPaint(); + void endPaint(); - NativeWindow *native; - EventHandler *eventhandler; + // For the NativeWindow + friend class NativeWindowX11; + friend class NativeWindowWin32; + friend class NativeWindowPugl; + PixelBuffer wpixbuf; - Image back; - Image logo; + size_t refcount{0}; - size_t max_refcount; -}; + Widget* _keyboardFocus{nullptr}; + Widget* _buttonDownFocus{nullptr}; + Widget* _mouseFocus{nullptr}; + + NativeWindow* native{nullptr}; + EventHandler* eventhandler{nullptr}; + size_t maxRefcount{0}; }; -#endif/*__DRUMGIZMO_WINDOW_H__*/ +} // GUI:: diff --git a/src/configfile.cc b/src/configfile.cc index 6b0d14f..8447d9a 100644 --- a/src/configfile.cc +++ b/src/configfile.cc @@ -30,6 +30,7 @@ #include <errno.h> #include <string.h> #include <stdlib.h> +#include <unistd.h> #include <sys/stat.h> #include <sys/types.h> @@ -65,7 +66,7 @@ static std::string configPath() configpath = szPath; } #else - std::string configpath = strdup(getenv("HOME")); + std::string configpath = getenv("HOME"); #endif configpath += SEP; configpath += CONFIGDIRNAME; diff --git a/src/drumkit.h b/src/drumkit.h index 04b2c56..a9ceb80 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -56,13 +56,13 @@ public: size_t samplerate(); private: - void *magic; + void *magic{nullptr}; std::string _file; std::string _name; std::string _description; - size_t _samplerate; + size_t _samplerate{0}; VersionStr _version; }; diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 550d885..22859a0 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -92,13 +92,13 @@ private: Semaphore semaphore; Semaphore framesize_semaphore; Mutex mutex; - volatile bool running; + volatile bool running{false}; std::list<AudioFile*> load_queue; - size_t total_num_audiofiles; - size_t fraction; - size_t loaded; + size_t total_num_audiofiles{0}; + size_t fraction{1}; + size_t loaded{0}; - size_t framesize; + size_t framesize{0}; }; #endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/ diff --git a/src/instrumentparser.h b/src/instrumentparser.h index 2a7a9c9..60a6261 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -47,14 +47,14 @@ protected: int readData(char *data, size_t size); private: - FILE *fd; + FILE *fd{nullptr}; Instrument &instrument; - Sample *s; + Sample *s{nullptr}; std::string path; - level_t lower; - level_t upper; + level_t lower{0}; + level_t upper{0}; }; #endif/*__DRUMGIZMO_INSTRUMENTPARSER_H__*/ diff --git a/src/semaphore.cc b/src/semaphore.cc index b478eb1..2bd244c 100644 --- a/src/semaphore.cc +++ b/src/semaphore.cc @@ -28,6 +28,8 @@ #include <hugin.hpp> +#include <limits> + #ifdef WIN32 #include <windows.h> #else @@ -53,7 +55,7 @@ Semaphore::Semaphore(const char *name) #ifdef WIN32 prv->semaphore = CreateSemaphore(NULL, // default security attributes 0, // initial count - 2147483647, // maximum count (Max LONG) + std::numeric_limits<LONG>::max(), NULL); // unnamed semaphore #else sem_init(&prv->semaphore, 0, 0); @@ -70,7 +72,7 @@ Semaphore::~Semaphore() sem_destroy(&prv->semaphore); #endif - if(prv) delete prv; + delete prv; } void Semaphore::post() diff --git a/src/semaphore.h b/src/semaphore.h index 7e39f5a..ed284de 100644 --- a/src/semaphore.h +++ b/src/semaphore.h @@ -38,8 +38,8 @@ public: void wait(); private: - struct semaphore_private_t *prv; - const char *name; + struct semaphore_private_t *prv{nullptr}; + const char *name{nullptr}; }; #endif/*__PRACRO_SEMAPHORE_H__*/ diff --git a/src/thread.cc b/src/thread.cc index 8abf3cb..6e216e9 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -29,18 +29,6 @@ #include <stdio.h> #include <hugin.hpp> -#ifdef WIN32 -static DWORD WINAPI thread_run(void *data) -#else -static void* thread_run(void *data) -#endif/*WIN32*/ -{ - DEBUG(thread, "Thread run\n"); - Thread *t = (Thread*)data; - t->thread_main(); - return 0; -} - Thread::Thread() {} @@ -66,19 +54,15 @@ void Thread::wait_stop() #endif/*WIN32*/ } -#ifdef TEST_THREAD -//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_THREAD*/ +#ifdef WIN32 +DWORD WINAPI +#else +void* +#endif/*WIN32*/ +Thread::thread_run(void *data) +{ + DEBUG(thread, "Thread run\n"); + Thread *t = (Thread*)data; + t->thread_main(); + return 0; +} diff --git a/src/thread.h b/src/thread.h index 837222a..33435e6 100644 --- a/src/thread.h +++ b/src/thread.h @@ -24,10 +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_THREAD_H__ -#define __DRUMGIZMO_THREAD_H__ +#pragma once #ifdef WIN32 +#define WIN32_LEAN_AND_MEAN #include <windows.h> #else #include <pthread.h> @@ -41,14 +41,16 @@ public: void run(); void wait_stop(); +protected: virtual void thread_main() = 0; private: #ifdef WIN32 - HANDLE tid; + HANDLE tid{nullptr}; + static DWORD WINAPI #else - pthread_t tid; + pthread_t tid{0}; + static void* #endif/*WIN32*/ + thread_run(void *data); }; - -#endif/*__DRUMGIZMO_THREAD_H__*/ diff --git a/test/Makefile.am b/test/Makefile.am index 1f605e5..8a746a6 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,11 +1,21 @@ # Rules for the test code (use `make check` to execute) include $(top_srcdir)/src/Makefile.am.drumgizmo -TESTS = engine gui resampler lv2 configfile audiocache audiocachefile \ - audiocacheidmanager audiocacheeventhandler +TESTS = resource engine gui resampler lv2 configfile audiocache \ + audiocachefile audiocacheidmanager audiocacheeventhandler check_PROGRAMS = $(TESTS) +resource_CXXFLAGS = -DOUTPUT=\"resource\" $(CPPUNIT_CFLAGS) \ + -I$(top_srcdir)/hugin +resource_LDFLAGS = $(CPPUNIT_LIBS) +resource_SOURCES = \ + $(top_srcdir)/plugingui/resource.cc \ + $(top_srcdir)/plugingui/resource_data.cc \ + $(top_srcdir)/hugin/hugin.c \ + test.cc \ + resource_test.cc + audiocache_CXXFLAGS = -DOUTPUT=\"audiocache\" $(CPPUNIT_CFLAGS) \ -I$(top_srcdir)/src -I$(top_srcdir)/include \ -I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) @@ -106,3 +116,6 @@ configfile_SOURCES = \ $(top_srcdir)/hugin/hugin.c \ test.cc \ configtest.cc + +EXTRA_DIST = \ + lv2_test_host.h diff --git a/test/lv2.cc b/test/lv2.cc index bfd2ce5..32d896c 100644 --- a/test/lv2.cc +++ b/test/lv2.cc @@ -47,7 +47,7 @@ */ class test_lv2 : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(test_lv2); + CPPUNIT_TEST_SUITE(test_lv2); CPPUNIT_TEST(open_and_verify); CPPUNIT_TEST(run_no_ports_connected); CPPUNIT_TEST(run_no_output_ports_connected); @@ -58,274 +58,282 @@ public: void setUp() {} void tearDown() {} - void open_and_verify() - { - int res; - - LV2TestHost h(LV2_PATH); - - res = h.open(DG_URI); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.verify(); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.close(); - CPPUNIT_ASSERT_EQUAL(0, res); - } - - void run_no_ports_connected() - { - int res; - - LV2TestHost h(LV2_PATH); - - res = h.open(DG_URI); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.verify(); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.createInstance(); - CPPUNIT_ASSERT_EQUAL(0, res); - - const char config_fmt[] = - "<config>\n" - " <value name=\"drumkitfile\">%s</value>\n" - " <value name=\"midimapfile\">%s</value>\n" - " <value name=\"enable_velocity_modifier\">%s</value>\n" - " <value name=\"velocity_modifier_falloff\">%f</value>\n" - " <value name=\"velocity_modifier_weight\">%f</value>\n" - " <value name=\"enable_velocity_randomiser\">%s</value>\n" - " <value name=\"velocity_randomiser_weight\">%f</value>\n" - " <value name=\"enable_resampling\">%s</value>\n" - "</config>"; - - const char drumkitfile[] = "kit/kit1.xml"; - const char midimapfile[] = "kit/midimap.xml"; - bool enable_velocity_modifier = true; - float velocity_modifier_falloff = 0.5; - float velocity_modifier_weight = 0.25; - bool enable_velocity_randomiser = false; - float velocity_randomiser_weight = 0.1; - bool enable_resampling = false; - - char config[sizeof(config_fmt) * 2]; - sprintf(config, config_fmt, - drumkitfile, - midimapfile, - enable_velocity_modifier?"true":"false", - velocity_modifier_falloff, - velocity_modifier_weight, - enable_velocity_randomiser?"true":"false", - velocity_randomiser_weight, - enable_resampling?"true":"false" - ); - - res = h.loadConfig(config, strlen(config)); - CPPUNIT_ASSERT_EQUAL(0, res); - - // run for 1 samples to trigger kit loading - res = h.run(1); - CPPUNIT_ASSERT_EQUAL(0, res); - sleep(1); // wait for kit to get loaded (async), - - res = h.run(100); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.destroyInstance(); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.close(); - CPPUNIT_ASSERT_EQUAL(0, res); - } - - void run_no_output_ports_connected() - { - int res; - - LV2TestHost h(LV2_PATH); - - res = h.open(DG_URI); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.verify(); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.createInstance(); - CPPUNIT_ASSERT_EQUAL(0, res); - - const char config_fmt[] = - "<config>\n" - " <value name=\"drumkitfile\">%s</value>\n" - " <value name=\"midimapfile\">%s</value>\n" - " <value name=\"enable_velocity_modifier\">%s</value>\n" - " <value name=\"velocity_modifier_falloff\">%f</value>\n" - " <value name=\"velocity_modifier_weight\">%f</value>\n" - " <value name=\"enable_velocity_randomiser\">%s</value>\n" - " <value name=\"velocity_randomiser_weight\">%f</value>\n" - " <value name=\"enable_resampling\">%s</value>\n" - "</config>"; - - const char drumkitfile[] = "kit/kit1.xml"; - const char midimapfile[] = "kit/midimap.xml"; - bool enable_velocity_modifier = true; - float velocity_modifier_falloff = 0.5; - float velocity_modifier_weight = 0.25; - bool enable_velocity_randomiser = false; - float velocity_randomiser_weight = 0.1; - bool enable_resampling = false; - - char config[sizeof(config_fmt) * 2]; - sprintf(config, config_fmt, - drumkitfile, - midimapfile, - enable_velocity_modifier?"true":"false", - velocity_modifier_falloff, - velocity_modifier_weight, - enable_velocity_randomiser?"true":"false", - velocity_randomiser_weight, - enable_resampling?"true":"false" - ); - - res = h.loadConfig(config, strlen(config)); - CPPUNIT_ASSERT_EQUAL(0, res); - - // Port buffers: - char sequence_buffer[4096]; - - LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); - res = h.connectPort(0, seq.data()); - CPPUNIT_ASSERT_EQUAL(0, res); - - // run for 1 samples to trigger kit loading - res = h.run(1); - CPPUNIT_ASSERT_EQUAL(0, res); - sleep(1); // wait for kit to get loaded (async), - - seq.addMidiNote(5, 1, 127); - res = h.run(100); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.destroyInstance(); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.close(); - CPPUNIT_ASSERT_EQUAL(0, res); - } - - void test1() - { - int res; - - LV2TestHost h(LV2_PATH); - - res = h.open(DG_URI); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.verify(); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.createInstance(); - CPPUNIT_ASSERT_EQUAL(0, res); - - const char config_fmt[] = - "<config>\n" - " <value name=\"drumkitfile\">%s</value>\n" - " <value name=\"midimapfile\">%s</value>\n" - " <value name=\"enable_velocity_modifier\">%s</value>\n" - " <value name=\"velocity_modifier_falloff\">%f</value>\n" - " <value name=\"velocity_modifier_weight\">%f</value>\n" - " <value name=\"enable_velocity_randomiser\">%s</value>\n" - " <value name=\"velocity_randomiser_weight\">%f</value>\n" - " <value name=\"enable_resampling\">%s</value>\n" - "</config>"; - - const char drumkitfile[] = "kit/kit1.xml"; - const char midimapfile[] = "kit/midimap.xml"; - bool enable_velocity_modifier = true; - float velocity_modifier_falloff = 0.5; - float velocity_modifier_weight = 0.25; - bool enable_velocity_randomiser = false; - float velocity_randomiser_weight = 0.1; - bool enable_resampling = false; - - char config[sizeof(config_fmt) * 2]; - sprintf(config, config_fmt, - drumkitfile, - midimapfile, - enable_velocity_modifier?"true":"false", - velocity_modifier_falloff, - velocity_modifier_weight, - enable_velocity_randomiser?"true":"false", - velocity_randomiser_weight, - enable_resampling?"true":"false" - ); - - res = h.loadConfig(config, strlen(config)); - CPPUNIT_ASSERT_EQUAL(0, res); - - // Port buffers: - char sequence_buffer[4096]; - float pcm_buffer[16][10]; - - LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); - res = h.connectPort(0, seq.data()); - CPPUNIT_ASSERT_EQUAL(0, res); - - for(int i = 1; i <= 16; i++) { - memset(pcm_buffer, 1, sizeof(pcm_buffer)); - res += h.connectPort(i, pcm_buffer[i-1]); - } - CPPUNIT_ASSERT_EQUAL(0, res); - - // run for 1 samples to trigger kit loading - res = h.run(1); - CPPUNIT_ASSERT_EQUAL(0, res); - sleep(1); // wait for kit to get loaded (async), - - /* - seq.addMidiNote(5, 1, 127); - for(int i = 0; i < 10; i++) { - res = h.run(10); - CPPUNIT_ASSERT_EQUAL(0, res); - - printf("Iteration:\n"); - for(int k = 0; k < 4; k++) { - printf("#%d ", k); - for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); - printf("\n"); - } - printf("\n"); - - seq.clear(); - } - */ - - seq.addMidiNote(5, 1, 127); - res = h.run(10); - CPPUNIT_ASSERT_EQUAL(0, res); - - union { - float f; - unsigned int u; - } comp_val; - - comp_val.u = 1040744448; - - for(int k = 0; k < 4; k++) { - for(int j = 0; j < 10; j++) { - CPPUNIT_ASSERT(pcm_buffer[k][j] == ((j==4)?comp_val.f:0)); - } - } - seq.clear(); - - res = h.destroyInstance(); - CPPUNIT_ASSERT_EQUAL(0, res); - - res = h.close(); - CPPUNIT_ASSERT_EQUAL(0, res); - } + void open_and_verify() + { + int res; + + LV2TestHost h(LV2_PATH); + + res = h.open(DG_URI); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.verify(); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.close(); + CPPUNIT_ASSERT_EQUAL(0, res); + } + + void run_no_ports_connected() + { + int res; + + LV2TestHost h(LV2_PATH); + + res = h.open(DG_URI); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.verify(); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.createInstance(); + CPPUNIT_ASSERT_EQUAL(0, res); + + const char config_fmt[] = + "<config>\n" + " <value name=\"drumkitfile\">%s</value>\n" + " <value name=\"midimapfile\">%s</value>\n" + " <value name=\"enable_velocity_modifier\">%s</value>\n" + " <value name=\"velocity_modifier_falloff\">%f</value>\n" + " <value name=\"velocity_modifier_weight\">%f</value>\n" + " <value name=\"enable_velocity_randomiser\">%s</value>\n" + " <value name=\"velocity_randomiser_weight\">%f</value>\n" + " <value name=\"enable_resampling\">%s</value>\n" + "</config>"; + + const char drumkitfile[] = "kit/kit1.xml"; + const char midimapfile[] = "kit/midimap.xml"; + bool enable_velocity_modifier = true; + float velocity_modifier_falloff = 0.5; + float velocity_modifier_weight = 0.25; + bool enable_velocity_randomiser = false; + float velocity_randomiser_weight = 0.1; + bool enable_resampling = false; + + char config[sizeof(config_fmt) * 2]; + sprintf(config, config_fmt, + drumkitfile, + midimapfile, + enable_velocity_modifier?"true":"false", + velocity_modifier_falloff, + velocity_modifier_weight, + enable_velocity_randomiser?"true":"false", + velocity_randomiser_weight, + enable_resampling?"true":"false"); + + res = h.loadConfig(config, strlen(config)); + CPPUNIT_ASSERT_EQUAL(0, res); + + // run for 1 samples to trigger kit loading + res = h.run(1); + CPPUNIT_ASSERT_EQUAL(0, res); + sleep(1); // wait for kit to get loaded (async), + + res = h.run(100); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.destroyInstance(); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.close(); + CPPUNIT_ASSERT_EQUAL(0, res); + } + + void run_no_output_ports_connected() + { + int res; + + LV2TestHost h(LV2_PATH); + + res = h.open(DG_URI); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.verify(); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.createInstance(); + CPPUNIT_ASSERT_EQUAL(0, res); + + const char config_fmt[] = + "<config>\n" + " <value name=\"drumkitfile\">%s</value>\n" + " <value name=\"midimapfile\">%s</value>\n" + " <value name=\"enable_velocity_modifier\">%s</value>\n" + " <value name=\"velocity_modifier_falloff\">%f</value>\n" + " <value name=\"velocity_modifier_weight\">%f</value>\n" + " <value name=\"enable_velocity_randomiser\">%s</value>\n" + " <value name=\"velocity_randomiser_weight\">%f</value>\n" + " <value name=\"enable_resampling\">%s</value>\n" + "</config>"; + + const char drumkitfile[] = "kit/kit1.xml"; + const char midimapfile[] = "kit/midimap.xml"; + bool enable_velocity_modifier = true; + float velocity_modifier_falloff = 0.5; + float velocity_modifier_weight = 0.25; + bool enable_velocity_randomiser = false; + float velocity_randomiser_weight = 0.1; + bool enable_resampling = false; + + char config[sizeof(config_fmt) * 2]; + sprintf(config, config_fmt, + drumkitfile, + midimapfile, + enable_velocity_modifier?"true":"false", + velocity_modifier_falloff, + velocity_modifier_weight, + enable_velocity_randomiser?"true":"false", + velocity_randomiser_weight, + enable_resampling?"true":"false"); + + res = h.loadConfig(config, strlen(config)); + CPPUNIT_ASSERT_EQUAL(0, res); + + // Port buffers: + char sequence_buffer[4096]; + + LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); + res = h.connectPort(0, seq.data()); + CPPUNIT_ASSERT_EQUAL(0, res); + + // run for 1 samples to trigger kit loading + res = h.run(1); + CPPUNIT_ASSERT_EQUAL(0, res); + sleep(1); // wait for kit to get loaded (async), + + seq.addMidiNote(5, 1, 127); + res = h.run(100); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.destroyInstance(); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.close(); + CPPUNIT_ASSERT_EQUAL(0, res); + } + + void test1() + { + int res; + + LV2TestHost h(LV2_PATH); + + res = h.open(DG_URI); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.verify(); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.createInstance(); + CPPUNIT_ASSERT_EQUAL(0, res); + + const char config_fmt[] = + "<config>\n" + " <value name=\"drumkitfile\">%s</value>\n" + " <value name=\"midimapfile\">%s</value>\n" + " <value name=\"enable_velocity_modifier\">%s</value>\n" + " <value name=\"velocity_modifier_falloff\">%f</value>\n" + " <value name=\"velocity_modifier_weight\">%f</value>\n" + " <value name=\"enable_velocity_randomiser\">%s</value>\n" + " <value name=\"velocity_randomiser_weight\">%f</value>\n" + " <value name=\"enable_resampling\">%s</value>\n" + "</config>"; + + const char drumkitfile[] = "kit/kit1.xml"; + const char midimapfile[] = "kit/midimap.xml"; + bool enable_velocity_modifier = true; + float velocity_modifier_falloff = 0.5; + float velocity_modifier_weight = 0.25; + bool enable_velocity_randomiser = false; + float velocity_randomiser_weight = 0.1; + bool enable_resampling = false; + + char config[sizeof(config_fmt) * 2]; + sprintf(config, config_fmt, + drumkitfile, + midimapfile, + enable_velocity_modifier?"true":"false", + velocity_modifier_falloff, + velocity_modifier_weight, + enable_velocity_randomiser?"true":"false", + velocity_randomiser_weight, + enable_resampling?"true":"false"); + + res = h.loadConfig(config, strlen(config)); + CPPUNIT_ASSERT_EQUAL(0, res); + + // Port buffers: + char sequence_buffer[4096]; + float pcm_buffer[16][10]; + + LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); + res = h.connectPort(0, seq.data()); + CPPUNIT_ASSERT_EQUAL(0, res); + + for(int i = 1; i <= 16; i++) { + memset(pcm_buffer, 1, sizeof(pcm_buffer)); + res += h.connectPort(i, pcm_buffer[i-1]); + } + CPPUNIT_ASSERT_EQUAL(0, res); + + // run for 1 samples to trigger kit loading + res = h.run(1); + CPPUNIT_ASSERT_EQUAL(0, res); + sleep(1); // wait for kit to get loaded (async), + + seq.addMidiNote(5, 1, 127); + for(int i = 0; i < 10; i++) { + res = h.run(10); + CPPUNIT_ASSERT_EQUAL(0, res); + + /* + printf("Iteration:\n"); + for(int k = 0; k < 4; k++) { + printf("#%d ", k); + for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); + printf("\n"); + } + printf("\n"); + */ + + seq.clear(); + } + + + seq.addMidiNote(5, 1, 127); + res = h.run(10); + CPPUNIT_ASSERT_EQUAL(0, res); + + /* + printf("Iteration:\n"); + for(int k = 0; k < 4; k++) { + printf("#%d ", k); + for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); + printf("\n"); + } + printf("\n"); + */ + + union { + float f; + unsigned int u; + } comp_val; + + comp_val.u = 1040744448; // floating point value 0.133301.... + + for(int k = 0; k < 4; k++) { + for(int j = 0; j < 10; j++) { + CPPUNIT_ASSERT_EQUAL(((j==0)?comp_val.f:0), pcm_buffer[k][j]); + } + } + seq.clear(); + + res = h.destroyInstance(); + CPPUNIT_ASSERT_EQUAL(0, res); + + res = h.close(); + CPPUNIT_ASSERT_EQUAL(0, res); + } }; // Registers the fixture into the 'registry' diff --git a/test/resource_test.cc b/test/resource_test.cc new file mode 100644 index 0000000..7fc632a --- /dev/null +++ b/test/resource_test.cc @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * resource_test.cc + * + * Fri Nov 13 18:50:52 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include "../plugingui/resource.h" + +class ResourceTester : public GUI::Resource { +public: + ResourceTester(const std::string& name) + : Resource(name) + {} + + bool probeIsInternal() + { + return isInternal; + } +}; + +class ResourceTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ResourceTest); + CPPUNIT_TEST(externalReadTest); + CPPUNIT_TEST(internalReadTest); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp() {} + void tearDown() {} + + void externalReadTest() + { + ResourceTester rc("kit/0000.wav"); + CPPUNIT_ASSERT(!rc.probeIsInternal()); + CPPUNIT_ASSERT(rc.valid()); + CPPUNIT_ASSERT_EQUAL((size_t)46, rc.size()); + } + + void internalReadTest() + { + ResourceTester rc(":bg.png"); + CPPUNIT_ASSERT(rc.probeIsInternal()); + CPPUNIT_ASSERT(rc.valid()); + CPPUNIT_ASSERT_EQUAL((size_t)1123, rc.size()); + } +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(ResourceTest); diff --git a/test/run_test.sh b/test/run_test.sh new file mode 100755 index 0000000..51b99c4 --- /dev/null +++ b/test/run_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# This is a script to faciliate running single tests. +# +# Usage: ./run_test.sh <test_1> <test_2> ... <test_n> +# If no test string is passed then all tests are run. + +test_dir=$(dirname $0) +cd $test_dir + +if [[ $# == 0 ]] +then + echo "======================" + echo "All tests are now run." + echo "======================" + make check +else + for TST in "$@" + do + echo "=========================" + echo "The $TST test is now run." + echo "=========================" + rm -f $TST*.o; make $TST && (./$TST; RES=$?; echo; echo "Result: $RES"; cat result_$TST.xml) + done +fi diff --git a/tools/add_file b/tools/add_file index d63b4ab..1f2b545 100755 --- a/tools/add_file +++ b/tools/add_file @@ -2,28 +2,30 @@ PROJECT="DrumGizmo" function allfile() { - echo "/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */" > $1; - echo "/***************************************************************************" >> $1; - echo " * $1" >> $1; - echo " *" >> $1 ; - echo " * `date`" >> $1; - echo -n " * Copyright " >> $1 - echo -n `date +%Y | xargs` >> $1 - if [ "$USER" == "nemo" ]; + if [ "$USER" == "nemo" ] + then + NAME="Jonas Suhr Christensen"; EMAIL="jsc@umbraculum.org" + fi + if [ "$USER" == "deva" ] then - echo " Jonas Suhr Christensen" >> $1; - echo " * jsc@umbraculum.org" >> $1; + NAME="Bent Bisballe Nyeng"; EMAIL="deva@aasimon.org" fi - if [ "$USER" == "deva" ]; + if [ "$USER" == "senator" ] then - echo " Bent Bisballe Nyeng" >> $1; - echo " * deva@aasimon.org" >> $1; + NAME="Lars Bisballe Jensen"; EMAIL="elsenator@gmail.com" fi - if [ "$USER" == "senator" ]; + if [ "$USER" == "chaot" ] then - echo " Lars Bisballe Jensen" >> $1; - echo " * elsenator@gmail.com" >> $1; + NAME="André Nusser"; EMAIL="andre.nusser@googlemail.com" fi + + echo "/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */" > $1; + echo "/***************************************************************************" >> $1; + echo " * $1" >> $1; + echo " *" >> $1 ; + echo " * `date`" >> $1; + echo " * Copyright "`date +%Y | xargs`" $NAME" >> $1; + echo " * $EMAIL" >> $1; echo " ****************************************************************************/" >> $1; echo "" >> $1; echo "/*" >> $1; @@ -60,9 +62,7 @@ function hfile() { allfile $1; local hn=`echo $1 | tr 'a-z.' 'A-Z_'` local pr=`echo $PROJECT | tr 'a-z.' 'A-Z_'` - echo "#ifndef __${pr}_${hn}__" >> $1; - echo "#define __${pr}_${hn}__" >> $1; - echo "#endif/*__${pr}_${hn}__*/" >> $1; + echo "#pragma once" >> $1; } if [ "$#" = "1" ]; then diff --git a/vst/Makefile.am b/vst/Makefile.am index 7bb7214..d6c5c9e 100644 --- a/vst/Makefile.am +++ b/vst/Makefile.am @@ -40,7 +40,7 @@ libdg_la_CXXFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/plugingui \ -DUSE_THREAD $(SAMPLERATE_CFLAGS) nodist_libdrumgizmo_vst_la_SOURCES = \ - $(VST_SOURCES) + $(VST_SOURCES) libdrumgizmo_vst_la_SOURCES = \ drumgizmo_vst.cc \ @@ -50,5 +50,4 @@ libdrumgizmo_vst_la_SOURCES = \ libdrumgizmo_vst_la_LDFLAGS = -no-undefined -shared libdrumgizmo_vst_la_LIBADD = libdg.la libdrumgizmo_vst_la_CXXFLAGS = -w $(VST_CPPFLAGS) \ - -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_srcdir)/plugingui - + -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_srcdir)/plugingui
\ No newline at end of file diff --git a/vst/Makefile.mingw32.in b/vst/Makefile.mingw32.in index 804c97c..5a087b7 100644 --- a/vst/Makefile.mingw32.in +++ b/vst/Makefile.mingw32.in @@ -38,7 +38,7 @@ DG_SRC = \ DG_CFLAGS = -I.. -I../include -I../src -DSSE -msse -msse2 -DDISABLE_HUGIN GUI_SRC = \ - @top_srcdir@/plugingui/nativewindow_x11.cc \ + @top_srcdir@/plugingui/dgwindow.cc \ @top_srcdir@/plugingui/nativewindow_win32.cc \ @top_srcdir@/plugingui/plugingui.cc \ @top_srcdir@/plugingui/pluginconfig.cc \ @@ -53,11 +53,13 @@ GUI_SRC = \ @top_srcdir@/plugingui/pixelbuffer.cc \ @top_srcdir@/plugingui/lineedit.cc \ @top_srcdir@/plugingui/led.cc \ + @top_srcdir@/plugingui/layout.cc \ @top_srcdir@/plugingui/cacheaudiofile.cc \ @top_srcdir@/plugingui/cachemanager.cc \ @top_srcdir@/plugingui/checkbox.cc \ @top_srcdir@/plugingui/slider.cc \ @top_srcdir@/plugingui/scrollbar.cc \ + @top_srcdir@/plugingui/textedit.cc \ @top_srcdir@/plugingui/listbox.cc \ @top_srcdir@/plugingui/listboxthin.cc \ @top_srcdir@/plugingui/listboxbasic.cc \ @@ -88,13 +90,10 @@ DBG_CFLAGS=-I../hugin -DWITH_HUG_SYSLOG -DWITH_HUG_MUTEX -DDISABLE_HUGIN EXPAT_CFLAGS=@EXPAT_CFLAGS@ EXPAT_LIBS=@EXPAT_LIBS@ - + SNDFILE_CFLAGS=@SNDFILE_CFLAGS@ SNDFILE_LIBS=@SNDFILE_LIBS@ -ZLIB_CFLAGS=@ZLIB_CFLAGS@ -ZLIB_LIBS=@ZLIB_LIBS@ - SRC_CFLAGS=@SAMPLERATE_CFLAGS@ SRC_LIBS=@SAMPLERATE_LIBS@ @@ -114,7 +113,7 @@ SRC = \ # #C_SOURCES=$(DBG_SRC) #CXX_SOURCES=$(GUI_SRC) $(DG_SRC) -#CPP_SOURCES=$(VST_SRC) +#CPP_SOURCES=$(VST_SRC) # #OBJECTS=$(CXX_SOURCES:.cc=.o) $(CPP_SOURCES:.cpp=.o) $(C_SOURCES:.c=.o) #all: $(CXX_SOURCES) $(CPP_SOURCES) $(C_SOURCES) drumgizmo_vst.dll @@ -136,11 +135,11 @@ SRC = \ # ######################## - + all: gcc $(DBG_CFLAGS) @top_srcdir@/hugin/hugin.c -c gcc $(DBG_CFLAGS) @top_srcdir@/hugin/hugin_syslog.c -c - g++ -std=c++11 -static -static-libgcc -O2 -g -Wall $(DBG_CFLAGS) $(DG_CFLAGS) $(DG_LIBS) $(VST_CFLAGS) hugin.o hugin_syslog.o $(DG_SRC) $(VST_SRC) ${SRC} ${GUI_SRC} ${GUI_CFLAGS} $(GUI_LIBS) $(EXPAT_CFLAGS) $(ZLIB_CFLAGS) $(SRC_CFLAGS) $(ZITA_CXXFLAGS) $(EXPAT_LIBS) $(ZLIB_LIBS) $(SNDFILE_CFLAGS) $(SNDFILE_LIBS) $(SRC_LIBS) $(ZITA_LIBS) -shared -o drumgizmo_vst.dll -Wl,--out-implib,libdrumgizmo_vst.a - + g++ -std=c++11 -static -static-libgcc -O2 -g -Wall $(DBG_CFLAGS) $(DG_CFLAGS) $(DG_LIBS) $(VST_CFLAGS) hugin.o hugin_syslog.o $(DG_SRC) $(VST_SRC) ${SRC} ${GUI_SRC} ${GUI_CFLAGS} $(GUI_LIBS) $(EXPAT_CFLAGS) $(SRC_CFLAGS) $(ZITA_CXXFLAGS) $(EXPAT_LIBS) $(SNDFILE_CFLAGS) $(SNDFILE_LIBS) $(SRC_LIBS) $(ZITA_LIBS) -shared -o drumgizmo_vst.dll -Wl,--out-implib,libdrumgizmo_vst.a + clean: del -f drumgizmo_vst.dll libdrumgizmo_vst.a diff --git a/vst/drumgizmo_vst.cc b/vst/drumgizmo_vst.cc index 109f8b9..70d0847 100644 --- a/vst/drumgizmo_vst.cc +++ b/vst/drumgizmo_vst.cc @@ -49,7 +49,7 @@ bool DGEditor::open(void* ptr) DEBUG(dgeditor, "open GUI (new PluginGUI)\n"); if(plugingui) delete plugingui; - plugingui = new PluginGUI(); + plugingui = new GUI::PluginGUI(); // plugingui->setChangeMidimapCallback(midimapHandler, dgeff); // plugingui->show(); diff --git a/vst/drumgizmo_vst.h b/vst/drumgizmo_vst.h index 4497c48..b15122c 100644 --- a/vst/drumgizmo_vst.h +++ b/vst/drumgizmo_vst.h @@ -112,7 +112,7 @@ public: private: DrumGizmoVst* dgeff; - PluginGUI *plugingui; + GUI::PluginGUI *plugingui; DrumGizmo *drumgizmo; }; |