Max 5 API Reference
00001 /** 00002 @page chapter_enhancements Enhancements to Objects 00003 00004 00005 @section chapter_enhancements_presets Preset Support 00006 00007 Presets are a simple state-saving mechanism. Your object receives a preset message when state is being saved. You respond by creating a message that will be sent back to your object when the preset is recalled. 00008 00009 For more powerful and general state-saving, use the pattr system described below. 00010 00011 To support saving a single integer in a preset, you can use the preset_int() convenience function. The preset_int() function records an int message with the value you pass it in the preset, to be sent back to your object at a later time. 00012 00013 @code 00014 class_addmethod(c, (method)myobject_preset, "preset", 0); 00015 00016 void myobject_preset(t_myobject *x) 00017 { 00018 preset_int(x, x->m_currentvalue); 00019 } 00020 @endcode 00021 00022 More generally, you can use preset_store(). Here is an example of storing two values (m_xvalue and m_yvalue) in a list. 00023 @code 00024 preset_store("ossll", x, ob_sym(x), gensym("list"), x->m_xvalue, x->m_yvalue); 00025 @endcode 00026 00027 00028 @section chapter_enhancements_assistance Assistance 00029 00030 To show descriptions of your object's inlets and outlets while editing a patcher, your object can respond to the assist message with a function that copies the text to a string. 00031 00032 @code 00033 class_addmethod(c, (method)myobject_assist, "assist", A_CANT, 0); 00034 @endcode 00035 00036 The function below has two inlets and one outlet. The io argument will be 1 for inlets, 2 for outlets. The index argument will be 0 for the leftmost inlet or outlet. You can copy a maximum of 512 characters to the output string s. You can use strncpy_zero() to copy the string, or if you want to format the assistance string based on a current value in the object, you could use snprintf_zero(). 00037 00038 @code 00039 void myobject_assist(t_myobject *x, void *b, long io, long index, char *s) 00040 { 00041 switch (io) { 00042 case 1: 00043 switch (index) { 00044 case 0: 00045 strncpy_zero(s, "This is a description of the leftmost inlet", 512); 00046 break; 00047 case 1: 00048 strncpy_zero(s, "This is a description of the rightmost inlet", 512); 00049 break; 00050 } 00051 break; 00052 case 2: 00053 strncpy_zero(s, "This is a description of the outlet", 512); 00054 break; 00055 } 00056 } 00057 @endcode 00058 00059 00060 @section chapter_enhancements_hotness Hot and Cold Inlets 00061 00062 Objects such as operators (+, -, etc.) and the int object have inlets that merely store values rather than performing an operation and producing output. These inlets are labeled with a blue color to indicate they are "cold" rather than action-producing "hot" inlets. To implement this labeling, your object can respond to the inletinfo message. 00063 00064 @code 00065 class_addmethod(c, (method)myobject_inletinfo, "inletinfo", A_CANT, 0); 00066 @endcode 00067 00068 If all of your object's non-left inlets are "cold" you can use the function stdinletinfo() instead of writing your own, as shown below: 00069 @code 00070 class_addmethod(c, (method)stdinletinfo, "inletinfo", A_CANT, 0); 00071 @endcode 00072 00073 To write your own function, just look at the index argument (which is 0 for the left inlet). This example turns the third inlet cold. You don't need to do anything for "hot" inlets. 00074 00075 @code 00076 void myobject_inletinfo(t_myobject *x, void *b, long index, char *t) 00077 { 00078 if (index == 2) 00079 *t = 1; 00080 } 00081 @endcode 00082 00083 00084 @section chapter_enhancements_ed Showing a Text Editor 00085 00086 Objects such as coll and text display a text editor window when you double-click. Users can edit the contents of the objects and save the updated data (or not). Here's how to do the same thing in your object. 00087 00088 First, if you want to support double-clicking on a non-UI object, you can respond to the dblclick message. 00089 00090 @code 00091 class_addmethod(c, (method)myobject_dblclick, "dblclick", A_CANT, 0); 00092 00093 void myobject_dblclick(t_myobject *x) 00094 { 00095 // open editor here 00096 } 00097 @endcode 00098 00099 You'll need to add a #t_object pointer to your object's data structure to hold the editor. 00100 00101 @code 00102 typedef struct _myobject 00103 { 00104 t_object m_obj; 00105 t_object *m_editor; 00106 } t_myobject; 00107 @endcode 00108 00109 Initialize the m_editor field to NULL in your new instance routine. Then implement the dblclick method as follows: 00110 @code 00111 if (!x->m_editor) 00112 x->m_editor = object_new(CLASS_NOBOX, gensym("jed"), (t_object *)x, 0); 00113 else 00114 object_attr_setchar(x->m_editor, gensym("visible"), 1); 00115 @endcode 00116 00117 The code above does the following: If the editor does not exist, we create one by making a "jed" object and passing our object as an argument. This permits the editor to tell our object when the window is closed. 00118 00119 If the editor does exist, we set its visible attribute to 1, which brings the text editor window to the front. 00120 00121 To set the text of the edit window, we can send our jed object the settext message with a zero-terminated buffer of text. We also provide a symbol specifying how the text is encoded. For best results, the text should be encoded as UTF-8. Here is an example where we set a string to contain "Some text to edit" then pass it to the editor. 00122 00123 @code 00124 char text[512]; 00125 00126 strcpy(text,"Some text to edit"); 00127 object_method(x->m_editor, gensym("settext"), text, gensym("utf-8")); 00128 @endcode 00129 00130 The title attribute sets the window title of the text editor. 00131 @code 00132 object_attr_setsym(x->m_editor, gensym("title"), gensym("crazytext")); 00133 @endcode 00134 00135 When the user closes the text window, your object (or the object you passed as an argument when creating the editor) will be sent the edclose message. 00136 @code 00137 class_addmethod(c, (method)myobject_edclose, "edclose", A_CANT, 0); 00138 @endcode 00139 00140 The edclose method is responsible for doing something with the text. It should also zero the reference to the editor stored in the object, because it will be freed. A pointer to the text pointer is passed, along with its size. The encoding of the text is always UTF-8. 00141 00142 @code 00143 void myobject_edclose(t_myobject *x, char **ht, long size) 00144 { 00145 // do something with the text 00146 x->m_editor = NULL; 00147 } 00148 @endcode 00149 00150 If your object will be showing the contents of a text file, you are still responsible for setting the initial text, but you can assign a file so that the editor will save the text data when the user chooses Save from the File menu. To assign a file, use the filename message, assuming you have a filename and path ID. 00151 00152 @code 00153 object_method(x->m_editor, gensym("filename"), x->m_myfilename, x->m_mypath); 00154 @endcode 00155 00156 The filename message will set the title of the text editor window, but you can use the title attribute to override the simple filename. For example, you might want the name of your object to precede the filename: 00157 @code 00158 char titlename[512]; 00159 00160 sprintf(titlename, "myobject: %s", x->m_myfilename); 00161 object_attr_setsym(x->m_editor, gensym("title"), gensym(titlename)); 00162 @endcode 00163 00164 Each time the user chooses Save, your object will receive an edsave message. If you return zero from your edsave method, the editor will proceed with saving the text in a file. If you return non-zero, the editor assumes you have taken care of saving the text. The general idea is that when the user wants to save the text, it is either updated inside your object, updated in a file, or both. As an example, the js object uses its edsave message to trigger a recompile of the Javascript code. But it also returns 0 from its edsave method so that the text editor will update the script file. Except for the return value, the prototype of the edsave method is identical to the edclose method. 00165 00166 @code 00167 class_addmethod(c, (method)myobject_edsave, "edsave", A_CANT, 0); 00168 00169 long myobject_edsave(t_myobject *x, char **ht, long size) 00170 { 00171 // do something with the text 00172 return 0; // tell editor it can save the text 00173 } 00174 @endcode 00175 00176 00177 @section chapter_enhancements_tables Accessing Data in table Objects 00178 00179 Table objects can be given names as arguments. If a table object has a name, you can access the data using table_get(). Supply a symbol, as well as a place to assign a pointer to the data and the length. The following example accesses a table called foo, and, if found, posts all its values. 00180 00181 @code 00182 long **data = NULL; 00183 long i, size; 00184 00185 if (!table_get(gensym("foo"), &data, &size)) { 00186 for (i = 0; i < size; i++) { 00187 post("%ld: %ld",i,(*data)[i]); 00188 } 00189 } 00190 @endcode 00191 00192 You can also write data into the table. If you would like the table editor to redraw after doing so, use table_dirty(). Here's an example where we set all values in the table to zero, then notify the table to redraw. 00193 00194 @code 00195 long **data = NULL; 00196 long i, size; 00197 00198 if (!table_get(gensym("foo"), &data, &size)) { 00199 for (i = 0; i < size; i++) { 00200 (*data)[i] = 0; 00201 } 00202 table_dirty(gensym("foo")); 00203 } 00204 @endcode 00205 00206 00207 buffer~ support 00208 00209 00210 */
Copyright © 2008, Cycling '74