AmendHub

jcs

/

amend

/

amendments

/

82

focusable: Import focusable framework


jcs made amendment 82 about 1 month ago
--- focusable.c Tue Aug 16 14:20:54 2022 +++ focusable.c Tue Aug 16 14:20:54 2022 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021-2022 joshua stein <jcs@jcs.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <string.h> + +#include "focusable.h" +#include "util.h" + +struct focusable **focusables = NULL; +short nfocusables = 0; + +struct focusable * +focusable_find(GrafPtr win) +{ + short n; + + for (n = 0; n < nfocusables; n++) { + if (focusables[n]->win == win) + return focusables[n]; + } + + return NULL; +} + +struct focusable * +focusable_focused(void) +{ + if (nfocusables && focusables[0]->visible) + return focusables[0]; + + return NULL; +} + +void +focusable_add(struct focusable *focusable) +{ + short n; + + nfocusables++; + focusables = xreallocarray(focusables, sizeof(struct focusable *), + nfocusables); + + if (nfocusables > 1) + for (n = nfocusables - 1; n > 0; n--) + focusables[n] = focusables[n - 1]; + + focusables[0] = focusable; + + focusable_show(focusable); +} + +bool +focusable_show(struct focusable *focusable) +{ + struct focusable *last, *tmp; + short n; + + if (nfocusables > 1 && focusables[0] != focusable) { + last = focusables[0]; + + if (last->modal) + /* other focusables cannot steal focus from modals */ + return false; + + focusables[0] = focusable; + for (n = 1; n < nfocusables; n++) { + tmp = focusables[n]; + focusables[n] = last; + last = tmp; + if (last == focusable) + break; + } + } + + if (!focusable->visible) { + focusable->visible = true; + ShowWindow(focusable->win); + } + + SelectWindow(focusable->win); + SetPort(focusable->win); + + return true; +} + +bool +focusable_close(struct focusable *focusable) +{ + short n; + + if (focusable->close) { + if (!focusable->close(focusable)) + return false; + } else + DisposeWindow(focusable->win); + + for (n = 0; n < nfocusables; n++) { + if (focusables[n] == focusable) { + for (; n < nfocusables - 1; n++) + focusables[n] = focusables[n + 1]; + break; + } + } + + nfocusables--; + if (nfocusables) + focusables = xreallocarray(focusables, sizeof(Ptr), nfocusables); + else { + free(focusables); + focusables = NULL; + } + + if (nfocusables && focusables[0]->visible) + focusable_show(focusables[0]); + + return true; +} + +void +focusable_hide(struct focusable *focusable) +{ + short n; + + HideWindow(focusable->win); + focusable->visible = false; + + for (n = 0; n < nfocusables; n++) { + if (focusables[n] == focusable) { + for (; n < nfocusables - 1; n++) + focusables[n] = focusables[n + 1]; + break; + } + } + focusables[nfocusables - 1] = focusable; +} + +bool +focusables_quit(void) +{ + short tnfocusables = nfocusables; + short n; + struct focusable **tfocusables; + bool quit = true; + + if (nfocusables) { + /* + * nfocusables and focusables array will probably be + * modified as each focusable quits + */ + tfocusables = xcalloc(sizeof(Ptr), tnfocusables); + memcpy(tfocusables, focusables, sizeof(Ptr) * tnfocusables); + + for (n = 0; n < tnfocusables; n++) { + if (tfocusables[n] && !focusable_close(tfocusables[n])) { + quit = false; + break; + } + } + + free(tfocusables); + } + + return quit; +} --- focusable.h Tue Aug 16 13:33:08 2022 +++ focusable.h Tue Aug 16 13:33:08 2022 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021-2022 joshua stein <jcs@jcs.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __FOCUSABLE_H__ +#define __FOCUSABLE_H__ + +#include "util.h" + +struct focusable { + WindowPtr win; + bool visible; + void *cookie; + bool modal; + short (*wait_type)(struct focusable *focusable); + void (*idle)(struct focusable *focusable, EventRecord *event); + void (*update)(struct focusable *focusable, EventRecord *event); + void (*key_down)(struct focusable *focusable, EventRecord *event); + void (*mouse_down)(struct focusable *focusable, EventRecord *event); + bool (*menu)(struct focusable *focusable, short menu, short item); + void (*suspend)(struct focusable *focusable, EventRecord *event); + void (*resume)(struct focusable *focusable, EventRecord *event); + bool (*close)(struct focusable *focusable); + void (*atexit)(struct focusable *focusable); +}; +extern struct focusable **focusables; +extern short nfocusables; + +struct focusable * focusable_find(GrafPtr win); +struct focusable * focusable_focused(void); +void focusable_add(struct focusable *focusable); +bool focusable_show(struct focusable *focusable); +bool focusable_close(struct focusable *focusable); +void focusable_hide(struct focusable *focusable); +bool focusables_quit(void); + +#endif