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