Root/src/selector.cpp

1/***************************************************************************
2 * Copyright (C) 2006 by Massimiliano Torromeo *
3 * massimiliano.torromeo@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#include "selector.h"
22
23#include "debug.h"
24#include "filelister.h"
25#include "gmenu2x.h"
26#include "linkapp.h"
27#include "menu.h"
28#include "surface.h"
29#include "utilities.h"
30
31#include <SDL.h>
32#include <SDL_gfxPrimitives.h>
33#include <algorithm>
34
35//for browsing the filesystem
36#include <sys/stat.h>
37#include <sys/types.h>
38#include <dirent.h>
39#include <fstream>
40
41using namespace std;
42
43#define SELECTOR_ELEMENTS 11
44
45Selector::Selector(GMenu2X *gmenu2x, LinkApp *link, const string &selectorDir) :
46    Dialog(gmenu2x)
47{
48    this->link = link;
49    loadAliases();
50    selRow = 0;
51    if (selectorDir.empty())
52        dir = link->getSelectorDir();
53    else
54        dir = selectorDir;
55    if (dir[dir.length()-1]!='/') dir += "/";
56}
57
58int Selector::exec(int startSelection) {
59    bool close = false, result = true;
60    vector<string> screens, titles;
61
62    FileLister fl(dir, link->getSelectorBrowser());
63    fl.setFilter(link->getSelectorFilter());
64    fl.browse();
65
66    Surface bg(gmenu2x->bg);
67    drawTitleIcon(link->getIconPath(), true, &bg);
68    writeTitle(link->getTitle(), &bg);
69    writeSubTitle(link->getDescription(), &bg);
70
71    if (link->getSelectorBrowser()) {
72        gmenu2x->drawButton(&bg, "start", gmenu2x->tr["Exit"],
73        gmenu2x->drawButton(&bg, "accept", gmenu2x->tr["Select a file"],
74        gmenu2x->drawButton(&bg, "cancel", gmenu2x->tr["Up one folder"],
75        gmenu2x->drawButton(&bg, "left", "", 5)-10)));
76    } else {
77        gmenu2x->drawButton(&bg, "start", gmenu2x->tr["Exit"],
78        gmenu2x->drawButton(&bg, "cancel", "",
79        gmenu2x->drawButton(&bg, "accept", gmenu2x->tr["Select a file"], 5)) - 10);
80    }
81
82    bg.convertToDisplayFormat();
83
84    Uint32 selTick = SDL_GetTicks(), curTick;
85    uint i, firstElement = 0, iY;
86
87    prepare(&fl,&screens,&titles);
88    uint selected = constrain(startSelection,0,fl.size()-1);
89
90    //Add the folder icon manually to be sure to load it with alpha support since we are going to disable it for screenshots
91    if (gmenu2x->sc.skinRes("imgs/folder.png")==NULL)
92        gmenu2x->sc.addSkinRes("imgs/folder.png");
93    gmenu2x->sc.defaultAlpha = false;
94    while (!close) {
95        bg.blit(gmenu2x->s,0,0);
96
97        if (selected>=firstElement+SELECTOR_ELEMENTS) firstElement=selected-SELECTOR_ELEMENTS+1;
98        if (selected<firstElement) firstElement=selected;
99
100        //Selection
101        iY = selected-firstElement;
102        iY = 42+(iY*16);
103        if (selected<fl.size())
104            gmenu2x->s->box(1, iY, 309, 14, gmenu2x->skinConfColors[COLOR_SELECTION_BG]);
105
106        //Screenshot
107        if (selected-fl.dirCount()<screens.size()
108                && !screens[selected-fl.dirCount()].empty()) {
109            curTick = SDL_GetTicks();
110            if (curTick - selTick > 200) {
111                gmenu2x->sc[screens[selected-fl.dirCount()]]->blitRight(
112                        gmenu2x->s, 311, 42, 160, 160,
113                        min((curTick - selTick - 200) / 3, 255u));
114            }
115        }
116
117        //Files & Dirs
118        gmenu2x->s->setClipRect(0,41,311,179);
119        for (i=firstElement; i<fl.size() && i<firstElement+SELECTOR_ELEMENTS; i++) {
120            iY = i-firstElement;
121            if (fl.isDirectory(i)) {
122                gmenu2x->sc["imgs/folder.png"]->blit(gmenu2x->s, 4, 42+(iY*16));
123                gmenu2x->s->write(gmenu2x->font, fl[i], 21, 49+(iY*16), Font::HAlignLeft, Font::VAlignMiddle);
124            } else
125                gmenu2x->s->write(gmenu2x->font, titles[i-fl.dirCount()], 4, 49+(iY*16), Font::HAlignLeft, Font::VAlignMiddle);
126        }
127        gmenu2x->s->clearClipRect();
128
129        gmenu2x->drawScrollBar(SELECTOR_ELEMENTS, fl.size(), firstElement);
130        gmenu2x->s->flip();
131
132        switch (gmenu2x->input.waitForPressedButton()) {
133            case InputManager::SETTINGS:
134                close = true;
135                result = false;
136                break;
137
138            case InputManager::UP:
139                if (selected == 0) selected = fl.size() -1;
140                else selected -= 1;
141                selTick = SDL_GetTicks();
142                break;
143
144            case InputManager::ALTLEFT:
145                if ((int)(selected-SELECTOR_ELEMENTS+1)<0) selected = 0;
146                else selected -= SELECTOR_ELEMENTS-1;
147                selTick = SDL_GetTicks();
148                break;
149
150            case InputManager::DOWN:
151                if (selected+1>=fl.size()) selected = 0;
152                else selected += 1;
153                selTick = SDL_GetTicks();
154                break;
155
156            case InputManager::ALTRIGHT:
157                if (selected+SELECTOR_ELEMENTS-1>=fl.size()) selected = fl.size()-1;
158                else selected += SELECTOR_ELEMENTS-1;
159                selTick = SDL_GetTicks();
160                break;
161
162            case InputManager::CANCEL:
163                if (!link->getSelectorBrowser()) {
164                    close = true;
165                    result = false;
166                    break;
167                }
168
169            case InputManager::LEFT:
170                if (link->getSelectorBrowser()) {
171                    string::size_type p = dir.rfind("/", dir.size()-2);
172                    if (p==string::npos || dir.compare(0, 1, "/") != 0 || dir.length() < 2) {
173                        close = true;
174                        result = false;
175                    } else {
176                        dir = dir.substr(0,p+1);
177                        selected = 0;
178                        firstElement = 0;
179                        prepare(&fl,&screens,&titles);
180                    }
181                }
182                break;
183
184            case InputManager::ACCEPT:
185                if (fl.isFile(selected)) {
186                    file = fl[selected];
187                    close = true;
188                } else {
189                    dir = dir+fl[selected];
190                    char *buf = realpath(dir.c_str(), NULL);
191                    dir = (string) buf + '/';
192                    free(buf);
193
194                    selected = 0;
195                    firstElement = 0;
196                    prepare(&fl,&screens,&titles);
197                }
198                break;
199
200            default:
201                break;
202        }
203    }
204
205    gmenu2x->sc.defaultAlpha = true;
206    freeScreenshots(&screens);
207
208    return result ? (int)selected : -1;
209}
210
211void Selector::prepare(FileLister *fl, vector<string> *screens, vector<string> *titles) {
212    fl->setPath(dir);
213    freeScreenshots(screens);
214    screens->resize(fl->getFiles().size());
215    titles->resize(fl->getFiles().size());
216
217    string screendir = link->getSelectorScreens();
218    if (!screendir.empty() && screendir[screendir.length() - 1] != '/') {
219        screendir += "/";
220    }
221
222    string noext;
223    string::size_type pos;
224    for (uint i=0; i<fl->getFiles().size(); i++) {
225        noext = fl->getFiles()[i];
226        pos = noext.rfind(".");
227        if (pos!=string::npos && pos>0)
228            noext = noext.substr(0, pos);
229        titles->at(i) = getAlias(noext);
230        if (titles->at(i).empty())
231            titles->at(i) = noext;
232
233        DEBUG("Searching for screen '%s%s.png'\n", screendir.c_str(), noext.c_str());
234
235        if (fileExists(screendir+noext+".png"))
236            screens->at(i) = screendir+noext+".png";
237        else
238            screens->at(i) = "";
239    }
240}
241
242void Selector::freeScreenshots(vector<string> *screens) {
243    for (uint i=0; i<screens->size(); i++) {
244        if (!screens->at(i).empty())
245            gmenu2x->sc.del(screens->at(i));
246    }
247}
248
249void Selector::loadAliases() {
250    aliases.clear();
251    if (fileExists(link->getAliasFile())) {
252        string line;
253        ifstream infile (link->getAliasFile().c_str(), ios_base::in);
254        while (getline(infile, line, '\n')) {
255            string::size_type position = line.find("=");
256            string name = trim(line.substr(0,position));
257            string value = trim(line.substr(position+1));
258            aliases[name] = value;
259        }
260        infile.close();
261    }
262}
263
264string Selector::getAlias(const string &key) {
265    unordered_map<string, string>::iterator i = aliases.find(key);
266    if (i == aliases.end())
267        return "";
268    else
269        return i->second;
270}
271

Archive Download this file



interactive