/* text widget for Pd Copyright 2003 Guenter Geiger Copyright 2004 Ben Bogart Copyright 2007 Hans-Christoph Steiner This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "shared/tkwidgets.h" /* TODO: get Ctrl-A working to select all */ /* TODO: set message doesnt work with a loadbang */ /* TODO: add size to query and save */ /* TODO: add scrollbars to query and save */ #define DEFAULT_COLOR "grey70" #define TEXT_DEFAULT_WIDTH 130 #define TEXT_DEFAULT_HEIGHT 60 #define TEXT_MIN_WIDTH 40 #define TEXT_MIN_HEIGHT 20 #define TOTAL_INLETS 1 #define TOTAL_OUTLETS 2 #define DEBUG(x) x typedef struct _textwidget { t_object x_obj; t_canvas* x_canvas; /* canvas/glist this widget is currently drawn in*/ t_glist* x_glist; /* glist that owns this widget */ t_binbuf* options_binbuf;/* binbuf to save options state in */ int size_x; int size_y; int x_have_scrollbars; int x_resizing; int x_selected; /* IDs for Tk widgets */ t_symbol* tcl_namespace; t_symbol* receive_name; /* name to bind to to receive callbacks */ t_symbol* canvas_id; t_symbol* frame_id; t_symbol* widget_id; t_symbol* scrollbar_id; t_symbol* handle_id; t_symbol* window_id; t_symbol* all_tag; t_outlet* x_data_outlet; t_outlet* x_status_outlet; } t_textwidget; static t_class *textwidget_class; static char *textwidget_tk_options[] = { "autoseparators", "background", "borderwidth", "cursor", "exportselection", "font", "foreground", "height", "highlightbackground", "highlightcolor", "highlightthickness", "insertbackground", "insertborderwidth", "insertofftime", "insertontime", "insertwidth", "maxundo", "padx", "pady", "relief", "selectbackground", "selectborderwidth", "selectforeground", "setgrid", "spacing1", "spacing2", "spacing3", "state", "tabs", "takefocus", "undo", "width", "wrap", "xscrollcommand", "yscrollcommand" }; /* common symbols to preload */ static t_symbol *scrollbars_symbol; static t_symbol *size_symbol; static t_symbol *backspace_symbol; static t_symbol *return_symbol; static t_symbol *space_symbol; static t_symbol *tab_symbol; static t_symbol *escape_symbol; static t_symbol *left_symbol; static t_symbol *right_symbol; static t_symbol *up_symbol; static t_symbol *down_symbol; /* function prototypes */ static void textwidget_getrect(t_gobj *z, t_glist *owner, int *xp1, int *yp1, int *xp2, int *yp2); static void textwidget_displace(t_gobj *z, t_glist *glist, int dx, int dy); static void textwidget_select(t_gobj *z, t_glist *glist, int state); static void textwidget_activate(t_gobj *z, t_glist *glist, int state); static void textwidget_delete(t_gobj *z, t_glist *glist); static void textwidget_vis(t_gobj *z, t_glist *glist, int vis); //static int textwidget_click(t_gobj *z, t_glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit); static void textwidget_save(t_gobj *z, t_binbuf *b); static void textwidget_query_callback(t_textwidget *x, t_symbol *s, int argc, t_atom *argv); static t_widgetbehavior textwidget_widgetbehavior = { w_getrectfn: textwidget_getrect, w_displacefn: textwidget_displace, w_selectfn: textwidget_select, w_activatefn: textwidget_activate, w_deletefn: textwidget_delete, w_visfn: textwidget_vis, w_clickfn: NULL, }; /* widget helper functions */ static void store_options(t_textwidget *x) { // build list then send the whole shebang to store_callback int i; int argc = sizeof(textwidget_tk_options)/sizeof(char *); post("total options: %d", argc); for(i = 0; i < argc; i++) { // TODO: only send if there is a value, not when blank sys_vgui("lappend ::%s::store_list -%s \n", x->tcl_namespace->s_name, textwidget_tk_options[i]); sys_vgui("lappend ::%s::store_list [%s cget -%s] \n", x->tcl_namespace->s_name, x->widget_id, textwidget_tk_options[i]); post("option %d: %s", i, textwidget_tk_options[i]); } sys_vgui("pd [concat %s store_callback $::%s::store_list \\;]\n", x->receive_name->s_name, x->tcl_namespace->s_name); sys_vgui("unset ::%s::store_list \n", x->tcl_namespace->s_name); } static void restore_options(t_textwidget *x) { // TODO restore options from x->options_binbuf } static void set_tkwidgets_ids(t_textwidget *x, t_canvas *canvas) { x->x_canvas = canvas; x->canvas_id = tkwidgets_gen_canvas_id(x->x_canvas); x->frame_id = tkwidgets_gen_frame_id((t_object*)x, x->canvas_id); x->widget_id = tkwidgets_gen_widget_id((t_object*)x, x->frame_id); x->scrollbar_id = tkwidgets_gen_scrollbar_id((t_object*)x, x->frame_id); x->window_id = tkwidgets_gen_window_id((t_object*)x, x->frame_id); x->handle_id = tkwidgets_gen_handle_id((t_object *)x, x->canvas_id); } static int calculate_onset(t_textwidget *x, t_glist *glist, int current_iolet, int total_iolets) { post("calculate_onset"); return(text_xpix(&x->x_obj, glist) + (x->size_x - IOWIDTH) \ * current_iolet / (total_iolets == 1 ? 1 : total_iolets - 1)); } static void textwidget_draw_inlets(t_textwidget *x, t_glist *glist, int firsttime, int total_inlets, int total_outlets) { DEBUG(post("textwidget_draw_inlets in: %d out: %d", total_inlets, total_outlets);); int i, onset; for (i = 0; i < total_inlets; i++) /* inlets */ { onset = calculate_onset(x, glist, i, total_inlets); sys_vgui("%s create rectangle %d %d %d %d -tags {%xi%d %xi %s}\n", x->canvas_id->s_name, onset, text_ypix(&x->x_obj, glist) - 2, onset + IOWIDTH, text_ypix(&x->x_obj, glist), x, i, x, x->all_tag->s_name); } for (i = 0; i < total_outlets; i++) /* outlets */ { onset = calculate_onset(x, glist, i, total_outlets); sys_vgui("%s create rectangle %d %d %d %d -tags {%xo%d %xo %s}\n", x->canvas_id->s_name, onset, text_ypix(&x->x_obj, glist) + x->size_y, onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->size_y + 2, x, i, x, x->all_tag->s_name); } } static void erase_inlets(t_textwidget *x) { DEBUG(post("erase_inlets");); /* Added tag for all inlets/outlets of one instance */ sys_vgui("%s delete %xi\n", x->canvas_id->s_name, x); sys_vgui("%s delete %xo\n", x->canvas_id->s_name, x); } static void draw_scrollbar(t_textwidget *x) { sys_vgui("pack %s -side right -fill y -before %s \n", x->scrollbar_id->s_name, x->widget_id->s_name); x->x_have_scrollbars = 1; } static void erase_scrollbar(t_textwidget *x) { sys_vgui("pack forget %s \n", x->scrollbar_id->s_name); x->x_have_scrollbars = 0; } static void bind_standard_keys(t_textwidget *x) { #ifdef __APPLE__ sys_vgui("bind %s {pdtk_canvas_ctrlkey %s %%K 0}\n", x->widget_id->s_name, x->canvas_id->s_name); sys_vgui("bind %s {pdtk_canvas_ctrlkey %s %%K 1}\n", x->widget_id->s_name, x->canvas_id->s_name); #else sys_vgui("bind %s {pdtk_canvas_ctrlkey %s %%K 0}\n", x->widget_id->s_name, x->canvas_id->s_name); sys_vgui("bind %s {pdtk_canvas_ctrlkey %s %%K 1}\n", x->widget_id->s_name, x->canvas_id->s_name); #endif } static void bind_button_events(t_textwidget *x) { /* mouse buttons */ sys_vgui("bind %s