Subversion Repositories freemyipod

Rev

Rev 826 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
824 theseven 1
//
2
//
3
//    Copyright 2011 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "emcorelib.h"
25
#include "libui.h"
26
#include "settingchooser.h"
27
#include "chooser.h"
28
#include "chooser_renderer_list.h"
29
#include "chooser_action_handler_wheel.h"
30
 
31
 
32
static bool settingchooser_event_filter(struct chooser_data* data, enum button_event event,
33
                                        int which, int value)
34
{
35
    struct settingchooser_data* state = (struct settingchooser_data*)data->info->userparams;
36
    struct settingchooser_info* info = (struct settingchooser_info*)state->info;
37
    struct settingchooser_item* item = (struct settingchooser_item*)data->selected->user;
38
    struct chooser_renderer_list_itemdata* rp;
39
    rp = (struct chooser_renderer_list_itemdata*)data->selected->renderparams;
827 theseven 40
    int change = 0;
824 theseven 41
    bool redraw = false;
42
    bool handled = false;
43
    bool setcolors = false;
44
    switch (event)
45
    {
46
        case BUTTON_PRESS:
47
            switch (which)
48
            {
49
                case 0:
826 theseven 50
                case 1:
824 theseven 51
                    switch (item->type)
52
                    {
53
                        case SETTINGCHOOSER_TYPE_INTEGER:
54
                            handled = true;
55
                            setcolors = true;
56
                            state->editing = !state->editing;
57
                            if (state->editing) state->collect = 0;
58
                            break;
59
                    }
60
                    break;
61
 
62
                case 2:
63
                    if (state->editing)
64
                    {
65
                        handled = true;
66
                        setcolors = true;
67
                        state->editing = false;
68
                    }
69
                    break;
827 theseven 70
 
71
                case 3:
72
                    if (state->editing)
73
                    {
74
                        handled = true;
75
                        change = -128;
76
                    }
77
                    break;
78
 
79
                case 4:
80
                    if (state->editing)
81
                    {
82
                        handled = true;
83
                        change = 128;
84
                    }
85
                    break;
824 theseven 86
 
87
                default:
88
                    handled = state->editing;
89
                    break;
90
            }
91
            break;
92
 
93
        case WHEEL_MOVED_ACCEL:
94
            if (state->editing)
95
            {
96
                switch (item->type)
97
                {
98
                    case SETTINGCHOOSER_TYPE_INTEGER:
99
                        handled = true;
827 theseven 100
                        change = value;
824 theseven 101
                        break;
102
                }
103
            }
104
            break;
105
    }
827 theseven 106
    if (change)
107
    {
108
        state->collect += change;
109
        change = (state->collect * item->config.integer.step) / 128;
110
        if (change)
111
        {
112
            state->collect -= (change * 128) / item->config.integer.step;
113
            int* setting = (int*)item->setting;
114
            if (*setting + change < item->config.integer.min)
115
                *setting = item->config.integer.min;
116
            else if (*setting + change > item->config.integer.max)
117
                *setting = item->config.integer.max;
118
            else *setting += change;
119
            if (item->validator) item->validator(item->setting);
120
            state->changed = true;
121
            redraw = true;
122
        }
123
    }
824 theseven 124
    if (setcolors)
125
    {
126
        if (state->editing)
127
        {
128
            rp->fill_color_selected = info->itemparams.fill_color_active;
129
            rp->text_color_selected = info->itemparams.text_color_active;
130
            rp->icon_selected_opacity = info->itemparams.icon_active_opacity;
131
        }
132
        else
133
        {
134
            rp->fill_color_selected = info->itemparams.fill_color_selected;
135
            rp->text_color_selected = info->itemparams.text_color_selected;
136
            rp->icon_selected_opacity = info->itemparams.icon_selected_opacity;
137
        }
138
        redraw = true;
139
    }
140
    if (redraw)
141
    {
142
        mutex_lock(&data->statemutex, TIMEOUT_BLOCK);
143
        data->redrawneeded = true;
144
        wakeup_signal(&data->eventwakeup);
145
        mutex_unlock(&data->statemutex);
146
    }
147
    return handled;
148
}
149
 
150
static struct chooser_action_handler_wheel_params settingchooser_aparams =
151
{
152
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
153
    .stepsperitem = 128,
154
    .eventfilter = settingchooser_event_filter,
155
    .timeout_initial = TIMEOUT_BLOCK,
156
    .timeout_idle = TIMEOUT_BLOCK,
157
    .timeout_item = 0,
158
    .tick_force_redraw = true,
159
    .buttoncount = 5,
160
    .buttonmap =
161
    {
162
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
826 theseven 163
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
824 theseven 164
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_CANCEL,
165
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
166
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
167
    }
168
};
169
static struct chooser_action_handler_wheel_params settingchooser_aparams2 =
170
{
171
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
172
    .stepsperitem = 128,
173
    .eventfilter = NULL,
174
    .timeout_initial = TIMEOUT_BLOCK,
175
    .timeout_idle = TIMEOUT_BLOCK,
176
    .timeout_item = 0,
177
    .tick_force_redraw = true,
178
    .buttoncount = 5,
179
    .buttonmap =
180
    {
181
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
826 theseven 182
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
824 theseven 183
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_CANCEL,
184
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
185
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
186
    }
187
};
188
 
189
static void settingchooser_render_preview(struct chooser_data* data,
190
                                          const struct chooser_item* item,
191
                                          bool selected, int x, int y)
192
{
193
    struct settingchooser_item* itemdata = (struct settingchooser_item*)item->user;
194
    int value = *((int*)itemdata->setting);
195
    const char* str = NULL;
196
    char buf[16];
197
    switch (itemdata->type)
198
    {
199
        case SETTINGCHOOSER_TYPE_INTEGER:
200
            if (itemdata->config.integer.tostring)
201
                itemdata->config.integer.tostring(buf, sizeof(buf), itemdata->setting, value);
202
            else snprintf(buf, sizeof(buf), "%d", value);
203
            str = buf;
204
            break;
205
 
206
        case SETTINGCHOOSER_TYPE_SELECT:
207
            if (value < itemdata->config.select.options->optioncount)
208
                str = itemdata->config.select.options->options[value].preview;
209
            break;
210
    }
211
    if (str) chooser_renderer_list_render_attached_text(data, item, selected, x, y, str);
212
}
213
 
214
static void settingchooser_populate_rp(const struct settingchooser_info* info,
215
                                       struct chooser_renderer_list_itemdata* rp)
216
{
217
    rp->size = info->itemparams.size;
218
    rp->fill_box = info->itemparams.fill_box;
219
    rp->fill_color = info->itemparams.fill_color;
220
    rp->fill_color_selected = info->itemparams.fill_color_selected;
221
    rp->icon_pos = info->itemparams.icon_pos;
222
    rp->icon_opacity = info->itemparams.icon_opacity;
223
    rp->icon_selected_opacity = info->itemparams.icon_selected_opacity;
224
    rp->text_pos = info->itemparams.text_pos;
225
    rp->text_color = info->itemparams.text_color;
226
    rp->text_color_selected = info->itemparams.text_color_selected;
227
}
228
 
229
bool settingchooser_run(const struct settingchooser_info* info)
230
{
231
    int i;
232
    bool rc = false;
233
    struct chooser_renderer_list_itemdata* rp;
234
    if (info->version != SETTINGCHOOSER_INFO_VERSION) return false;
235
    int allocsize = sizeof(struct settingchooser_data)
236
                  + sizeof(struct chooser_info)
237
                  + sizeof(struct chooser_item) * (info->itemcount + 1)
238
                  + sizeof(struct chooser_renderer_list_itemdata) * (info->itemcount + 1);
239
    void* mem = malloc(allocsize);
240
    if (!mem) return false;
241
    memset(mem, 0, allocsize);
242
    void* ptr = mem;
243
    struct settingchooser_data* data = (struct settingchooser_data*)ptr;
244
    ptr += sizeof(struct settingchooser_data);
245
    struct chooser_info* chooser = (struct chooser_info*)ptr;
246
    ptr += sizeof(struct chooser_info);
247
    ptr += sizeof(struct chooser_item) * (info->itemcount + 1);
248
    for (i = 0; i < info->itemcount + 1; i++)
249
    {
250
        chooser->items[i].renderparams = (struct chooser_renderer_list_itemdata*)ptr;
251
        ptr += sizeof(struct chooser_renderer_list_itemdata);
252
    }
253
    data->info = info;
254
    chooser->version = CHOOSER_INFO_VERSION;
255
    chooser->actionhandler = &chooser_action_handler_wheel;
256
    chooser->actionhandlerparams = &settingchooser_aparams;
257
    chooser->renderer = &chooser_renderer_list;
258
    chooser->rendererparams = &info->rendererparams;
259
    chooser->userparams = data;
260
    chooser->tickinterval = info->tickinterval;
261
    chooser->itemcount = info->itemcount + 1;
262
    rp = (struct chooser_renderer_list_itemdata*)chooser->items[0].renderparams;
263
    settingchooser_populate_rp(info, rp);
264
    rp->text = info->returntext;
265
    rp->render = chooser_renderer_list_show_arrow_left;
266
    for (i = 0; i < info->itemcount; i++)
267
    {
268
        chooser->items[i + 1].user = &info->items[i];
269
        rp = (struct chooser_renderer_list_itemdata*)chooser->items[i + 1].renderparams;
270
        settingchooser_populate_rp(info, rp);
271
        rp->text = info->items[i].text;
272
        rp->icon = info->items[i].icon;
273
        rp->icon_selected = info->items[i].icon_selected;
274
        rp->render = settingchooser_render_preview;
275
    }
276
    while (true)
277
    {
278
        const struct chooser_item* result = chooser_run(chooser);
279
        if (!result) break;
280
        struct settingchooser_item* item = (struct settingchooser_item*)result->user;
281
        if (!item) break;
282
        chooser->defaultitem = result - chooser->items;
283
        const struct settingchooser_select_options* options = item->config.select.options;
284
        int allocsize2 = sizeof(struct chooser_info)
285
                       + sizeof(struct chooser_item) * (options->optioncount + 1)
286
                       + sizeof(struct chooser_renderer_list_itemdata)
287
                       * (options->optioncount + 1);
288
        void* mem2 = malloc(allocsize2);
289
        if (!mem2) continue;
290
        memset(mem2, 0, allocsize2);
291
        void* ptr = mem2;
292
        struct chooser_info* chooser2 = (struct chooser_info*)ptr;
293
        ptr += sizeof(struct chooser_info);
294
        ptr += sizeof(struct chooser_item) * (options->optioncount + 1);
295
        for (i = 0; i < options->optioncount + 1; i++)
296
        {
297
            chooser2->items[i].renderparams = (struct chooser_renderer_list_itemdata*)ptr;
298
            ptr += sizeof(struct chooser_renderer_list_itemdata);
299
        }
300
        chooser2->version = CHOOSER_INFO_VERSION;
301
        chooser2->actionhandler = &chooser_action_handler_wheel;
302
        chooser2->actionhandlerparams = &settingchooser_aparams;
303
        chooser2->renderer = &chooser_renderer_list;
304
        chooser2->rendererparams = &info->rendererparams;
305
        chooser2->userparams = data;
306
        chooser2->tickinterval = info->tickinterval;
307
        chooser2->itemcount = options->optioncount + 1;
308
        chooser2->defaultitem = *((int*)item->setting) + 1;
309
        rp = (struct chooser_renderer_list_itemdata*)chooser2->items[0].renderparams;
310
        settingchooser_populate_rp(info, rp);
311
        rp->text = "Cancel";
312
        rp->render = chooser_renderer_list_show_arrow_left;
313
        for (i = 0; i < options->optioncount; i++)
314
        {
315
            chooser2->items[i + 1].user = &options->options[i];
316
            rp = (struct chooser_renderer_list_itemdata*)chooser2->items[i + 1].renderparams;
317
            settingchooser_populate_rp(info, rp);
318
            rp->text = options->options[i].text;
319
            rp->icon = options->options[i].icon;
320
            rp->icon_selected = options->options[i].icon_selected;
321
        }
322
        result = chooser_run(chooser2);
323
        int value = result - chooser2->items;
324
        if (result && value && *((int*)item->setting) != value - 1)
325
        {
326
            data->changed = true;
327
            *((int*)item->setting) = value - 1;
328
            if (item->validator) item->validator(item->setting);
329
        }
330
        free(mem2);
331
    }
332
    rc = data->changed;
333
    free(mem);
334
    return rc;
335
}