Subversion Repositories freemyipod

Rev

Rev 824 | Go to most recent revision | 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;
40
    bool redraw = false;
41
    bool handled = false;
42
    bool setcolors = false;
43
    switch (event)
44
    {
45
        case BUTTON_PRESS:
46
            switch (which)
47
            {
48
                case 0:
826 theseven 49
                case 1:
824 theseven 50
                    switch (item->type)
51
                    {
52
                        case SETTINGCHOOSER_TYPE_INTEGER:
53
                            handled = true;
54
                            setcolors = true;
55
                            state->editing = !state->editing;
56
                            if (state->editing) state->collect = 0;
57
                            break;
58
                    }
59
                    break;
60
 
61
                case 2:
62
                    if (state->editing)
63
                    {
64
                        handled = true;
65
                        setcolors = true;
66
                        state->editing = false;
67
                    }
68
                    break;
69
 
70
                default:
71
                    handled = state->editing;
72
                    break;
73
            }
74
            break;
75
 
76
        case WHEEL_MOVED_ACCEL:
77
            if (state->editing)
78
            {
79
                switch (item->type)
80
                {
81
                    case SETTINGCHOOSER_TYPE_INTEGER:
82
                        handled = true;
83
                        state->collect += value;
84
                        int change = (state->collect * item->config.integer.step) / 128;
85
                        if (!change) break;
86
                        state->collect -= (change * 128) / item->config.integer.step;
87
                        int* setting = (int*)item->setting;
88
                        if (*setting + change < item->config.integer.min)
89
                            *setting = item->config.integer.min;
90
                        else if (*setting + change > item->config.integer.max)
91
                            *setting = item->config.integer.max;
92
                        else *setting += change;
93
                        if (item->validator) item->validator(item->setting);
94
                        state->changed = true;
95
                        redraw = true;
96
                        break;
97
                }
98
            }
99
            break;
100
    }
101
    if (setcolors)
102
    {
103
        if (state->editing)
104
        {
105
            rp->fill_color_selected = info->itemparams.fill_color_active;
106
            rp->text_color_selected = info->itemparams.text_color_active;
107
            rp->icon_selected_opacity = info->itemparams.icon_active_opacity;
108
        }
109
        else
110
        {
111
            rp->fill_color_selected = info->itemparams.fill_color_selected;
112
            rp->text_color_selected = info->itemparams.text_color_selected;
113
            rp->icon_selected_opacity = info->itemparams.icon_selected_opacity;
114
        }
115
        redraw = true;
116
    }
117
    if (redraw)
118
    {
119
        mutex_lock(&data->statemutex, TIMEOUT_BLOCK);
120
        data->redrawneeded = true;
121
        wakeup_signal(&data->eventwakeup);
122
        mutex_unlock(&data->statemutex);
123
    }
124
    return handled;
125
}
126
 
127
static struct chooser_action_handler_wheel_params settingchooser_aparams =
128
{
129
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
130
    .stepsperitem = 128,
131
    .eventfilter = settingchooser_event_filter,
132
    .timeout_initial = TIMEOUT_BLOCK,
133
    .timeout_idle = TIMEOUT_BLOCK,
134
    .timeout_item = 0,
135
    .tick_force_redraw = true,
136
    .buttoncount = 5,
137
    .buttonmap =
138
    {
139
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
826 theseven 140
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
824 theseven 141
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_CANCEL,
142
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
143
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
144
    }
145
};
146
static struct chooser_action_handler_wheel_params settingchooser_aparams2 =
147
{
148
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
149
    .stepsperitem = 128,
150
    .eventfilter = NULL,
151
    .timeout_initial = TIMEOUT_BLOCK,
152
    .timeout_idle = TIMEOUT_BLOCK,
153
    .timeout_item = 0,
154
    .tick_force_redraw = true,
155
    .buttoncount = 5,
156
    .buttonmap =
157
    {
158
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
826 theseven 159
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
824 theseven 160
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_CANCEL,
161
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
162
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
163
    }
164
};
165
 
166
static void settingchooser_render_preview(struct chooser_data* data,
167
                                          const struct chooser_item* item,
168
                                          bool selected, int x, int y)
169
{
170
    struct settingchooser_item* itemdata = (struct settingchooser_item*)item->user;
171
    int value = *((int*)itemdata->setting);
172
    const char* str = NULL;
173
    char buf[16];
174
    switch (itemdata->type)
175
    {
176
        case SETTINGCHOOSER_TYPE_INTEGER:
177
            if (itemdata->config.integer.tostring)
178
                itemdata->config.integer.tostring(buf, sizeof(buf), itemdata->setting, value);
179
            else snprintf(buf, sizeof(buf), "%d", value);
180
            str = buf;
181
            break;
182
 
183
        case SETTINGCHOOSER_TYPE_SELECT:
184
            if (value < itemdata->config.select.options->optioncount)
185
                str = itemdata->config.select.options->options[value].preview;
186
            break;
187
    }
188
    if (str) chooser_renderer_list_render_attached_text(data, item, selected, x, y, str);
189
}
190
 
191
static void settingchooser_populate_rp(const struct settingchooser_info* info,
192
                                       struct chooser_renderer_list_itemdata* rp)
193
{
194
    rp->size = info->itemparams.size;
195
    rp->fill_box = info->itemparams.fill_box;
196
    rp->fill_color = info->itemparams.fill_color;
197
    rp->fill_color_selected = info->itemparams.fill_color_selected;
198
    rp->icon_pos = info->itemparams.icon_pos;
199
    rp->icon_opacity = info->itemparams.icon_opacity;
200
    rp->icon_selected_opacity = info->itemparams.icon_selected_opacity;
201
    rp->text_pos = info->itemparams.text_pos;
202
    rp->text_color = info->itemparams.text_color;
203
    rp->text_color_selected = info->itemparams.text_color_selected;
204
}
205
 
206
bool settingchooser_run(const struct settingchooser_info* info)
207
{
208
    int i;
209
    bool rc = false;
210
    struct chooser_renderer_list_itemdata* rp;
211
    if (info->version != SETTINGCHOOSER_INFO_VERSION) return false;
212
    int allocsize = sizeof(struct settingchooser_data)
213
                  + sizeof(struct chooser_info)
214
                  + sizeof(struct chooser_item) * (info->itemcount + 1)
215
                  + sizeof(struct chooser_renderer_list_itemdata) * (info->itemcount + 1);
216
    void* mem = malloc(allocsize);
217
    if (!mem) return false;
218
    memset(mem, 0, allocsize);
219
    void* ptr = mem;
220
    struct settingchooser_data* data = (struct settingchooser_data*)ptr;
221
    ptr += sizeof(struct settingchooser_data);
222
    struct chooser_info* chooser = (struct chooser_info*)ptr;
223
    ptr += sizeof(struct chooser_info);
224
    ptr += sizeof(struct chooser_item) * (info->itemcount + 1);
225
    for (i = 0; i < info->itemcount + 1; i++)
226
    {
227
        chooser->items[i].renderparams = (struct chooser_renderer_list_itemdata*)ptr;
228
        ptr += sizeof(struct chooser_renderer_list_itemdata);
229
    }
230
    data->info = info;
231
    chooser->version = CHOOSER_INFO_VERSION;
232
    chooser->actionhandler = &chooser_action_handler_wheel;
233
    chooser->actionhandlerparams = &settingchooser_aparams;
234
    chooser->renderer = &chooser_renderer_list;
235
    chooser->rendererparams = &info->rendererparams;
236
    chooser->userparams = data;
237
    chooser->tickinterval = info->tickinterval;
238
    chooser->itemcount = info->itemcount + 1;
239
    rp = (struct chooser_renderer_list_itemdata*)chooser->items[0].renderparams;
240
    settingchooser_populate_rp(info, rp);
241
    rp->text = info->returntext;
242
    rp->render = chooser_renderer_list_show_arrow_left;
243
    for (i = 0; i < info->itemcount; i++)
244
    {
245
        chooser->items[i + 1].user = &info->items[i];
246
        rp = (struct chooser_renderer_list_itemdata*)chooser->items[i + 1].renderparams;
247
        settingchooser_populate_rp(info, rp);
248
        rp->text = info->items[i].text;
249
        rp->icon = info->items[i].icon;
250
        rp->icon_selected = info->items[i].icon_selected;
251
        rp->render = settingchooser_render_preview;
252
    }
253
    while (true)
254
    {
255
        const struct chooser_item* result = chooser_run(chooser);
256
        if (!result) break;
257
        struct settingchooser_item* item = (struct settingchooser_item*)result->user;
258
        if (!item) break;
259
        chooser->defaultitem = result - chooser->items;
260
        const struct settingchooser_select_options* options = item->config.select.options;
261
        int allocsize2 = sizeof(struct chooser_info)
262
                       + sizeof(struct chooser_item) * (options->optioncount + 1)
263
                       + sizeof(struct chooser_renderer_list_itemdata)
264
                       * (options->optioncount + 1);
265
        void* mem2 = malloc(allocsize2);
266
        if (!mem2) continue;
267
        memset(mem2, 0, allocsize2);
268
        void* ptr = mem2;
269
        struct chooser_info* chooser2 = (struct chooser_info*)ptr;
270
        ptr += sizeof(struct chooser_info);
271
        ptr += sizeof(struct chooser_item) * (options->optioncount + 1);
272
        for (i = 0; i < options->optioncount + 1; i++)
273
        {
274
            chooser2->items[i].renderparams = (struct chooser_renderer_list_itemdata*)ptr;
275
            ptr += sizeof(struct chooser_renderer_list_itemdata);
276
        }
277
        chooser2->version = CHOOSER_INFO_VERSION;
278
        chooser2->actionhandler = &chooser_action_handler_wheel;
279
        chooser2->actionhandlerparams = &settingchooser_aparams;
280
        chooser2->renderer = &chooser_renderer_list;
281
        chooser2->rendererparams = &info->rendererparams;
282
        chooser2->userparams = data;
283
        chooser2->tickinterval = info->tickinterval;
284
        chooser2->itemcount = options->optioncount + 1;
285
        chooser2->defaultitem = *((int*)item->setting) + 1;
286
        rp = (struct chooser_renderer_list_itemdata*)chooser2->items[0].renderparams;
287
        settingchooser_populate_rp(info, rp);
288
        rp->text = "Cancel";
289
        rp->render = chooser_renderer_list_show_arrow_left;
290
        for (i = 0; i < options->optioncount; i++)
291
        {
292
            chooser2->items[i + 1].user = &options->options[i];
293
            rp = (struct chooser_renderer_list_itemdata*)chooser2->items[i + 1].renderparams;
294
            settingchooser_populate_rp(info, rp);
295
            rp->text = options->options[i].text;
296
            rp->icon = options->options[i].icon;
297
            rp->icon_selected = options->options[i].icon_selected;
298
        }
299
        result = chooser_run(chooser2);
300
        int value = result - chooser2->items;
301
        if (result && value && *((int*)item->setting) != value - 1)
302
        {
303
            data->changed = true;
304
            *((int*)item->setting) = value - 1;
305
            if (item->validator) item->validator(item->setting);
306
        }
307
        free(mem2);
308
    }
309
    rc = data->changed;
310
    free(mem);
311
    return rc;
312
}