1 
2 #ifndef OPENAV_AVTK_UI_HXX
3 #define OPENAV_AVTK_UI_HXX
4 
5 // libs AVTK needs
6 #include "pugl/pugl.h"
7 #include <cairo/cairo.h>
8 
9 // general C++ includes
10 #include <list>
11 #include <stack>
12 #include <vector>
13 #include <stdio.h>
14 #include <unistd.h>
15 
16 // the AVTK UI is a group
17 #include "group.hxx"
18 
19 // lv2 ui include
20 #include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
21 
22 namespace Avtk
23 {
24 
25 class Theme;
26 class Widget;
27 class Tester;
28 
29 
30 class UI : public Avtk::Group
31 {
32 public:
33 	UI( int w, int h, PuglNativeWindow parent = 0, const char* windowName = "Avtk" );
34 	virtual ~UI();
35 
36 	/// tells the UI a widget has captured a mouse-down event, and
37 	/// wants to be notified of mouse movement events
wantsMotionUpdates(Avtk::Widget * w,bool notifyOfMotion)38 	void wantsMotionUpdates( Avtk::Widget* w, bool notifyOfMotion )
39 	{
40 		if( notifyOfMotion )
41 			motionUpdateWidget = w;
42 		else
43 			motionUpdateWidget = 0;
44 	}
45 
46 	/// overriden so we can set motion widget etc to null on removal.
47 	virtual void remove ( Widget* child );
48 
49 	/// Initiate a drag-and-drop action, with the widget as the "origin widget",
50 	/// and the data is copied to the UI instance.
51 	void dragDropInit( Avtk::Widget* origin, size_t size, void* data );
52 
53 	/// checks if the current drag-drop data-type is dropable on the "to" Widget
54 	bool dragDropVerify( Avtk::Widget* target );
55 
56 	/// performs the drag-drop action
57 	void dragDropComplete( Avtk::Widget* target );
58 
59 	/// Widget value callback: when a widget is added to the UI, its value
60 	/// callback is set to this function: it can be set to a custom function if
61 	/// preferred.
62 	///
63 	/// If the Widget* returned from new Widget() is stored, it can be compared
64 	/// against @param widget, which allows executing code based which Widget
65 	/// caused the event.
66 	virtual void widgetValueCB( Avtk::Widget* widget) = 0;
67 
68 	/// this function can be overridden by a UI if it wants to function as an
69 	/// LV2 plugin UI. The "index" represents the control number, as defined
70 	/// in the plugin TTL file. If the port is a control port, casting the
71 	/// void* buffer to float* gives the value of that control port.
lv2PortEvent(uint32_t index,uint32_t buffer_size,uint32_t format,const void * buffer)72 	virtual void lv2PortEvent(  uint32_t index,
73 	                            uint32_t buffer_size,
74 	                            uint32_t format,
75 	                            const void* buffer )
76 	{
77 		// stub implementation - not every UI will override this
78 	}
79 
80 	// Used by LV2 UI - allows writing control/Atom messages from derived UI
81 	LV2UI_Write_Function write_function;
82 	LV2UI_Controller     controller;
83 
84 	/// Static function for handling AVTK widget callbacks: is re-directed to
85 	/// instance-version above.
staticWidgetValueCB(Avtk::Widget * widget,void * userdata)86 	static void staticWidgetValueCB( Avtk::Widget* widget, void* userdata)
87 	{
88 		UI* ui = (UI*)userdata;
89 		ui->widgetValueCB( widget );
90 	}
91 
92 	/// draws the screen. Passing in will cause a partial redraw if possible
93 	/// on the current platform and rendering subsystem.
94 	void redraw();
95 	void redraw( Avtk::Widget* w );
96 
97 	/// when used as a UI plugin, created by a host, this function should be
98 	/// called repeatedly at ~30 fps to handle events and redraw if needed.
99 	int idle();
100 
101 	/// when UI is running standalone, call this function to run the UI. When
102 	/// the function returns, the main window has been closed.
103 	virtual int run();
104 
105 	/// Handle Only make the UI only pass events to one widget, until it is
106 	/// called with 0x0, then normal functionality resumes.
107 	void handleOnly( Widget* wid );
108 
109 	/// get the theme requested: the themes have ID's defined in theme file.
110 	/// calling this without a parameter returns the default theme.
111 	Theme* theme( int id = 0 );
112 
113 	/// call this to recieve the LV2 widget handle
getNativeHandle()114 	PuglNativeWindow getNativeHandle()
115 	{
116 		// returns the X11 handle, or Win32 surface, or Quartz surface
117 		return puglGetNativeWindow( view );
118 	}
119 
120 	/// sets the passed in Group* as the "parent" for any widgets created
121 	/// should only be called by Group widgets
122 	void pushParent( Avtk::Group* );
123 	void popParent();
parentStackTop()124 	Avtk::Group* parentStackTop()
125 	{
126 		return parentStack.top();
127 	}
128 
w()129 	int w()
130 	{
131 		return w_;
132 	}
h()133 	int h()
134 	{
135 		return h_;
136 	}
137 
138 protected:
139 	PuglView* view;
140 
141 	std::stack<Avtk::Group*> parentStack;
142 
143 	bool quit_;
144 	int w_, h_;
145 
146 #ifdef AVTK_TESTER
147 	/// for testing the UI, the Tester class can record and playback events.
148 	Tester* tester;
149 #endif
150 	/// The widget that should be handled modally: no other widgets are given
151 	/// the event
152 	Avtk::Widget* handleOnlyWidget;
153 
154 	/// the list of widgets currently instantiated, in order of being drawn.
155 	std::list<Avtk::Widget*> widgets;
156 
157 	/// A list of themes, loaded on startup, which widgets can request
158 	std::vector< Avtk::Theme* > themes;
159 
160 	/// pointers that are dynamically switched to represent a widget that could
161 	/// have a specific action performed with it in the future. These pointers
162 	/// *must* be checked for 0 before *any* use.
163 	Avtk::Widget* dragDropOrigin;
164 	Avtk::Widget* motionUpdateWidget;
165 
166 	bool          dragDropTargetVerified;
167 	Avtk::Widget* dragDropTargetVerifiedWidget;
168 
169 	size_t dragDropDataSize;
170 	char*  dragDropDataPtr;
171 
172 	void scroll( int x, int y, int dx, int dy );
173 	void display( cairo_t* cr );
174 	void motion(int x, int y);
175 	void reshape(int x, int y);
close()176 	void close()
177 	{
178 		quit_ = true;
179 	}
180 
181 #ifdef AVTK_TESTER
182 public: // make event() public when TESTER is on to allow injecting events
183 #endif
184 	/// the main event function: it handles all event input, and distritbutes it
185 	/// to the widgets. See handleOnly() for details on handling Dialogs
186 	void event( const PuglEvent* event );
187 #ifdef AVTK_TESTER
188 protected:
189 #endif
190 
191 	/// internalEvent handles events like ALT-F4, and ESC. Split from the main
192 	/// event function so dialog boxes etc can easily support handling these
193 	void internalEvent( const PuglEvent* event );
194 
195 	// Static Functions for handling PUGL events below
onMotion(PuglView * view,int x,int y)196 	static void onMotion(PuglView* view, int x, int y)
197 	{
198 		UI* ui = (UI*)puglGetHandle( view );
199 		ui->motion( x, y );
200 	}
onClose(PuglView * view)201 	static void onClose(PuglView* view)
202 	{
203 		UI* ui = (UI*)puglGetHandle( view );
204 		ui->close();
205 	}
onEvent(PuglView * view,const PuglEvent * event)206 	static void onEvent(PuglView* view, const PuglEvent* event)
207 	{
208 		UI* ui = (UI*)puglGetHandle( view );
209 		ui->event( event );
210 	}
onDisplay(PuglView * view)211 	static void onDisplay(PuglView* view)
212 	{
213 		UI* ui = (UI*)puglGetHandle( view );
214 		cairo_t* cr = (cairo_t*)puglGetContext(view);
215 		ui->display( cr );
216 	}
onScroll(PuglView * view,int x,int y,float dx,float dy)217 	static void onScroll(PuglView* view, int x, int y, float dx, float dy)
218 	{
219 		UI* ui = (UI*)puglGetHandle( view );
220 		ui->scroll( x, y, dx, dy );
221 	}
onReshape(PuglView * view,int w,int h)222 	static void onReshape(PuglView* view, int w, int h)
223 	{
224 		UI* ui = (UI*)puglGetHandle( view );
225 		ui->reshape( w, h );
226 	}
227 };
228 
229 }; // namespace Avtk
230 
231 #endif // OPENAV_AVTK_UI_HXX
232