Blender V2.61 - r43446

space_console.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  * 
00018  * Contributor(s): Campbell Barton
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00027 #include <string.h>
00028 #include <stdio.h>
00029 
00030 #ifdef WIN32
00031 #include "BLI_winstuff.h"
00032 #endif
00033 
00034 #include "MEM_guardedalloc.h"
00035 
00036 #include "BLI_blenlib.h"
00037 #include "BLI_math.h"
00038 #include "BLI_utildefines.h"
00039 
00040 #include "BKE_context.h"
00041 #include "BKE_screen.h"
00042 #include "BKE_idcode.h"
00043 
00044 #include "ED_space_api.h"
00045 #include "ED_screen.h"
00046 
00047 #include "BIF_gl.h"
00048 
00049 #include "RNA_access.h"
00050 
00051 #include "WM_api.h"
00052 #include "WM_types.h"
00053 
00054 #include "UI_resources.h"
00055 #include "UI_view2d.h"
00056 
00057 #include "console_intern.h" // own include
00058 
00059 /* ******************** default callbacks for console space ***************** */
00060 
00061 static SpaceLink *console_new(const bContext *UNUSED(C))
00062 {
00063     ARegion *ar;
00064     SpaceConsole *sconsole;
00065     
00066     sconsole= MEM_callocN(sizeof(SpaceConsole), "initconsole");
00067     sconsole->spacetype= SPACE_CONSOLE;
00068     
00069     sconsole->lheight=  14;
00070     
00071     /* header */
00072     ar= MEM_callocN(sizeof(ARegion), "header for console");
00073     
00074     BLI_addtail(&sconsole->regionbase, ar);
00075     ar->regiontype= RGN_TYPE_HEADER;
00076     ar->alignment= RGN_ALIGN_BOTTOM;
00077     
00078     
00079     /* main area */
00080     ar= MEM_callocN(sizeof(ARegion), "main area for text");
00081     
00082     BLI_addtail(&sconsole->regionbase, ar);
00083     ar->regiontype= RGN_TYPE_WINDOW;
00084     
00085     /* keep in sync with info */
00086     ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
00087     ar->v2d.align |= V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y; /* align bottom left */
00088     ar->v2d.keepofs |= V2D_LOCKOFS_X;
00089     ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
00090     ar->v2d.keeptot= V2D_KEEPTOT_BOUNDS;
00091     ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
00092 
00093     /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
00094     //ar->v2d.keepzoom= (V2D_KEEPASPECT|V2D_LIMITZOOM);
00095 
00096     return (SpaceLink *)sconsole;
00097 }
00098 
00099 /* not spacelink itself */
00100 static void console_free(SpaceLink *sl)
00101 {
00102     SpaceConsole *sc= (SpaceConsole*) sl;
00103     
00104     while(sc->scrollback.first)
00105         console_scrollback_free(sc, sc->scrollback.first);
00106     
00107     while(sc->history.first)
00108         console_history_free(sc, sc->history.first);
00109 }
00110 
00111 
00112 /* spacetype; init callback */
00113 static void console_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
00114 {
00115 
00116 }
00117 
00118 static SpaceLink *console_duplicate(SpaceLink *sl)
00119 {
00120     SpaceConsole *sconsolen= MEM_dupallocN(sl);
00121     
00122     /* clear or remove stuff from old */
00123     
00124     /* TODO - duplicate?, then we also need to duplicate the py namespace */
00125     sconsolen->scrollback.first= sconsolen->scrollback.last= NULL;
00126     sconsolen->history.first= sconsolen->history.last= NULL;
00127     
00128     return (SpaceLink *)sconsolen;
00129 }
00130 
00131 
00132 
00133 /* add handlers, stuff you only do once or on area/region changes */
00134 static void console_main_area_init(wmWindowManager *wm, ARegion *ar)
00135 {
00136     wmKeyMap *keymap;
00137     ListBase *lb;
00138 
00139     const float prev_y_min= ar->v2d.cur.ymin; /* so resizing keeps the cursor visible */
00140 
00141     UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
00142 
00143     /* always keep the bottom part of the view aligned, less annoying */
00144     if(prev_y_min != ar->v2d.cur.ymin) {
00145         const float cur_y_range= ar->v2d.cur.ymax - ar->v2d.cur.ymin;
00146         ar->v2d.cur.ymin= prev_y_min;
00147         ar->v2d.cur.ymax= prev_y_min + cur_y_range;
00148     }
00149 
00150     /* own keymap */
00151     keymap= WM_keymap_find(wm->defaultconf, "Console", SPACE_CONSOLE, 0);
00152     WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
00153     
00154     /* add drop boxes */
00155     lb= WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
00156     
00157     WM_event_add_dropbox_handler(&ar->handlers, lb);
00158 }
00159 
00160 
00161 /* ************* dropboxes ************* */
00162 
00163 static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
00164 {
00165 //  SpaceConsole *sc= CTX_wm_space_console(C);
00166     if(drag->type==WM_DRAG_ID)
00167         return 1;
00168     return 0;
00169 }
00170 
00171 static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
00172 {
00173     char text[64];
00174     ID *id= drag->poin;
00175     char id_esc[(sizeof(id->name) - 2) * 2];
00176 
00177     BLI_strescape(id_esc, id->name+2, sizeof(id_esc));
00178 
00179     BLI_snprintf(text, sizeof(text), "bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc);
00180 
00181     /* copy drag path to properties */
00182     RNA_string_set(drop->ptr, "text", text);
00183 }
00184 
00185 static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
00186 {
00187 //    SpaceConsole *sc= CTX_wm_space_console(C);
00188     if(drag->type==WM_DRAG_PATH)
00189         return 1;
00190     return 0;
00191 }
00192 
00193 static void path_drop_copy(wmDrag *drag, wmDropBox *drop)
00194 {
00195     char pathname[FILE_MAX+2];
00196     BLI_snprintf(pathname, sizeof(pathname), "\"%s\"", drag->path);
00197     RNA_string_set(drop->ptr, "text", pathname);
00198 }
00199 
00200 
00201 /* this region dropbox definition */
00202 static void console_dropboxes(void)
00203 {
00204     ListBase *lb= WM_dropboxmap_find("Console", SPACE_CONSOLE, RGN_TYPE_WINDOW);
00205     
00206     WM_dropbox_add(lb, "CONSOLE_OT_insert", id_drop_poll, id_drop_copy);
00207     WM_dropbox_add(lb, "CONSOLE_OT_insert", path_drop_poll, path_drop_copy);
00208 }
00209 
00210 /* ************* end drop *********** */
00211 
00212 static void console_main_area_draw(const bContext *C, ARegion *ar)
00213 {
00214     /* draw entirely, view changes should be handled here */
00215     SpaceConsole *sc= CTX_wm_space_console(C);
00216     View2D *v2d= &ar->v2d;
00217     View2DScrollers *scrollers;
00218 
00219     if(sc->scrollback.first==NULL)
00220         WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL);
00221 
00222     /* clear and setup matrix */
00223     UI_ThemeClearColor(TH_BACK);
00224     glClear(GL_COLOR_BUFFER_BIT);
00225 
00226     /* worlks best with no view2d matrix set */
00227     UI_view2d_view_ortho(v2d);
00228 
00229     /* data... */
00230 
00231     console_history_verify(C); /* make sure we have some command line */
00232     console_textview_main(sc, ar);
00233     
00234     /* reset view matrix */
00235     UI_view2d_view_restore(C);
00236     
00237     /* scrollers */
00238     scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_GRID_CLAMP);
00239     UI_view2d_scrollers_draw(C, v2d, scrollers);
00240     UI_view2d_scrollers_free(scrollers);
00241 }
00242 
00243 static void console_operatortypes(void)
00244 {
00245     /* console_ops.c */
00246     WM_operatortype_append(CONSOLE_OT_move);
00247     WM_operatortype_append(CONSOLE_OT_delete);
00248     WM_operatortype_append(CONSOLE_OT_insert);
00249     
00250     /* for use by python only */
00251     WM_operatortype_append(CONSOLE_OT_history_append); 
00252     WM_operatortype_append(CONSOLE_OT_scrollback_append);
00253     
00254     WM_operatortype_append(CONSOLE_OT_clear); 
00255     WM_operatortype_append(CONSOLE_OT_history_cycle);
00256     WM_operatortype_append(CONSOLE_OT_copy);
00257     WM_operatortype_append(CONSOLE_OT_paste);
00258     WM_operatortype_append(CONSOLE_OT_select_set);
00259 }
00260 
00261 static void console_keymap(struct wmKeyConfig *keyconf)
00262 {
00263     wmKeyMap *keymap= WM_keymap_find(keyconf, "Console", SPACE_CONSOLE, 0);
00264     wmKeyMapItem *kmi;
00265     
00266 #ifdef __APPLE__
00267     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
00268     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_END);
00269 #endif
00270 
00271     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
00272     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
00273     
00274     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
00275     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
00276     
00277     kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0);
00278     RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
00279     RNA_boolean_set(kmi->ptr, "reverse", FALSE);
00280     
00281     kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
00282     RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
00283     RNA_boolean_set(kmi->ptr, "reverse", TRUE);
00284 
00285     kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
00286     RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
00287     RNA_boolean_set(kmi->ptr, "reverse", FALSE);
00288     
00289     kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0);
00290     RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
00291     RNA_boolean_set(kmi->ptr, "reverse", TRUE);
00292 
00293     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
00294     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR);
00295     
00296     kmi = WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", UPARROWKEY, KM_PRESS, 0, 0);
00297     RNA_boolean_set(kmi->ptr, "reverse", TRUE);
00298     WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", DOWNARROWKEY, KM_PRESS, 0, 0);
00299     
00300     /*
00301     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
00302     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
00303     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_LINE);
00304     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_LINE);
00305     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_PAGE);
00306     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_PAGE);
00307 
00308 
00309     //RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
00310     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_CHAR);
00311     //RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
00312     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_WORD);
00313     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD);
00314     */
00315     
00316     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
00317     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
00318     RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", DEL_PREV_CHAR);  /* same as above [#26623] */
00319 
00320 #ifdef WITH_PYTHON
00321     WM_keymap_add_item(keymap, "CONSOLE_OT_execute", RETKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
00322     WM_keymap_add_item(keymap, "CONSOLE_OT_execute", PADENTER, KM_PRESS, 0, 0);
00323     
00324     //WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", TABKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
00325     WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0); /* python operator - space_text.py */
00326 #endif
00327 
00328     WM_keymap_add_item(keymap, "CONSOLE_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
00329     WM_keymap_add_item(keymap, "CONSOLE_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
00330 #ifdef __APPLE__
00331     WM_keymap_add_item(keymap, "CONSOLE_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
00332     WM_keymap_add_item(keymap, "CONSOLE_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
00333 #endif
00334     
00335     WM_keymap_add_item(keymap, "CONSOLE_OT_select_set", LEFTMOUSE, KM_PRESS, 0, 0);
00336 
00337     RNA_string_set(WM_keymap_add_item(keymap, "CONSOLE_OT_insert", TABKEY, KM_PRESS, 0, 0)->ptr, "text", "\t"); /* fake tabs */
00338     WM_keymap_add_item(keymap, "CONSOLE_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
00339 }
00340 
00341 /****************** header region ******************/
00342 
00343 /* add handlers, stuff you only do once or on area/region changes */
00344 static void console_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
00345 {
00346     ED_region_header_init(ar);
00347 }
00348 
00349 static void console_header_area_draw(const bContext *C, ARegion *ar)
00350 {
00351     ED_region_header(C, ar);
00352 }
00353 
00354 static void console_main_area_listener(ARegion *ar, wmNotifier *wmn)
00355 {
00356     // SpaceInfo *sinfo= sa->spacedata.first;
00357 
00358     /* context changes */
00359     switch(wmn->category) {
00360         case NC_SPACE:
00361             if(wmn->data == ND_SPACE_CONSOLE) { /* generic redraw request */
00362                 ED_region_tag_redraw(ar);
00363             }
00364             break;
00365     }
00366 }
00367 
00368 /* only called once, from space/spacetypes.c */
00369 void ED_spacetype_console(void)
00370 {
00371     SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype console");
00372     ARegionType *art;
00373     
00374     st->spaceid= SPACE_CONSOLE;
00375     strncpy(st->name, "Console", BKE_ST_MAXNAME);
00376     
00377     st->new= console_new;
00378     st->free= console_free;
00379     st->init= console_init;
00380     st->duplicate= console_duplicate;
00381     st->operatortypes= console_operatortypes;
00382     st->keymap= console_keymap;
00383     st->dropboxes= console_dropboxes;
00384     
00385     /* regions: main window */
00386     art= MEM_callocN(sizeof(ARegionType), "spacetype console region");
00387     art->regionid = RGN_TYPE_WINDOW;
00388     art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
00389 
00390     art->init= console_main_area_init;
00391     art->draw= console_main_area_draw;
00392     art->listener= console_main_area_listener;
00393     
00394     
00395 
00396     BLI_addhead(&st->regiontypes, art);
00397     
00398     /* regions: header */
00399     art= MEM_callocN(sizeof(ARegionType), "spacetype console region");
00400     art->regionid = RGN_TYPE_HEADER;
00401     art->prefsizey= HEADERY;
00402     art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_HEADER;
00403     
00404     art->init= console_header_area_init;
00405     art->draw= console_header_area_draw;
00406     
00407     BLI_addhead(&st->regiontypes, art);
00408 
00409 
00410     BKE_spacetype_register(st);
00411 }