root/window/widget.cc

Revision 65:4416cfac86ae, 43.5 KB (checked in by Thibaut Girka <thib@…>, 18 months ago)
Convert EUC-JP files to UTF8
Line 
1/*
2 * Copyright (c) 2004-2006  Kazunori "jagarl" Ueno
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "widget.h"
29#include <algorithm>
30#include <map>
31#include <string>
32
33Rect DSurfaceRenderText(TextGlyphStream::iterator start, TextGlyphStream::iterator end, const Rect& srcrect,
34        Surface* dst, const Rect& dstrect);
35void DSurfaceFill(Surface* src, const Rect& rect, int r, int g, int b, int a = 0xff);
36void DSurfaceMove(Surface* src, const Rect& srcrect, Surface* dst_o, const Rect& dstrect);
37
38//static char* wdefault_font_orig = "msgothic.ttc;times.ttf;";
39static std::map<int, XKFont::HorizLayout*> size_to_layout;
40static const char* wdefault_font_orig = "times.ttf;msgothic.ttc";
41static std::string wdefault_font = wdefault_font_orig;
42
43void SetFont(const char* font) {
44        if (font == 0) return;
45        std::map<int,XKFont::HorizLayout*>::iterator it;
46        for (it=size_to_layout.begin(); it != size_to_layout.end(); it++) {
47                delete it->second;
48        }
49        size_to_layout.clear();
50        wdefault_font = font;
51}
52
53// namespace Widget {
54#define TimeCursor WidTimeCursor
55#define MouseCursor WidMouseCursor
56#define Button WidButton
57#define Scale WidScale
58#define TextButton WidTextButton
59#define Text WidText
60#define AnmTime WidAnmTime
61#define AnmMove WidAnmMove
62#define AnmAlpha WidAnmAlpha
63#define AnmPtnSolid WidAnmPtnSolid
64#define AnmPtnAlpha WidAnmPtnAlpha
65
66XKFont::HorizLayout* DefaultLayout(int text_size) {
67    if(text_size <= 0) abort();//FIXME: Find why the hell text_size can be <= 0
68        if (size_to_layout.find(text_size) == size_to_layout.end()) {
69                size_to_layout[text_size] = new XKFont::HorizLayout(wdefault_font.c_str(), text_size);
70        }
71        return size_to_layout[text_size];
72}
73
74void PicWidget::activate(void) {
75}
76
77void PicWidget::deactivate(void) {
78}
79
80void PicWidget::SetRegion(const Rect& apos) {
81}
82
83void PicWidget::show(void) {
84        Pic()->show();
85}
86
87void PicWidget::hide(void) {
88        Pic()->hide();
89}
90
91void PicWidget::show_all(void) {
92        Pic()->show_all();
93}
94
95TimeCursor::TimeCursor(Event::Container& container, int _interval, PicContainer* parent, const char* s, int _sx, int _sy, int _sdx, int _sdy, int _nptn, const Rect& r) :
96        Time(container) {
97        interval = _interval;
98        if (interval < 0) interval = 100;
99        nptn = _nptn;
100        if (nptn < 0) nptn = 1;
101        count = 0; old_time = 0;
102
103        x = _sx; y = _sy; dx = _sdx; dy = _sdy;
104        SetPic(parent->create_leaf(r, PicBase::CACHE_BACK));
105        Pic()->SetSurface(s, _sx, _sy);
106};
107void TimeCursor::Elapsed(unsigned int current_time) {
108        int move = (current_time-old_time)/interval;
109        if (move) {
110                old_time += move*interval;
111                count += move;
112                count %= nptn;
113                Pic()->SetSurfacePos(x + count*dx, y + count*dy);
114        }
115        if (current_time > old_time+interval) SetWakeup(current_time);
116        else SetWakeup(old_time+interval);
117}
118
119MouseCursor::MouseCursor(Event::Container& _container, PicContainer* parent, const char* s, int x, int y, int w, int h) :
120        Event::Video(_container), container(_container) {
121        int sx, sy;
122        _container.MousePos(sx, sy);
123        SetPic(parent->create_leaf(Rect(sx, sy, sx+w, sy+h), 0));
124        Pic()->SetSurface(s, x, y);
125        x = 0; y = 0;
126        container.RegisterGlobalMotionFunc(&Motionfunc, (void*)this);
127}
128
129MouseCursor::MouseCursor(Event::Container& _container, PicContainer* parent, Surface* s, int x, int y, int w, int h) :
130        Event::Video(_container), container(_container) {
131        int sx, sy;
132        _container.MousePos(sx, sy);
133        SetPic(parent->create_leaf(Rect(sx, sy, sx+w, sy+h), 0));
134        Pic()->SetSurface(s, x, y);
135        x = 0; y = 0;
136        container.RegisterGlobalMotionFunc(&Motionfunc, (void*)this);
137}
138
139MouseCursor::~MouseCursor() {
140        container.DeleteGlobalMotionFunc(&Motionfunc, (void*)this);
141}
142
143bool MouseCursor::Motionfunc(int x, int y, void* pointer) {
144        MouseCursor* _this = (MouseCursor*)pointer;
145        // 巊䞊がカヌ゜ルポむントの堎合
146        // _this->Pic()->Move(x,y);
147        // 巊䞋がカヌ゜ルポむントの堎合
148        _this->Pic()->Move(x,y-_this->Pic()->Height());
149        return true;
150}
151
152Button::Button(Event::Container& container, PicContainer* parent, const char* s, int _sx, int _sy, int _sdx, int _sdy, int _nptn, const Rect& r, int _z) : sx(_sx), sy(_sy), sdx(_sdx), sdy(_sdy), nptn(_nptn) ,Event::Video(container,r, _z) {
153        SetPic(parent->create_leaf(r, 0));
154        Pic()->SetSurface(s, _sx, _sy);
155        show();
156        is_in = false;
157        is_toggled = false;
158        press_func = NULL;
159        press_pointer = NULL;
160        drag_func = NULL;
161        drag_pointer = NULL;
162        is_toggle_switch = false;
163}
164
165Button::Button(Event::Container& container, PicContainer* parent, Surface* s, int _sx, int _sy, int _sdx, int _sdy, int _nptn, const Rect& r, int _z) : sx(_sx), sy(_sy), sdx(_sdx), sdy(_sdy), nptn(_nptn) ,Event::Video(container,r, _z) {
166        SetPic(parent->create_leaf(r, 0));
167        Pic()->SetSurface(s, _sx, _sy);
168        show();
169        is_in = false;
170        is_toggled = false;
171        press_func = NULL;
172        press_pointer = NULL;
173        drag_func = NULL;
174        drag_pointer = NULL;
175        is_toggle_switch = false;
176}
177
178Button::~Button() {
179}
180
181void Button::In(void) {
182        is_in = true;
183        if (nptn > 1)
184                if (! is_toggled)
185                        Pic()->SetSurfacePos(sx+sdx, sy+sdy);
186}
187
188void Button::Out(void) {
189        is_in = false;
190        if (!is_toggled)
191                Pic()->SetSurfacePos(sx, sy);
192}
193
194void Button::Toggle(bool new_toggle) {
195        if (is_toggled == new_toggle) {
196                return;
197        }
198        is_toggled = new_toggle;
199        // if (is_in) return; // is_in に関わらずりィゞットの衚瀺を倉曎するこずにする
200        if (is_toggled) {
201                if (nptn > 2)
202                        Pic()->SetSurfacePos(sx+sdx*2, sy+sdy*2);
203                else if (nptn > 1)
204                        Pic()->SetSurfacePos(sx+sdx, sy+sdy);
205                else
206                        Pic()->SetSurfacePos(sx, sy);
207        } else {
208                Pic()->SetSurfacePos(sx, sy);
209        }
210}
211
212void Button::Press(void) {
213        is_in = true;
214        if (is_toggled) ;
215        else if (nptn > 2)
216                Pic()->SetSurfacePos(sx+sdx*2, sy+sdy*2);
217        else if (nptn > 1)
218                Pic()->SetSurfacePos(sx+sdx, sy+sdy);
219        if (press_func) press_func(press_pointer, this);
220        if (is_toggle_switch) Toggle(!is_toggled);
221}
222
223void Button::Release(void) {
224        if (is_toggled) ;
225        else if (nptn > 1 && is_in)
226                Pic()->SetSurfacePos(sx+sdx, sy+sdy);
227        else if (nptn > 1)
228                Pic()->SetSurfacePos(sx, sy);
229}
230
231void Button::Drag(int x_from, int y_from, int x_to, int y_to) {
232        if (drag_func) drag_func(x_from,y_from,x_to, y_to,drag_pointer, this);
233}
234
235Scale::Scale(Event::Container& _container, PicContainer* _parent, const Rect& r_orig, const Color& _color, bool _is_vertical) :
236        Event::Video(_container,Rect(0,0), 1),
237        container(_container), parent(_parent), cursor_color(_color),
238        mouse_x(0), mouse_y(0), max(0), min(0),
239        value(0), value_add(0), value_dragstart(0), is_vertical(_is_vertical),
240        change_func(0), change_pointer(0) {
241
242        arrow_down = NULL;
243        arrow_up = NULL;
244        cursor = NULL;
245        panel = NULL;
246
247        Init(r_orig);
248}
249
250extern char* create_button(int number, int& width, int& height, int r, int g, int b);
251extern char* create_box(int& width, int& height, int r, int g, int b);
252
253void Scale::Init(Rect r_orig) {
254        int r=cursor_color.r, g=cursor_color.g, b=cursor_color.b;
255        // 矢印
256        int arrow_width = -1;
257        cursor_width = -1;
258        char* button1;
259        char* button2;
260        if (is_vertical) {
261                // 矢印に必芁な領域確保
262                int arrow_height = r_orig.width();
263                button1 = create_button(2, arrow_height, arrow_width, r, g, b);
264                button2 = create_button(3, arrow_height, arrow_width, r, g, b);
265                if (r_orig.height() < arrow_width*4) {
266                        if (r_orig.height() < 8) r_orig.by = r_orig.ty + 8; // 小さすぎる堎合は匷制倉曎
267                        free( (void*)button1);
268                        free( (void*)button2);
269                        arrow_width = r_orig.height()/4;
270                        // 再割り圓お
271                        button1 = create_button(2, arrow_height, arrow_width, r, g, b);
272                        button2 = create_button(3, arrow_height, arrow_width, r, g, b);
273                }
274                // 矢印ボタンの䜜成
275                Surface* a1s = parent->Root().NewSurfaceFromRGBAData(arrow_height, arrow_width*3, button1, ALPHA_MASK);
276                int x = r_orig.lx; int y = r_orig.ty;
277                arrow_up = new Button(container, parent, a1s, 0, 0, 0, arrow_width, 3, Rect(x,y,x+arrow_height,y+arrow_width),1);
278                arrow_up->Pic()->SetSurfaceFreeFlag();
279                Surface* a2s = parent->Root().NewSurfaceFromRGBAData(arrow_height, arrow_width*3, button2, ALPHA_MASK);
280                x = r_orig.rx - arrow_height; y = r_orig.by - arrow_width;
281                arrow_down = new Button(container, parent, a2s, 0, 0, 0, arrow_width, 3, Rect(x,y,x+arrow_height,y+arrow_width),1);
282                arrow_down->Pic()->SetSurfaceFreeFlag();
283                // picture䜜成ボタンの動く領域
284                Rect r = r_orig;
285                r.ty += arrow_width;
286                r.by -= arrow_width;
287                panel = parent->create_node(r, 0);
288                SetPic(panel);
289                // ボタンの䞭心線を描画、蚭定
290                Surface* s = parent->Root().NewSurface(r.width()/2, r.height(), ALPHA_MASK);
291                DSurfaceFill(s, Rect(0,0,r.width()/2,r.height()), 0, 0, 0, 0xff);
292                Pic()->SetSurface(s, -r.width()/4, 0, 0);
293                Pic()->SetSurfaceFreeFlag();
294        } else {
295                // 矢印に必芁な領域確保
296                int arrow_height = r_orig.height();
297                button1 = create_button(0, arrow_width, arrow_height, r, g, b);
298                button2 = create_button(1, arrow_width, arrow_height, r, g, b);
299                if (r_orig.width() < arrow_width*4) {
300                        if (r_orig.width() < 8) r_orig.rx = r_orig.lx + 8; // 小さすぎる堎合は匷制倉曎
301                        free( (void*)button1);
302                        free( (void*)button2);
303                        arrow_width = r_orig.width()/4;
304                        // 再割り圓お
305                        button1 = create_button(2, arrow_width, arrow_height, r, g, b);
306                        button2 = create_button(3, arrow_width, arrow_height, r, g, b);
307                }
308                // 矢印ボタンの䜜成
309                Surface* a1s = parent->Root().NewSurfaceFromRGBAData(arrow_width, arrow_height*3, button1, ALPHA_MASK);
310                int x = r_orig.lx; int y = r_orig.ty;
311                arrow_up = new Button(container, parent, a1s, 0, 0, 0, arrow_height, 3, Rect(x,y,x+arrow_width,y+arrow_height),1);
312                arrow_up->Pic()->SetSurfaceFreeFlag();
313                Surface* a2s = parent->Root().NewSurfaceFromRGBAData(arrow_width, arrow_height*3, button2, ALPHA_MASK);
314                x = r_orig.rx - arrow_width; y = r_orig.by - arrow_height;
315                arrow_down = new Button(container, parent, a2s, 0, 0, 0, arrow_height, 3, Rect(x,y,x+arrow_width,y+arrow_height),1);
316                arrow_down->Pic()->SetSurfaceFreeFlag();
317                // picture䜜成ボタンの動く領域
318                Rect r = r_orig;
319                r.lx += arrow_width;
320                r.rx -= arrow_width;
321                panel = parent->create_node(r, 0);
322                SetPic(panel);
323                // ボタンの䞭心線を描画、蚭定
324                Surface* s = parent->Root().NewSurface(r.width(), r.height()/2, ALPHA_MASK);
325                DSurfaceFill(s, Rect(0,0,r.width(),r.height()/2), 0, 0, 0, 0xff);
326                Pic()->SetSurface(s, 0, -r.height()/4, 0);
327                Pic()->SetSurfaceFreeFlag();
328        }
329        arrow_up->press_func = &Scale::PressArrowUp;
330        arrow_up->press_pointer = (void*)this;
331        arrow_down->press_func = &Scale::PressArrowDown;
332        arrow_down->press_pointer = (void*)this;
333        arrow_up->show();
334        arrow_down->show();
335        panel->show();
336        InitCursor(0);
337}
338
339void Scale::InitCursor(int width_ratio) {
340        int r=cursor_color.r, g=cursor_color.g, b=cursor_color.b;
341        if (cursor != NULL) delete cursor;
342        cursor = NULL;
343        Rect region(0,0);
344        if (width_ratio < 0) width_ratio = 0;
345        else if (width_ratio > 1024) width_ratio = 1024;
346        if (is_vertical) {
347                if (width_ratio == 0) cursor_width = Pic()->Width() * 3 / 2; // 幅の1.5倍
348                else cursor_width = Pic()->Height()*width_ratio/1024;
349                if (cursor_width <= 0) return; // カヌ゜ルなしいいのか
350                region = Rect(0, 0, Pic()->Width(), cursor_width);
351        } else { // horizontal
352                if (width_ratio == 0) cursor_width = Pic()->Height() * 3 / 2; // 高さの1.5倍
353                else cursor_width = Pic()->Width()*width_ratio/1024;
354                if (cursor_width <= 0) return; // カヌ゜ルなしいいのか
355                region = Rect(0, 0, cursor_width, Pic()->Height());
356        }
357
358        int height = region.height();
359        int width = region.width();
360        char* box = create_box(width, height, r, g, b);
361        Surface* boxs = parent->Root().NewSurfaceFromRGBAData(width, height*3, box, ALPHA_MASK);
362        cursor = new Button(container, panel, boxs, 0, 0, 0, height, 3, region, 2);
363        cursor->Pic()->SetSurfaceFreeFlag();
364
365        cursor->press_func = &Scale::PressCursor;
366        cursor->press_pointer = (void*)this;
367        cursor->drag_func = &Scale::DragCursor;
368        cursor->drag_pointer = (void*)this;
369        cursor->show();
370
371        // 矢印等をクリックしたずきの移動量蚈算
372        int bar_width;
373        if (is_vertical) bar_width = Pic()->Height();
374        else bar_width = Pic()->Width();
375        if (bar_width <= 0) value_add = max-min;
376        else if (cursor_width == 0) value_add = 2;
377        else value_add = scale_max*cursor_width/bar_width;
378}
379
380void Scale::PressArrowDown(void* pointer, Button* from) {
381        Scale* self = (Scale*)pointer;
382        self->SetScaleValue(self->value + self->value_add);
383}
384
385void Scale::PressArrowUp(void* pointer, Button* from){
386        Scale* self = (Scale*)pointer;
387        self->SetScaleValue(self->value - self->value_add);
388}
389
390void Scale::PressCursor(void* pointer, Button* from){
391        Scale* self = (Scale*)pointer;
392        self->value_dragstart = self->value;
393}
394
395void Scale::DragCursor(int x_from, int y_from,int x, int y, void* pointer, Button* from){
396        Scale* self = (Scale*)pointer;
397        int dx, w;
398        if (self->is_vertical) {
399                dx = y-y_from;
400                w = self->Event::Video::Region().height();
401        } else {
402                dx = x-x_from;
403                w = self->Event::Video::Region().width();
404        }
405        if (w == 0) return;
406        self->SetScaleValue(self->value_dragstart + dx*scale_max/w);
407}
408
409int Scale::CalcValue(void) {
410        Rect own_region = Event::Video::Region();
411        int x, w;
412        if (is_vertical) {
413                w = own_region.height();
414                x = mouse_y - own_region.ty;
415        } else {
416                w = own_region.width();
417                x = mouse_x - own_region.lx;
418        }
419        if (w == 0) return 0;
420        if (x < 0) x = 0;
421        else if (x > w) x = w;
422        return x*scale_max/w;
423}
424
425void Scale::Press(void){
426        int v = CalcValue();
427        if (v < value) SetScaleValue(value-value_add);
428        else SetScaleValue(value+value_add);
429}
430
431void Scale::Motion(int x, int y){
432        mouse_x = x;
433        mouse_y = y;
434}
435
436void Scale::SetRange(int new_min, int new_max) {
437        min = new_min;
438        max = new_max;
439        SetValue(value);
440}
441
442void Scale::SetValue(int new_value) {
443        if (min == max) {
444                value = min;
445                SetScaleValue(0);
446                return;
447        }
448        int scale_value = (new_value-min) * scale_max / (max-min);
449        SetScaleValue(scale_value);
450}
451
452int Scale::GetValue(void) const{
453        return min + value * (max-min) / scale_max;
454}
455
456void Scale::SetScaleValue(int new_value) {
457        if (new_value < 0) value = 0;
458        else if (new_value > scale_max) value = scale_max;
459        else value = new_value;
460        if (is_vertical) {
461                int h = Pic()->Height();
462                int y = (h-cursor_width) * value / scale_max;
463                if (y < 0) y = 0;
464                cursor->Pic()->Move(0, y);
465        } else { // horizontal
466                int w = Pic()->Width();
467                int x = (w-cursor_width) * value / scale_max;
468                if (x < 0) x = 0;
469                cursor->Pic()->Move(x, 0);
470        }
471        if (change_func) {
472                (*change_func)(change_pointer, this);
473        }
474}
475
476TextButton::TextButton(Event::Container& container, PicContainer* parent, const char* text, int _text_size, Attribute attr, const Rect& r_orig, int _z, const Color& _fore, const Color& _pressed, const Color& _back) :
477        Button(container, parent, (Surface*)0, 0, 0, 0, 0, 0, r_orig, _z),
478        root(parent->Root()), surface(0), attribute(attr), text_size(_text_size),
479        fore(_fore), pressed(_pressed), back(_back)
480{
481        bool rect_changed = false;
482        // たず、テキスト領域の広さを埗る
483        Rect r(r_orig);
484
485        if (text == NULL) text = "";
486        int width = r.width(); int height = r.height();
487        if (width == 0) width = parent->Width() - r.lx;
488
489        TextStream ts = TextStream::ParseMoji(text, _fore.r , _fore.g, _fore.b, text_size);
490        TextGlyphStream gs = DefaultLayout(text_size)->Layout(ts, width);
491
492        if (r.width() == 0) { // 文字に合わせおりィゞット䜜成
493                rect_changed = true;
494                width = gs.width() + text_size;
495                r.rx = r.lx + gs.width();
496                attribute = Attribute(attribute | CENTER);
497        }
498        if (r.height() == 0) {
499                rect_changed = true;
500                if (attribute & NOPADDING) r.by = r.ty + gs.height();
501                else r.by = r.ty + gs.height() + text_size/2;
502        }
503
504        if (rect_changed) {
505                // 倧きさ倉曎
506                Pic()->SetSurfaceRect(r);
507        }
508
509        sx = 0; sy = 0; sdx = 0;
510        sdy = r.height();
511        nptn = 3;
512        int x = 0, y = 0;
513        if (attribute & CENTER)
514                x = (Pic()->Width() - gs.width()) / 2;
515        y = (Pic()->Height() - gs.height()) / 2;
516
517        //FIXME: (back.a == NULL ?)
518        if (back.a == 0) { // 背景なし、もしくはボタン抌の状態のみ背景あり
519                surface = root.NewSurface(r.width(), r.height()*2, ALPHA_MASK);
520                DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
521                if (attribute & REVERSE) {
522                        DSurfaceFill(surface, Rect(0,r.height(),r.width(),r.height()*2), pressed.r, pressed.g, pressed.b, 0xff);
523                }
524                gs.SetColor(fore.r, fore.g, fore.b);
525                DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), surface, Rect(x,y));
526                gs.SetColor(pressed.r, pressed.g, pressed.b);
527                if (attribute & REVERSE) {
528                        gs.SetReverse(true);
529                        DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), surface, Rect(x,y+r.height()));
530                        gs.SetReverse(false);
531                } else {
532                        DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), surface, Rect(x,y+r.height()));
533                }
534                nptn = 2;
535        } else { // ボタン型の背景あり
536                /* ラベル甚の Surface を䜜る */
537                width = r.width(); height = r.height();
538                char* box = create_box(width, height, back.r, back.g, back.b);
539                surface = root.NewSurfaceFromRGBAData(r.width(), r.height()*3, box, ALPHA_MASK);
540       
541                Surface* text_surface = root.NewSurface(r.width(), r.height(), ALPHA_MASK);
542                DSurfaceFill(text_surface, Rect(*text_surface), 0, 0, 0, 0);
543       
544                gs.SetColor(fore.r, fore.g, fore.b);
545                DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), text_surface, Rect(x,y));
546                root.BlitSurface(text_surface, Rect(0,0,width,height), surface, Rect(0,0));
547                gs.SetColor(pressed.r, pressed.g, pressed.b);
548                DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), text_surface, Rect(x,y));
549                root.BlitSurface(text_surface, Rect(0,0,width,height), surface, Rect(0,height));
550                root.BlitSurface(text_surface, Rect(0,0,width,height), surface, Rect(0,height*2));
551                root.DeleteSurface(text_surface);
552        }
553
554        Pic()->SetSurface(surface, 0, 0);
555        show();
556}
557
558void TextButton::SetText(const char* text, const Color& _fore, const Color& _pressed, const Color& _back)
559{
560        int width = Pic()->Width(); int height = Pic()->Height();
561        // たず、テキスト領域の広さを埗る
562        if (text == NULL) text = "";
563
564        TextGlyphStream gs = DefaultLayout(text_size)->Layout(text, width);
565
566        int x = 0, y = 0;
567        if (attribute & CENTER) {
568                x = (width - gs.width()) / 2;
569                y = (height - gs.height()) / 2;
570        }
571        int surf_x = Pic()->SurfacePosX();
572        int surf_y = Pic()->SurfacePosY();
573        Pic()->SetSurface( (Surface*)0,0,0);
574        root.DeleteSurface(surface);
575        surface = NULL;
576
577        //FIXME: (back.a == NULL) ?
578        if (back.a == 0) { // 背景なし
579                surface = root.NewSurface(width, height*2, ALPHA_MASK);
580                DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
581                if (attribute & REVERSE) {
582                        DSurfaceFill(surface, Rect(0,height,width,height*2), pressed.r, pressed.g, pressed.b, 0xff);
583                }
584                gs.SetColor(_fore.r, _fore.g, _fore.b);
585                DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), surface, Rect(x,y));
586                gs.SetColor(_pressed.r, _pressed.g, _pressed.b);
587                gs.SetReverse(true);
588                DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), surface, Rect(x,y+height));
589                gs.SetReverse(false);
590                nptn = 2;
591        } else {
592                /* ラベル甚の Surface を䜜る */
593                char* box = create_box(width, height, _back.r, _back.g, _back.b);
594                surface = root.NewSurfaceFromRGBAData(width, height*3, box, ALPHA_MASK);
595       
596                Surface* text_surface = root.NewSurface(width, height, ALPHA_MASK);
597                DSurfaceFill(text_surface, Rect(*text_surface), 0, 0, 0, 0);
598       
599                gs.SetColor(_fore.r, _fore.g, _fore.b);
600                DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), text_surface, Rect(x,y));
601                root.BlitSurface(text_surface, Rect(0,0,width,height), surface, Rect(0,0));
602                gs.SetColor(_pressed.r, _pressed.g, _pressed.b);
603                DSurfaceRenderText(gs.begin(), gs.end(), Rect(0,0,gs.width(),gs.height()), text_surface, Rect(x,y));
604                root.BlitSurface(text_surface, Rect(0,0,width,height), surface, Rect(0,height));
605                root.BlitSurface(text_surface, Rect(0,0,width,height), surface, Rect(0,height*2));
606                root.DeleteSurface(text_surface);
607        }
608
609        Pic()->SetSurface(surface, surf_x, surf_y);
610        show();
611}
612
613TextButton::~TextButton() {
614        if (surface) root.DeleteSurface(surface);
615        surface = NULL;
616}
617
618Text::Text(Event::Container& container, PicContainer* parent, const Rect& r, const Rect& text_r, int _fontsize) :
619        Event::Video(container),
620        Event::Time(container),
621        event(container),
622        srcrect(0,0,0,0),
623        layout(wdefault_font.c_str(), _fontsize), fontsize(_fontsize) {
624
625        SetPic(parent->create_node(r, 0));
626        surface = parent->Root().NewSurface(text_r.width(), text_r.height(), ALPHA_MASK);
627        pictext = PicNode()->create_leaf(text_r, PicBase::CACHE_BACK);
628        pictext->SetSurface(surface, 0, 0);
629        pictext->show();
630        cursor = 0;
631        cursor_activated = false;
632        window_activated = false;
633
634        event.RegisterGlobalPressFunc(&Pressed, (void*)this);
635
636        speed = 10;
637        wait_delay = -1;
638        status = PREPARE;
639        old_time = wait_starttime = 0;
640}
641
642Text::~Text() {
643        event.DeleteGlobalPressFunc(&Pressed, (void*)this);
644        PicNode()->Root().DeleteSurface(surface);
645}
646
647void Text::SetSpeed(int new_speed) {
648        speed = new_speed;
649}
650
651void Text::SetWait(int new_wait) {
652        if (new_wait < 0) new_wait = 100000000;
653        wait_delay = new_wait;
654}
655
656int Text::CalcScrollHeight(void) {
657        int i;
658        int len = bottom_pos.size();
659        int y0 = bottom_pos[line_number];
660        int height = Rect(*surface).height();
661        for (i=line_number; i<len; i++)
662                if (bottom_pos[i] - y0 > height) break;
663        if (i == line_number) i = line_number + 1;
664        return i - line_number - 1;
665}
666
667void Text::Elapsed(unsigned int current_time) {
668        SetWakeup(current_time + 50);
669        if (status == PREPARE) {
670                old_time = current_time;
671                return;
672        }
673        int nChar = speed * (current_time - old_time) / 1000;
674        if (speed == -1 || press_count) nChar = -1;
675        if (nChar == 0) return;
676        if (speed == -1) old_time = current_time;
677        else old_time += nChar * 1000 / speed;
678
679        switch(status) {
680        case WAIT: goto label_wait;
681        case SCROLL: goto label_scroll;
682        case DRAW2: goto label_draw2;
683        case WAIT2: goto label_wait2;
684        }
685
686        status = DRAW;
687        if (press_count) {
688                nChar = -1;
689                press_count = 0;
690        }
691        DrawText(nChar);
692        if (nChar == 0) return;
693        status = WAIT;
694        cursor_activated = true;
695        if (cursor_activated && window_activated && cursor) cursor->show();
696        wait_starttime = current_time;
697label_wait:
698        if (current_time < wait_starttime + wait_delay && press_count == 0) return;
699        press_count = 0;
700        nChar = 0;
701        cursor_activated = false;
702        if (cursor) cursor->hide();
703        while(cur_pos != gstream.end()) {
704                // スクロヌルしおは次行描画、を繰り返す
705                for (scroll_height = CalcScrollHeight(); scroll_height > 0; scroll_height--) {
706                        status = SCROLL;
707label_scroll:
708                        if (press_count) break;
709                        Scrollup(nChar);
710                        if (nChar == 0) return;
711                        status = DRAW2;
712label_draw2:
713                        if (press_count) break;
714                        DrawText(nChar);
715                        if (nChar == 0) return;
716                }
717                if (nChar != 0 && scroll_height) {
718                        nChar = 100000;
719                        if (status == SCROLL) Scrollup(nChar);
720                        DrawText(nChar);
721                        scroll_height--;
722                        for (; scroll_height > 0; scroll_height--) {
723                                Scrollup(nChar);
724                                DrawText(nChar);
725                        }
726                }
727                press_count = 0;
728                status = WAIT2;
729                cursor_activated = true;
730                if (cursor_activated && window_activated && cursor) cursor->show();
731                wait_starttime = current_time;
732label_wait2:
733                if (current_time < wait_starttime + wait_delay && press_count == 0) return;
734                press_count = 0;
735                nChar = 0;
736                cursor_activated = false;
737                if (cursor) cursor->hide();
738        }
739        status = PREPARE;
740}
741
742bool Text::Pressed(int x, int y, void* pointer) {
743        Text* wid = (Text*)pointer;
744        if (wid->Pic()->IsHidden()) return true;
745        wid->press_count++;
746        return true;
747}
748
749void Text::Clear(void) {
750        stream.container.clear();
751        DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
752        pictext->ReBlit();
753        status = PREPARE;
754}
755
756void Text::Flush(void) {
757        int nChar = -1;
758        DrawText(nChar);
759}
760
761void Text::Start(void) {
762        gstream.clear();
763        bottom_pos.clear();
764        layout.Layout(stream, gstream, bottom_pos, pictext->Width()-fontsize/2);
765
766        // height の積算倀ずしお bottom_pos を蚈算
767        std::vector<int>::iterator it;
768        int pos = 0;
769        for (it = bottom_pos.begin(); it != bottom_pos.end(); it++) {
770                pos += *it;
771                *it = pos;
772        }
773
774        cur_pos = gstream.begin();
775        line_number = 0;
776        scrolled_count = 0;
777        srcrect = Rect(0, 0, pictext->Width(), pictext->Height());
778        press_count = 0;
779
780        status = DRAW;
781        cursor_activated = false;
782        if (cursor) cursor->hide();
783}
784
785void Text::DrawText(int& nChar) {
786        // 描画範囲を埗る
787        iterator end = gstream.end();
788        iterator it = cur_pos;
789        while(nChar && it != end) { // nChar < 0 なら出来るだけの文字を描画
790                if (! (it->flag & TextGlyph::Group)) nChar--;
791                if (it->flag & TextGlyph::LineEnd) {
792                        if (bottom_pos[line_number+1] > srcrect.by) { //改行するず画面から出おしたう
793                                it++;
794                                if (nChar == 0) nChar = 1;
795                                break;
796                        }
797                        line_number++;
798                }
799                it++;
800        }
801        // 描画する
802        Rect r = DSurfaceRenderText(cur_pos, it, srcrect, surface, Rect(0,0,0,0));
803        pictext->ReBlit(r);
804        cur_pos = it;
805}
806
807void Text::Scrollup(int& nChar) {
808        if (nChar < 0) { // 䞀画面分スクロヌルする
809                DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
810                pictext->ReBlit();
811                srcrect = Rect(*surface);
812                srcrect.rmove(0, bottom_pos[line_number]);
813                line_number++;
814                scrolled_count = 0;
815                return;
816        }
817        // スクロヌル幅を求める
818        const int max_scroll_count = 8;
819        int dy = bottom_pos[line_number+1] - bottom_pos[line_number];
820        int cur_dy;
821        if (scrolled_count+nChar >= max_scroll_count) {
822                cur_dy = dy - (scrolled_count*dy/max_scroll_count);
823                nChar -= max_scroll_count-scrolled_count;
824                nChar++;
825                scrolled_count = 0;
826                line_number++;
827                srcrect.rmove(0, dy);
828        } else {
829                cur_dy = (scrolled_count+nChar)*dy/max_scroll_count;
830                cur_dy -=(scrolled_count*dy/max_scroll_count);
831                scrolled_count += nChar;
832                nChar = 0;
833        }
834        Rect r(*surface);
835        DSurfaceMove(surface, r, surface, Rect(0, -cur_dy, 0, 0));
836        r.ty = r.by-cur_dy;
837        DSurfaceFill(surface, r, 0, 0, 0, 0);
838        pictext->ReBlit();
839}
840
841void Text::activate(void) {
842        event.RegisterGlobalPressFunc(&Pressed, (void*)this);
843        Event::Video::activate();
844        window_activated = true;
845        if (cursor_activated && window_activated && cursor) cursor->show();
846}
847
848void Text::deactivate(void) {
849        event.DeleteGlobalPressFunc(&Pressed, (void*)this);
850        Event::Video::deactivate();
851        window_activated = false;
852        if (cursor) cursor->hide();
853}
854
855void Text::SetCursor(TimeCursor* c) {
856        cursor = c;
857        if (c) {
858                if (cursor_activated && window_activated) c->show();
859                else c->hide();
860        }
861}
862
863Label::Label(PicContainer* parent, const Rect& r_orig, bool _is_center, const char* text, int _text_size) :
864        is_center(_is_center),
865        root(parent->Root()),
866        text_size(_text_size) {
867        Rect r(r_orig);
868
869        if (text == NULL) text = "";
870        int width = r.width();
871        int height = r.height();
872        if (width == 0) width = parent->Width() - r.lx;
873
874        TextGlyphStream gs = DefaultLayout(text_size)->Layout(text, width);
875
876        if (r.width() == 0) { // 文字に合わせおりィゞット䜜成
877                width = gs.width();
878                r.rx = r.lx + gs.width();
879        }
880        if (r.height() == 0) {
881                r.by = r.ty + gs.height();
882        }
883
884        SetPic(parent->create_leaf(r, 0));
885
886        /* ラベル甚の Surface を䜜る */
887        surface = parent->Root().NewSurface(r.width(), r.height(), ALPHA_MASK);
888       
889        DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
890        int x = 0, y = 0;
891        if (is_center) {
892                x = (Pic()->Width() - gs.width()) / 2;
893                y = (Pic()->Height() - gs.height()) / 2;
894        }
895
896        DSurfaceRenderText(gs.begin(), gs.end(), Rect(*surface), surface, Rect(x,y));
897
898        Pic()->SetSurface(surface, 0, 0);
899        show();
900}
901
902Label::~Label() {
903        root.DeleteSurface(surface);
904}
905
906void Label::SetText(const char* text) {
907        if (text == NULL) text = "";
908        TextGlyphStream gs = DefaultLayout(text_size)->Layout(text, Pic()->Width());
909        DSurfaceFill(surface, Rect(*surface), 0, 0, 0, 0);
910        int x = 0, y = 0;
911        if (is_center) {
912                x = (Pic()->Width() - gs.width()) / 2;
913                y = (Pic()->Height() - gs.height()) / 2;
914        }
915
916        DSurfaceRenderText(gs.begin(), gs.end(), Rect(*surface), surface, Rect(x,y));
917        Pic()->ReBlit();
918}
919
920Dialog::Dialog(Event::Container& container, PicContainer* parent, const char* text, bool with_cancel) :
921        Event::Video(container) {
922
923        int x,y;
924        status = WAIT;
925        set_func = NULL;
926        set_pointer = NULL;
927
928        XKFont::HorizLayout& layout = *DefaultLayout(26);
929        int dialog_width = parent->Width() / 2;
930        TextGlyphStream s_ok = layout.Layout("", dialog_width);
931        TextGlyphStream s_cancel = layout.Layout("取消", dialog_width);
932        TextGlyphStream s_text = layout.Layout(text, dialog_width);
933
934        Rect r_text(0, 0, s_text.width(), s_text.height());
935        Rect r_ok(0, 0, s_ok.width(), s_ok.height());
936        Rect r_cancel(0, 0, s_cancel.width(), s_cancel.height());
937
938        /* ダむアログボックスの Surface を䜜る */
939        int dwidth = r_text.width() + (r_text.width()/10)*2 + 6;
940        int dheight = r_text.height() + r_ok.height() + r_cancel.height()*3 + 4;
941        surface_diag = parent->Root().NewSurface(dwidth, dheight, NO_MASK); // alpha なし
942        DSurfaceFill(surface_diag, Rect(*surface_diag), 0xf0, 0xd0, 0xa0);
943        DrawBox(surface_diag, Rect(0,0,dwidth,dheight));
944
945        Surface* surface_text = parent->Root().NewSurface(r_text.width(), r_text.height(), ALPHA_MASK);
946        s_text.SetColor(0x38, 0x20, 0x18);
947        DSurfaceRenderText(s_text.begin(), s_text.end(), r_text, surface_text, Rect(0, 0, 0, 0));
948        x = r_text.width()/10 + 3;
949        y = r_cancel.height()+2;
950        parent->Root().BlitSurface(surface_text, r_text, surface_diag, Rect(x, y, x+r_text.width(), y+r_text.height()));
951        parent->Root().DeleteSurface(surface_text);
952
953        /* panel を぀くる */
954        x = (parent->Width()-dwidth)/2;
955        y = (parent->Height()-dheight)/2;
956        SetPic(parent->create_node(Rect(x, y, x+dwidth, y+dheight), 0));
957
958        /* ボタンを䜜成する */
959        /* f8d8c8 背景(明)*/
960        /* f0d0a0 背景*/
961        /* b08040 枠明)*/
962        /* 805010 枠*/
963        /* 382018 黒*/
964        /* 9890f8 青*/ 
965        /* dc6448 èµ€*/
966        /* 各ボタンは巊右にボタン幅の 1/4, 䞊䞋にボタン幅の 1/4 のマヌゞンを持぀ */
967        Rect r_btn(r_ok); r_btn.join(r_cancel);
968        int btn_width = r_btn.width() * 3 / 2;
969        int btn_height = r_btn.height() * 3 / 2;
970        surface_btn = parent->Root().NewSurface(btn_width, btn_height*4, ALPHA_MASK);
971        DSurfaceFill(surface_btn, Rect(*surface_btn), 0, 0, 0, 0);
972        s_ok.SetColor(0x38, 0x20, 0x18);
973        DSurfaceRenderText(s_ok.begin(), s_ok.end(), r_ok, surface_btn, Rect( (btn_width-r_ok.width())/2,(btn_height-r_ok.height())/2));
974        s_ok.SetColor(0x98, 0x90, 0xf8);
975        DSurfaceRenderText(s_ok.begin(), s_ok.end(), r_ok, surface_btn, Rect( (btn_width-r_ok.width())/2,(btn_height-r_ok.height())/2 + btn_height));
976        s_cancel.SetColor(0x38, 0x20, 0x18);
977        DSurfaceRenderText(s_cancel.begin(), s_cancel.end(), r_cancel, surface_btn, Rect( (btn_width-r_cancel.width())/2,(btn_height-r_cancel.height())/2 + btn_height*2));
978        s_cancel.SetColor(0xdc, 0x64, 0x48);
979        DSurfaceRenderText(s_cancel.begin(), s_cancel.end(), r_cancel, surface_btn, Rect( (btn_width-r_cancel.width())/2,(btn_height-r_cancel.height())/2 + btn_height*3));
980
981        x = (dwidth - btn_width*2) / 3;;
982        y = r_cancel.height()*3/2 + r_text.height() + 2;
983        if (!with_cancel) x = (dwidth - btn_width) / 2;
984        Button* b_ok = new Button(container, PicNode(), surface_btn, 0, 0, 0, btn_height, 2, Rect(x, y, x+btn_width, y+btn_height), 1);
985        DrawBox(surface_diag, Rect(x-3,y-2,x+btn_width+3,y+btn_height+2));
986        b_ok->press_pointer = (void*)this;
987        b_ok->press_func = &press_ok;
988        if (with_cancel) {
989                x += x + btn_width;
990                Button* b_cancel = new Button(container, PicNode(), surface_btn, 0, btn_height*2, 0, btn_height, 2, Rect(x, y, x+btn_width, y+btn_height), 1);
991                DrawBox(surface_diag, Rect(x-3,y-2,x+btn_width+3,y+btn_height+2));
992                b_cancel->press_pointer = (void*)this;
993                b_cancel->press_func = &press_cancel;
994        }
995
996        Pic()->SetSurface(surface_diag, 0, 0);
997        Pic()->ZMove(ZMOVE_TOP);
998
999        show_all();
1000}
1001
1002Dialog::~Dialog() {
1003        PicRoot& root = PicNode()->Root();
1004        SetPic(NULL);
1005        root.DeleteSurface(surface_btn);
1006        root.DeleteSurface(surface_diag);
1007}
1008
1009void Dialog::press_ok(void* pointer, Button* btn) {
1010        if (pointer) {
1011                Dialog* wid = (Dialog*)pointer;
1012                wid->status = OK;
1013                if (wid->set_func) {
1014                        (*wid->set_func)(wid->set_pointer, wid);
1015                }
1016        }
1017}
1018
1019void Dialog::press_cancel(void* pointer, Button* btn) {
1020        if (pointer) {
1021                Dialog* wid = (Dialog*)pointer;
1022                wid->status = CANCEL;
1023                if (wid->set_func) {
1024                        (*wid->set_func)(wid->set_pointer, wid);
1025                }
1026        }
1027}
1028
1029void Dialog::DrawBox(Surface* s, const Rect& r) {
1030        DSurfaceFill(s, Rect(r.lx, r.ty, r.rx, r.ty+1), 0x80, 0x50, 0x10);
1031        DSurfaceFill(s, Rect(r.lx, r.ty+1, r.rx, r.ty+2), 0x38, 0x20, 0x18);
1032        DSurfaceFill(s, Rect(r.lx, r.by-2, r.rx, r.by-1), 0x80, 0x50, 0x10);
1033        DSurfaceFill(s, Rect(r.lx, r.by-1, r.rx, r.by), 0x38, 0x20, 0x18);
1034
1035        DSurfaceFill(s, Rect(r.lx, r.ty, r.lx+1, r.by), 0xb0, 0x80, 0x40);
1036        DSurfaceFill(s, Rect(r.lx+1, r.ty+1, r.lx+2, r.by-1), 0x80, 0x50, 0x10);
1037        DSurfaceFill(s, Rect(r.lx+1, r.ty+2, r.lx+2, r.by-2), 0x38, 0x20, 0x18);
1038        DSurfaceFill(s, Rect(r.rx-3, r.ty+2, r.rx-2, r.by-2), 0xb0, 0x80, 0x40);
1039        DSurfaceFill(s, Rect(r.rx-2, r.ty+1, r.rx-1, r.by-1), 0x80, 0x50, 0x10);
1040        DSurfaceFill(s, Rect(r.rx-1, r.ty, r.rx, r.by), 0x38, 0x20, 0x18);
1041}
1042
1043AnmTime::AnmTime(Event::Container& container, PicBase* _pic, int _total_time, int _all_count) :
1044        Event::Time(container),
1045        PicAnm(_pic), start_time(0), total_time(_total_time), all_count(_all_count) {
1046        status = FINISHED;
1047        if (total_time == 0) total_time = 1;
1048}
1049
1050AnmTime::AnmTime(Event::Container& container, std::vector<PicBase*> _pic, int _total_time, int _all_count) :
1051        Event::Time(container),
1052        PicAnm(_pic), start_time(0), total_time(_total_time), all_count(_all_count) {
1053        status = FINISHED;
1054        if (total_time == 0) total_time = 1;
1055}
1056
1057void AnmTime::Elapsed(unsigned int current_time) {
1058        if (total_time == 0) return;
1059        if (status == FINISHED || current_time == 0) {SetWakeup(current_time+1); return;}
1060        if (start_time == 0) {
1061                start_time = current_time;
1062                Start();
1063        }
1064        unsigned int time_elapsed = current_time - start_time;
1065        if (time_elapsed < total_time) {
1066                int count = time_elapsed * all_count / total_time;
1067                Exec(count);
1068                int next_time = start_time + (count+1) * total_time / all_count;
1069                SetWakeup(next_time);
1070        } else {
1071                Exec(all_count);
1072                Finish();
1073                status = FINISHED;
1074        }
1075}
1076
1077void AnmTime::Abort(void) { 
1078        if (status == FINISHED) return;
1079        if (start_time == 0) {
1080                Start();
1081                Exec(all_count);
1082        }
1083        if (total_time) {
1084                Finish();
1085        }
1086        status = FINISHED;
1087}
1088
1089bool AnmTime::IsEnd(void) {
1090        return status == FINISHED;
1091}
1092
1093AnmMove::AnmMove(Event::Container& container, PicBase* _pic, const Rect& _to, int total_time) :
1094        AnmTime(container, _pic, total_time),
1095        from(0,0), to(_to) {
1096        from.lx = _pic->PosX();
1097        from.ty = _pic->PosY();
1098        from.rx = from.lx + _pic->Width();
1099        from.by = from.ty + _pic->Height();
1100
1101        int dx = to.lx - from.lx;
1102        int dy = to.ty - from.ty;
1103        if (dx < 0) dx = -dx;
1104        if (dy < 0) dy = -dy;
1105        if (dx < dy) dx = dy;
1106        if (dx == 0) dx = 1;
1107        SetAllCount(dx);
1108}
1109
1110void AnmMove::Exec(int count) {
1111        Rect r(from);
1112        int dx = to.lx - from.lx;
1113        int dy = to.ty - from.ty;
1114        r.rmove(dx*count/all_count, dy*count/all_count);
1115        iterator it;
1116        for (it=pic.begin(); it!=pic.end(); it++)
1117                (*it)->Move(r.lx, r.ty);
1118}
1119
1120AnmAlpha::AnmAlpha(Event::Container& container, PicBase* _pic, int alpha_from, int alpha_to, int total_time) :
1121        AnmTime(container, _pic, total_time),
1122        from(alpha_from), to(alpha_to), alpha_r(0,0,1,1) {
1123        if (from < 0) from = 0;
1124        if (from >= ALPHA_MAX) from = ALPHA_MAX;
1125        if (to < 0) to = 0;
1126        if (to >= ALPHA_MAX) to = ALPHA_MAX;
1127        int c = from - to;     
1128        if (c < 0) c = -c;
1129        if (c == 0) c = 1;
1130        SetAllCount(c);
1131}
1132
1133AnmAlpha::AnmAlpha(Event::Container& container, std::vector<PicBase*> _pic, int alpha_from, int alpha_to, int total_time) :
1134        AnmTime(container, _pic, total_time),
1135        from(alpha_from), to(alpha_to), alpha_r(0,0,1,1) {
1136        if (from < 0) from = 0;
1137        if (from >= ALPHA_MAX) from = ALPHA_MAX;
1138        if (to < 0) to = 0;
1139        if (to >= ALPHA_MAX) to = ALPHA_MAX;
1140        int c = from - to;     
1141        if (c < 0) c = -c;
1142        if (c == 0) c = 1;
1143        SetAllCount(c);
1144}
1145
1146void AnmAlpha::Start(void) {
1147        iterator it;
1148        for (it=pic.begin(); it!=pic.end(); it++)
1149                (*it)->show();
1150}
1151
1152void AnmAlpha::Exec(int count) {
1153        alpha = (from * (all_count-count) + (to-from) * count) / all_count;
1154        iterator it;
1155        for (it=pic.begin(); it!=pic.end(); it++)
1156                (*it)->SetSurfaceAlpha(&alpha, alpha_r);
1157}
1158
1159void AnmAlpha::Finish(void) {
1160        iterator it;
1161        for (it=pic.begin(); it!=pic.end(); it++) {
1162                if (to == 0) (*it)->hide();
1163                else if (to != ALPHA_MAX) fprintf(stderr,"Warning in AnmAlpha::Finish: alpha value suddenly changed.\n");
1164                (*it)->SetSurfaceAlpha(0,Rect(0,0));
1165        }
1166}
1167
1168AnmAlphaMove::AnmAlphaMove(Event::Container& container, PicBase* _pic) :
1169        AnmTime(container, _pic, 0) {
1170}
1171
1172void AnmAlphaMove::SetPtn(void) {
1173        int total = 0;
1174        std::vector<Ptn>::iterator it;
1175        for (it=ptns.begin(); it!=ptns.end(); it++) {
1176                if (total < it->next_tick) total = it->next_tick;
1177        }
1178        SetAllCount(total);
1179        SetTotalTime(total);
1180        cur_count = 0;
1181}
1182
1183void AnmAlphaMove::Exec(int count) {
1184        if (ptns.empty()) return;
1185        if (cur_count != 0 && ptns[cur_count].next_tick > count) return;
1186        if (cur_count >= ptns.size()) return;
1187        // 次のパタヌンを探す
1188        // count <= it->next_tick なる条件を満たす最埌の it を探す
1189        std::vector<Ptn>::iterator it;
1190        for (it=ptns.begin()+cur_count; it != ptns.end(); it++) {
1191                if (count <= it->next_tick) break;
1192        }
1193        if (it == ptns.end()) {
1194                fprintf(stderr,"end\n");
1195                it = ptns.end() - 1;
1196        }
1197        cur_count = it - ptns.begin();
1198
1199        iterator p;
1200        for (p=pic.begin(); p!=pic.end(); p++) {
1201                // move
1202                (*p)->Move(it->pos.lx, it->pos.ty);
1203                (*p)->SetSurfacePos(it->surface_pos.lx, it->surface_pos.ty);
1204                // alpha set
1205                if (it->alpha == 0) (*p)->hide();
1206                else if (it->alpha == ALPHA_MAX) { (*p)->show(); (*p)->SetSurfaceAlpha(0, Rect(0,0)); }
1207                else { (*p)->show(); (*p)->SetSurfaceAlpha( &(it->alpha), Rect(0,0,1,1)); }
1208        }
1209}
1210
1211void AnmAlphaMove::Finish(void) {
1212        if (ptns.empty()) return;
1213        if (cur_count >= ptns.size() - 1) return;
1214        cur_count = ptns.size() - 1;
1215        Exec(ptns[cur_count].next_tick); // 最埌の pattern の状態にする
1216}
1217
1218AnmPtnSolid::AnmPtnSolid(Event::Container& container, PicBase* _pic, const unsigned char* _ptn, const Rect& _alpha_r, int total_time) :
1219        AnmTime(container, _pic, total_time),
1220        ptn(_ptn), alpha_r(_alpha_r)
1221{
1222        ptn_len = alpha_r.width() * alpha_r.height();
1223        alpha = new unsigned char[ptn_len];
1224        int max_a = 0;
1225        for (int i=0; i<ptn_len; i++) {
1226                if (ptn[i] > max_a) max_a = ptn[i];
1227        }
1228        if (max_a == 0) max_a = 1;
1229        SetAllCount(max_a);
1230}
1231
1232AnmPtnAlpha::AnmPtnAlpha(Event::Container& container, PicBase* _pic, const unsigned char* _ptn, const Rect& _alpha_r, int _band_width, int total_time) :
1233        AnmTime(container, _pic, total_time),
1234        ptn(_ptn), band(_band_width), alpha_r(_alpha_r)
1235{
1236        ptn_len = alpha_r.width() * alpha_r.height();
1237        alpha = new unsigned char[ptn_len];
1238        if (band <= 0) band = 1;
1239        SetAllCount(ALPHA_MAX+band);
1240}
1241
1242void AnmPtnSolid::Exec(int count) {
1243        int i;
1244        for (i=0; i<ptn_len; i++) {
1245                if (ptn[i] <= count) alpha[i] = ALPHA_MAX;
1246                else alpha[i] = 0;
1247        }
1248        iterator it;
1249        for (it=pic.begin(); it!=pic.end(); it++)
1250                (*it)->SetSurfaceAlpha(alpha, alpha_r);
1251}
1252
1253void AnmPtnAlpha::Exec(int count) {
1254        int i;
1255        int ptn_zero = count;
1256        int ptn_max = count - band;
1257        for (i=0; i<ptn_len; i++) {
1258                if (ptn[i] >= ptn_zero) alpha[i] = 0;
1259                else if (ptn[i] < ptn_max) alpha[i] = ALPHA_MAX;
1260                else alpha[i] = (ptn_zero-ptn[i])*ALPHA_MAX/band;
1261        }
1262        iterator it;
1263        for (it=pic.begin(); it!=pic.end(); it++) (*it)->SetSurfaceAlpha(alpha, alpha_r);
1264}
1265
1266void AnmPtnSolid::Start(void) {
1267        iterator it;
1268        for (it=pic.begin(); it!=pic.end(); it++)
1269                (*it)->show();
1270}
1271
1272void AnmPtnSolid::Finish(void) {
1273        iterator it;
1274        for (it=pic.begin(); it!=pic.end(); it++)
1275                (*it)->SetSurfaceAlpha(0, Rect(0,0));
1276}
1277
1278void AnmPtnAlpha::Start(void) {
1279        iterator it;
1280        for (it=pic.begin(); it!=pic.end(); it++)
1281                (*it)->show();
1282}
1283
1284void AnmPtnAlpha::Finish(void) {
1285        iterator it;
1286        for (it=pic.begin(); it!=pic.end(); it++) (*it)->SetSurfaceAlpha(0, Rect(0,0));
1287}
1288
1289/*
1290
1291Widget の皮類
1292        Mouse: マりス䜍眮に連動する。Surface ず origin が必須
1293        Panel : なにも存圚しないずころに匵り぀けおいく
1294                背景匵り぀けも可胜
1295                ButtonPanel : 無効化可胜。Group の Button がカヌ゜ルに入ったら、党Button / Label が「カヌ゜ル䞋」状態になる
1296                        同䞀倉数を扱うボタンは原則、同䞀ButtonPanel の䞋に入るこず同期する。高速化可胜
1297                        そうでない堎合、ボタンの GlobalVariable フラグを立おる必芁がある
1298                背景皮類Window
1299                        内郚の透明床ず枠圢を別々に指定可胜。枠圢は党枠、郚分枠どちらの圢でも可胜
1300                        郚分枠なら、内郚的には䞊枠、䞋枠、巊右枠ず別 Surface で管理する
1301                DragButton
1302                        Panel 党䜓をドラッグし、堎所倉曎できるボタン。
1303        Button: 無効化通垞カヌ゜ル䞋ボタン抌䞋 のpicture / animation
1304                Toggle Button にできる(Group化すればRadioButtonにもできる)
1305        Label : 無効化通垞カヌ゜ル䞋 のanimation
1306                animation は
1307                ・䞊ぞの倉化
1308                ・䞋ぞの倉化
1309                ・垞時倉圢
1310                の぀の圢匏をも぀。
1311                圢匏は
1312                ・x / y increment による党領域ず x,y の倧きさを指定するず巊䞊から右䞊、巊䞋、ずいう方ぞ勝手に領域を倉曎しおいく
1313                ・色倉化明床倉化。色テヌブルを指定する。Surface は alpha のみずする
1314                        どちらも、䞀぀のラベルに䜿う時間の長さを指定する
1315                ・callback による。指定した䞀定時間以䞊が立぀ずCallBack が呌び出され、新たなSurface , origin を指定する。
1316
1317                ・Surface は
1318                        普通の画像
1319                        文字列適圓に仮想化
1320                        画像数倀列
1321                のいずれか
1322        Cursor
1323                リタヌンカヌ゜ル。Label の䞀皮。
1324        Number
1325                数字を衚瀺する。フォントの倧きさ、もしくは画像数倀列
1326        Text
1327                テキストを衚瀺する
1328                パネルの倧きさだけ指定するず適圓にやっおくれる
1329                カヌ゜ルの䜍眮文字の次/最終を指定するこず
1330                機胜文字送り速床蚭定、読み飛ばし蚭定垞に最高速で抌しっぱなし
1331        ProgressBar など
1332                バヌの長さ、あるいは䜍眮で倉数の倧きさを瀺す。
1333                Tick, Max を指定、倉数の倉化には適圓に察応できるようにする
1334                バヌの方向ずしお瞊/暪。Surface は繰り返しで䜿う速床䞊、32pixel くらいあったほうがいいかも
1335                バヌの代わりにボタンも䜿える。Surface 指定のメ゜ッドが違うだけ。
1336                オプションバヌのどこかをクリックされたずき、そこに移動するかそこに向かっお移動するか
1337                オプション矢印ボタンいらないか
1338        ScrollBar
1339                暪/瞊。Panel ず連動する(専甚, ProgressBar の䞀皮ずしお実装)
1340                (Panel 偎で「芋えない郚分はdelete, 芋える郚分は自動で䜜成」機胜を぀けるバックログ
1341
1342       
1343       
1344メニュヌの出し方
1345        右クリック
1346        ボタンを抌す
1347        䞊の方、右の方など領域に行くずヌっず出おくる
1348メニュヌモヌド内
1349        ボタンを抌しお終了
1350        マップを䜜っおおき、各メニュヌに名前を割り振るず二次元に広がったメニュヌになる
1351        名前を割り振るず䞊に名前リストがでおくる
1352        名前を割り振るず暪に名前リストが出おくる
1353
1354*/
1355// }
Note: See TracBrowser for help on using the browser.