Fixed another bunch of i18n bugs (thx to Leon Cheung for spotting them), among which:
[blender.git] / source / blender / editors / space_outliner / space_outliner.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_outliner/space_outliner.c
28  *  \ingroup spoutliner
29  */
30
31
32 #include <string.h>
33 #include <stdio.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_math.h"
39 #include "BLI_rand.h"
40 #include "BLI_utildefines.h"
41
42 #include "BKE_context.h"
43 #include "BKE_screen.h"
44
45 #include "ED_space_api.h"
46 #include "ED_screen.h"
47
48 #include "WM_api.h"
49 #include "WM_types.h"
50
51 #include "BIF_gl.h"
52
53 #include "RNA_access.h"
54
55 #include "UI_resources.h"
56 #include "UI_view2d.h"
57
58
59 #include "outliner_intern.h"
60
61 static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar)
62 {
63         ListBase *lb;
64         wmKeyMap *keymap;
65         
66         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
67         
68         /* own keymap */
69         keymap = WM_keymap_find(wm->defaultconf, "Outliner", SPACE_OUTLINER, 0);
70         /* don't pass on view2d mask, it's always set with scrollbar space, hide fails */
71         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, NULL, &ar->winrct);
72
73         /* Add dropboxes */
74         lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
75         WM_event_add_dropbox_handler(&ar->handlers, lb);
76 }
77
78 static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
79 {
80         ARegion *ar= CTX_wm_region(C);
81         SpaceOops *soops= CTX_wm_space_outliner(C);
82         TreeElement *te= NULL;
83         float fmval[2];
84         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
85
86         if (drag->type == WM_DRAG_ID) {
87                 ID *id = (ID *)drag->poin;
88                 if ( GS(id->name) == ID_OB ) {
89                         /* Ensure item under cursor is valid drop target */
90                         /* Find object hovered over */
91                         for (te= soops->tree.first; te; te= te->next) {
92                                 TreeElement *te_valid;
93                                 te_valid= outliner_dropzone_parent(C, event, te, fmval);
94                                 if (te_valid) return 1;
95                         }
96                 }
97         }
98         return 0;
99 }
100
101 static void outliner_parent_drop_copy(wmDrag *drag, wmDropBox *drop)
102 {
103         ID *id = (ID *)drag->poin;
104
105         RNA_string_set(drop->ptr, "child", id->name+2);
106 }
107
108 static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, wmEvent *event)
109 {
110         ARegion *ar= CTX_wm_region(C);
111         SpaceOops *soops= CTX_wm_space_outliner(C);
112         TreeElement *te= NULL;
113         float fmval[2];
114
115         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
116
117         if (drag->type == WM_DRAG_ID) {
118                 ID *id = (ID *)drag->poin;
119                 if ( GS(id->name) == ID_OB ) {
120                         //TODO: Check if no parent?
121                         /* Ensure location under cursor is valid dropzone */
122                         for (te= soops->tree.first; te; te= te->next) {
123                                 if (outliner_dropzone_parent_clear(C, event, te, fmval)) return 1;
124                         }
125                         /* Check if mouse cursor is below the tree */
126                         te= soops->tree.last;
127                         while (((te->flag & TE_LAZY_CLOSED)==0) && (te->subtree.last)) {
128                                 te= te->subtree.last;
129                         }
130                         if (fmval[1] < te->ys) return 1;
131                 }
132         }
133         return 0;
134 }
135
136 static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop)
137 {
138         ID *id = (ID *)drag->poin;
139         RNA_string_set(drop->ptr, "dragged_obj", id->name+2);
140
141         /* Set to simple parent clear type. Avoid menus for drag and drop if possible.
142          * If desired, user can toggle the different "Clear Parent" types in the operator
143          * menu on tool shelf. */
144         RNA_enum_set(drop->ptr, "type", 0);
145 }
146
147 /* region dropbox definition */
148 static void outliner_dropboxes(void)
149 {
150         ListBase *lb = WM_dropboxmap_find("Outliner", SPACE_OUTLINER, RGN_TYPE_WINDOW);
151
152         WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", outliner_parent_drop_poll, outliner_parent_drop_copy);
153         WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy);
154 }
155
156 static void outliner_main_area_draw(const bContext *C, ARegion *ar)
157 {
158         View2D *v2d= &ar->v2d;
159         View2DScrollers *scrollers;
160         
161         /* clear */
162         UI_ThemeClearColor(TH_BACK);
163         glClear(GL_COLOR_BUFFER_BIT);
164         
165         draw_outliner(C);
166         
167         /* reset view matrix */
168         UI_view2d_view_restore(C);
169         
170         /* scrollers */
171         scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
172         UI_view2d_scrollers_draw(C, v2d, scrollers);
173         UI_view2d_scrollers_free(scrollers);
174 }
175
176
177 static void outliner_main_area_free(ARegion *UNUSED(ar))
178 {
179         
180 }
181
182 static void outliner_main_area_listener(ARegion *ar, wmNotifier *wmn)
183 {
184         /* context changes */
185         switch(wmn->category) {
186                 case NC_SCENE:
187                         switch(wmn->data) {
188                                 case ND_OB_ACTIVE:
189                                 case ND_OB_SELECT:
190                                 case ND_OB_VISIBLE:
191                                 case ND_OB_RENDER:
192                                 case ND_MODE:
193                                 case ND_KEYINGSET:
194                                 case ND_FRAME:
195                                 case ND_RENDER_OPTIONS:
196                                 case ND_LAYER:
197                                 case ND_WORLD:
198                                         ED_region_tag_redraw(ar);
199                                         break;
200                         }
201                         break;
202                 case NC_OBJECT:
203                         switch(wmn->data) {
204                                 case ND_TRANSFORM:
205                                         /* transform doesn't change outliner data */
206                                         break;
207                                 case ND_BONE_ACTIVE:
208                                 case ND_BONE_SELECT:
209                                 case ND_DRAW:
210                                 case ND_PARENT:
211                                 case ND_OB_SHADING:
212                                         ED_region_tag_redraw(ar);
213                                         break;
214                                 case ND_CONSTRAINT:
215                                         switch(wmn->action) {
216                                                 case NA_ADDED:
217                                                 case NA_REMOVED:
218                                                 case NA_RENAME:
219                                                         ED_region_tag_redraw(ar);
220                                                         break;
221                                         }
222                                         break;
223                                 case ND_MODIFIER:
224                                         /* all modifier actions now */
225                                         ED_region_tag_redraw(ar);
226                                         break;
227                         }
228                         break;
229                 case NC_GROUP:
230                         /* all actions now, todo: check outliner view mode? */
231                         ED_region_tag_redraw(ar);
232                         break;
233                 case NC_LAMP:
234                         /* For updating lamp icons, when changing lamp type */
235                         if (wmn->data == ND_LIGHTING_DRAW)
236                                 ED_region_tag_redraw(ar);
237                                 break;
238                 case NC_SPACE:
239                         if (wmn->data == ND_SPACE_OUTLINER)
240                                 ED_region_tag_redraw(ar);
241                                 break;
242                 case NC_ID:
243                         if (wmn->action == NA_RENAME)
244                                 ED_region_tag_redraw(ar);
245                         break;
246                 case NC_MATERIAL:
247                         switch(wmn->data) {
248                                 case ND_SHADING:
249                                 case ND_SHADING_DRAW:
250                                         ED_region_tag_redraw(ar);
251                                         break;
252                         }
253                         break;
254                 case NC_TEXTURE:
255                         ED_region_tag_redraw(ar);
256                         break;
257                 case NC_GEOM:
258                         switch(wmn->data) {
259                                 case ND_DATA:
260                                         /* needed for vertex groups only, no special notifier atm so use NC_GEOM|ND_DATA */
261                                         ED_region_tag_redraw(ar);
262                                         break;
263                         }
264                         break;
265                 case NC_ANIMATION:
266                         switch(wmn->data) {
267                                 case ND_NLA_ACTCHANGE:
268                                 case ND_KEYFRAME:
269                                         ED_region_tag_redraw(ar);
270                                         break;
271                                 case ND_ANIMCHAN:
272                                         if (wmn->action==NA_SELECTED)
273                                                 ED_region_tag_redraw(ar);
274                                         break;
275                         }
276                         break;
277         }
278         
279 }
280
281
282 /* ************************ header outliner area region *********************** */
283
284 /* add handlers, stuff you only do once or on area/region changes */
285 static void outliner_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
286 {
287         ED_region_header_init(ar);
288 }
289
290 static void outliner_header_area_draw(const bContext *C, ARegion *ar)
291 {
292         ED_region_header(C, ar);
293 }
294
295 static void outliner_header_area_free(ARegion *UNUSED(ar))
296 {
297 }
298
299 static void outliner_header_area_listener(ARegion *ar, wmNotifier *wmn)
300 {
301         /* context changes */
302         switch(wmn->category) {
303                 case NC_SCENE:
304                         if (wmn->data == ND_KEYINGSET)
305                                 ED_region_tag_redraw(ar);
306                         break;
307                 case NC_SPACE:
308                         if (wmn->data == ND_SPACE_OUTLINER)
309                                 ED_region_tag_redraw(ar);
310                         break;
311         }
312 }
313
314 /* ******************** default callbacks for outliner space ***************** */
315
316 static SpaceLink *outliner_new(const bContext *UNUSED(C))
317 {
318         ARegion *ar;
319         SpaceOops *soutliner;
320
321         soutliner= MEM_callocN(sizeof(SpaceOops), "initoutliner");
322         soutliner->spacetype= SPACE_OUTLINER;
323         
324         /* header */
325         ar= MEM_callocN(sizeof(ARegion), "header for outliner");
326         
327         BLI_addtail(&soutliner->regionbase, ar);
328         ar->regiontype= RGN_TYPE_HEADER;
329         ar->alignment= RGN_ALIGN_BOTTOM;
330         
331         /* main area */
332         ar= MEM_callocN(sizeof(ARegion), "main area for outliner");
333         
334         BLI_addtail(&soutliner->regionbase, ar);
335         ar->regiontype= RGN_TYPE_WINDOW;
336         
337         ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
338         ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
339         ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
340         ar->v2d.keeptot= V2D_KEEPTOT_STRICT;
341         ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
342         
343         return (SpaceLink*)soutliner;
344 }
345
346 /* not spacelink itself */
347 static void outliner_free(SpaceLink *sl)
348 {
349         SpaceOops *soutliner= (SpaceOops*)sl;
350         
351         outliner_free_tree(&soutliner->tree);
352         if (soutliner->treestore) {
353                 if (soutliner->treestore->data) MEM_freeN(soutliner->treestore->data);
354                 MEM_freeN(soutliner->treestore);
355         }
356         
357 }
358
359 /* spacetype; init callback */
360 static void outliner_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
361 {
362         
363 }
364
365 static SpaceLink *outliner_duplicate(SpaceLink *sl)
366 {
367         SpaceOops *soutliner= (SpaceOops *)sl;
368         SpaceOops *soutlinern= MEM_dupallocN(soutliner);
369
370         soutlinern->tree.first= soutlinern->tree.last= NULL;
371         soutlinern->treestore= NULL;
372         
373         return (SpaceLink *)soutlinern;
374 }
375
376 /* only called once, from space_api/spacetypes.c */
377 void ED_spacetype_outliner(void)
378 {
379         SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype time");
380         ARegionType *art;
381         
382         st->spaceid= SPACE_OUTLINER;
383         strncpy(st->name, "Outliner", BKE_ST_MAXNAME);
384         
385         st->new= outliner_new;
386         st->free= outliner_free;
387         st->init= outliner_init;
388         st->duplicate= outliner_duplicate;
389         st->operatortypes= outliner_operatortypes;
390         st->keymap= outliner_keymap;
391         st->dropboxes= outliner_dropboxes;
392         
393         /* regions: main window */
394         art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
395         art->regionid = RGN_TYPE_WINDOW;
396         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
397         
398         art->init= outliner_main_area_init;
399         art->draw= outliner_main_area_draw;
400         art->free= outliner_main_area_free;
401         art->listener= outliner_main_area_listener;
402         BLI_addhead(&st->regiontypes, art);
403         
404         /* regions: header */
405         art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
406         art->regionid = RGN_TYPE_HEADER;
407         art->prefsizey= HEADERY;
408         art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER;
409         
410         art->init= outliner_header_area_init;
411         art->draw= outliner_header_area_draw;
412         art->free= outliner_header_area_free;
413         art->listener= outliner_header_area_listener;
414         BLI_addhead(&st->regiontypes, art);
415         
416         BKE_spacetype_register(st);
417 }
418