| 1 | #include "lwlib-Xol.h" |
| 2 | #include <X11/StringDefs.h> |
| 3 | #include <X11/IntrinsicP.h> |
| 4 | #include <X11/CompositeP.h> |
| 5 | #include <X11/Shell.h> |
| 6 | #include <Xol/Menu.h> |
| 7 | #include <Xol/OpenLook.h> |
| 8 | #include <Xol/MenuButton.h> |
| 9 | #include <Xol/OblongButt.h> |
| 10 | #include <Xol/ControlAre.h> |
| 11 | #include <Xol/Stub.h> |
| 12 | #include <Xol/StaticText.h> |
| 13 | |
| 14 | \f/* forward declarations */ |
| 15 | static void |
| 16 | update_menu_widget (widget_instance* instance, Widget widget, |
| 17 | widget_value* val); |
| 18 | |
| 19 | \f/* Menu callbacks */ |
| 20 | static void |
| 21 | pre_hook (Widget w, caddr_t client_data, caddr_t call_data) |
| 22 | { |
| 23 | OlVirtualEvent ve = (OlVirtualEvent)call_data; |
| 24 | widget_instance* instance = (widget_instance*)client_data; |
| 25 | |
| 26 | if (w->core.being_destroyed) |
| 27 | return; |
| 28 | |
| 29 | if (XtParent (w) == instance->widget) |
| 30 | { |
| 31 | if (ve->xevent->type == ButtonPress && instance->info->pre_activate_cb) |
| 32 | instance->info->pre_activate_cb (instance->widget, instance->info->id, |
| 33 | NULL); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | static void |
| 38 | post_hook (Widget w, caddr_t client_data, caddr_t call_data) |
| 39 | { |
| 40 | widget_instance* instance = (widget_instance*)client_data; |
| 41 | |
| 42 | if (w->core.being_destroyed) |
| 43 | return; |
| 44 | |
| 45 | if (instance->info->post_activate_cb) |
| 46 | instance->info->post_activate_cb (w, instance->info->id, NULL); |
| 47 | } |
| 48 | |
| 49 | static void |
| 50 | pick_hook (Widget w, caddr_t client_data, caddr_t call_data) |
| 51 | { |
| 52 | widget_instance* instance = 0; |
| 53 | widget_value* val = (widget_value*)client_data; |
| 54 | |
| 55 | if (w->core.being_destroyed) |
| 56 | return; |
| 57 | |
| 58 | XtVaGetValues (w, XtNuserData, &instance, 0); |
| 59 | |
| 60 | if (!instance) |
| 61 | return; |
| 62 | |
| 63 | if (instance->info->selection_cb && val && val->enabled |
| 64 | && !val->contents) |
| 65 | instance->info->selection_cb (w, instance->info->id, val->call_data); |
| 66 | } |
| 67 | |
| 68 | \f/* creation functions */ |
| 69 | static Widget |
| 70 | xol_create_menubar (widget_instance* instance) |
| 71 | { |
| 72 | Widget widget = |
| 73 | XtVaCreateWidget (instance->info->name, controlAreaWidgetClass, |
| 74 | instance->parent, 0); |
| 75 | return widget; |
| 76 | } |
| 77 | |
| 78 | static Widget |
| 79 | xol_create_popup_menu (widget_instance* instance) |
| 80 | { |
| 81 | Widget popup_shell = |
| 82 | XtCreatePopupShell (instance->info->name, menuShellWidgetClass, |
| 83 | instance->parent, NULL, 0); |
| 84 | return popup_shell; |
| 85 | } |
| 86 | |
| 87 | widget_creation_entry |
| 88 | xol_creation_table [] = |
| 89 | { |
| 90 | {"menubar", xol_create_menubar}, |
| 91 | {"popup", xol_create_popup_menu}, |
| 92 | {NULL, NULL} |
| 93 | }; |
| 94 | |
| 95 | Widget |
| 96 | xol_create_dialog (widget_instance* instance) |
| 97 | { |
| 98 | return NULL; |
| 99 | } |
| 100 | |
| 101 | Boolean |
| 102 | lw_olit_widget_p (Widget widget) |
| 103 | { |
| 104 | return True; |
| 105 | } |
| 106 | |
| 107 | \f/* update functions */ |
| 108 | static void |
| 109 | destroy_all_children (Widget widget) |
| 110 | { |
| 111 | Widget* children; |
| 112 | unsigned int number; |
| 113 | int i; |
| 114 | |
| 115 | children = (Widget *) XtCompositeChildren (widget, &number); |
| 116 | if (children) |
| 117 | { |
| 118 | /* Unmanage all children and destroy them. They will only be |
| 119 | * really destroyed when we get out of DispatchEvent. */ |
| 120 | for (i = 0; i < number; i++) |
| 121 | { |
| 122 | Widget child = children [i]; |
| 123 | if (!child->core.being_destroyed) |
| 124 | { |
| 125 | XtUnmanageChild (child); |
| 126 | XtDestroyWidget (child); |
| 127 | } |
| 128 | } |
| 129 | XtFree (children); |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | static Boolean |
| 134 | all_dashes_p (char* s) |
| 135 | { |
| 136 | char* t; |
| 137 | for (t = s; *t; t++) |
| 138 | if (*t != '-') |
| 139 | return False; |
| 140 | return True; |
| 141 | } |
| 142 | |
| 143 | static void |
| 144 | make_menu_in_widget (widget_instance* instance, Widget widget, |
| 145 | widget_value* val) |
| 146 | { |
| 147 | widget_value* cur; |
| 148 | Widget button; |
| 149 | Arg al [256]; |
| 150 | int ac; |
| 151 | String label; |
| 152 | |
| 153 | for (cur = val; cur; cur = cur->next) |
| 154 | { |
| 155 | ac = 0; |
| 156 | XtSetArg (al [ac], XtNsensitive, cur->enabled); ac++; |
| 157 | XtSetArg (al [ac], XtNuserData, instance); ac++; |
| 158 | XtSetArg (al [ac], XtNacceleratorText, cur->key); ac++; |
| 159 | |
| 160 | /* label = (char *) resource_string (widget, cur->name);*/ |
| 161 | label = cur->name; |
| 162 | if (label) |
| 163 | { |
| 164 | XtSetArg (al [ac], XtNlabel, label); ac++; |
| 165 | } |
| 166 | |
| 167 | if (all_dashes_p (cur->name)) |
| 168 | { |
| 169 | /* no separator in OpenLook just make some space. */ |
| 170 | XtSetArg (al [ac], XtNheight, 5); ac++; |
| 171 | XtSetArg (al [ac], XtNwidth, 5); ac++; |
| 172 | button = XtCreateWidget (cur->name, stubWidgetClass, widget, al, ac); |
| 173 | } |
| 174 | else if (!cur->contents) |
| 175 | { |
| 176 | if (!cur->call_data) |
| 177 | button = |
| 178 | XtCreateManagedWidget (cur->name, staticTextWidgetClass, widget, |
| 179 | al, ac); |
| 180 | else |
| 181 | { |
| 182 | button = |
| 183 | XtCreateManagedWidget (cur->name, oblongButtonWidgetClass, |
| 184 | widget, al, ac); |
| 185 | XtAddCallback (button, XtNselect, pick_hook, cur); |
| 186 | } |
| 187 | } |
| 188 | else |
| 189 | { |
| 190 | Widget menu = NULL; |
| 191 | button = |
| 192 | XtCreateManagedWidget (cur->name, menuButtonWidgetClass, widget, |
| 193 | al, ac); |
| 194 | XtVaGetValues (button, XtNmenuPane, &menu, 0); |
| 195 | if (!menu) |
| 196 | abort (); |
| 197 | make_menu_in_widget (instance, menu, cur->contents); |
| 198 | OlAddCallback (button, XtNconsumeEvent, pre_hook, instance); |
| 199 | } |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | static void |
| 204 | update_one_menu_entry (widget_instance* instance, Widget widget, |
| 205 | widget_value* val) |
| 206 | { |
| 207 | Arg al [256]; |
| 208 | int ac; |
| 209 | Widget menu; |
| 210 | widget_value* contents; |
| 211 | |
| 212 | if (val->change == NO_CHANGE) |
| 213 | return; |
| 214 | |
| 215 | /* update the sensitivity */ |
| 216 | XtVaSetValues (widget, XtNsensitive, val->enabled, 0); |
| 217 | |
| 218 | /* update the pulldown/pullaside as needed */ |
| 219 | ac = 0; |
| 220 | menu = NULL; |
| 221 | XtVaGetValues (widget, XtNmenuPane, &menu, 0); |
| 222 | contents = val->contents; |
| 223 | |
| 224 | if (!menu) |
| 225 | { |
| 226 | if (contents) |
| 227 | { |
| 228 | /* in OLIT this would have to be a structural change on the |
| 229 | button. */ |
| 230 | abort (); |
| 231 | } |
| 232 | } |
| 233 | else if (!contents) |
| 234 | { |
| 235 | /* in OLIT this would have to be a structural change on the button. */ |
| 236 | abort (); |
| 237 | } |
| 238 | else if (contents->change != NO_CHANGE) |
| 239 | update_menu_widget (instance, menu, val); |
| 240 | } |
| 241 | |
| 242 | static void |
| 243 | update_menu_widget (widget_instance* instance, Widget widget, |
| 244 | widget_value* val) |
| 245 | |
| 246 | { |
| 247 | if (val->change == STRUCTURAL_CHANGE |
| 248 | || val->contents->change == STRUCTURAL_CHANGE) |
| 249 | { |
| 250 | destroy_all_children (widget); |
| 251 | make_menu_in_widget (instance, widget, val->contents); |
| 252 | } |
| 253 | else |
| 254 | { |
| 255 | /* Update all the buttons of the composite widget in order. */ |
| 256 | Widget* children; |
| 257 | unsigned int num_children; |
| 258 | int i; |
| 259 | widget_value* cur; |
| 260 | |
| 261 | children = (Widget *) XtCompositeChildren (widget, &num_children); |
| 262 | if (children) |
| 263 | { |
| 264 | for (i = 0, cur = val->contents; i < num_children; i++) |
| 265 | { |
| 266 | if (!cur) |
| 267 | abort (); |
| 268 | if (children [i]->core.being_destroyed |
| 269 | || strcmp (XtName (children [i]), cur->name)) |
| 270 | continue; |
| 271 | update_one_menu_entry (instance, children [i], cur); |
| 272 | cur = cur->next; |
| 273 | } |
| 274 | XtFree (children); |
| 275 | } |
| 276 | if (cur) |
| 277 | abort (); |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | void |
| 282 | xol_update_one_widget (widget_instance* instance, Widget widget, |
| 283 | widget_value* val, Boolean deep_p) |
| 284 | { |
| 285 | Widget menu = widget; |
| 286 | |
| 287 | if (XtIsShell (widget)) |
| 288 | XtVaGetValues (widget, XtNmenuPane, &menu, 0); |
| 289 | |
| 290 | update_menu_widget (instance, menu, val); |
| 291 | } |
| 292 | |
| 293 | void |
| 294 | xol_update_one_value (widget_instance* instance, Widget widget, |
| 295 | widget_value* val) |
| 296 | { |
| 297 | return; |
| 298 | } |
| 299 | |
| 300 | void |
| 301 | xol_pop_instance (widget_instance* instance, Boolean up) |
| 302 | { |
| 303 | } |
| 304 | |
| 305 | void |
| 306 | xol_popup_menu (Widget widget) |
| 307 | { |
| 308 | OlMenuPost (widget); |
| 309 | } |
| 310 | |
| 311 | \f/* Destruction of instances */ |
| 312 | void |
| 313 | xol_destroy_instance (widget_instance* instance) |
| 314 | { |
| 315 | XtDestroyWidget (instance->widget); |
| 316 | } |
| 317 | |