Skip to content
This repository has been archived by the owner on Jan 13, 2020. It is now read-only.

Commit

Permalink
Merge code from Selector into BrowseDialog
Browse files Browse the repository at this point in the history
Adding features to the selectors would have meant copy-pasting code.
This merging of code is intended to prepare the codebase for further
improvements.

This commit introduces more overridable functions for functionality
that differs per subclass, but only Selector is modified to use them.
Functions are provided to paint the background and icon required by
file selectors (useful for selecting wallpapers or previewable files)
and to initialise the path (for the wallpaper dialog, that would not
set the path at all, and instead merge from 4 wallpaper directories),
the display (row height, visible rows etc.) and the initial selection
(which is intended to be overridden by Selector to preserve its last
selection).

The behavior is intentionally kept similar, but due to the merge, there
are some differences:
* Selector now has an up-arrow icon next to the ".." entry, which
  selects the parent directory. Previously ".." was just text, which
  does not clearly indicate to a newbie that ".." goes to the parent.
* Selector now has a generic icon next to files, if directories are
  also shown. Previously there was no icon. This causes a slight loss
  of space for the file name.
* Selector now shows file extensions, when it didn't before.
* BrowseDialog and subclasses now have no big chunk of empty space at
  the bottom of the content area if only a partial row would fit there.
  The space is now redistributed to each row, as much as possible.
  This comes from Selector.
* FileDialog, used by the Explorer link, can now show the entries of
  the root directory properly. Previously, they would be displayed
  empty and possibly crash when selected.
* Selector now uses the same button as BrowseDialog and subclasses
  to cancel the entire dialog.
* The new virtual function to fill the ButtonBox runs per file. This
  allows for the text prompts to adjust to the context.
* BrowseDialog and subclasses now attempt to get an existing directory
  by removing path components at the end if the initial path doesn't
  exist, but only if directories are shown. If they are hidden, this
  path resolution is inhibited to act more like a pseudo-chroot, and
  "(no items)" is shown instead. This comes from Selector.
* Selector does not preserve the index of the first visible entry in
  it anymore, preferring to force the selected item to be at the bottom
  of the viewport. This comes from BrowseDialog.

While this is not due to the merge, the text hints for "Select" and
"Confirm" are now "Enter" and "Select". Select and Confirm were quite
confusing becaue they meant the same thing, but "Enter" now refers to
entering a directory without selecting it, and "Select" now refers to
designating the result of the selector.

The following behavior was kept the same using a workaround:
* DirDialog still selects the directory that the user has navigated
  *into*, not the one under the cursor. To keep this behavior,
  DirDialog::canSelect returns true for any selection, including "..",
  but BrowseDialog::initButtonBox checks for the selection being ".."
  and hides the hint for the Accept button in that case.

Code-wise, BrowseDialog::setPath() always adds a slash at the end of
the path, so getPath() will always have it.
  • Loading branch information
Nebuleon committed Oct 7, 2014
1 parent 280e006 commit c649e24
Show file tree
Hide file tree
Showing 12 changed files with 393 additions and 365 deletions.
314 changes: 215 additions & 99 deletions src/browsedialog.cpp

Large diffs are not rendered by default.

156 changes: 127 additions & 29 deletions src/browsedialog.h
Expand Up @@ -32,21 +32,18 @@
class OffscreenSurface;

class BrowseDialog : protected Dialog {
public:
bool exec();

virtual std::string const& getPath();
virtual std::string getFile();

protected:
BrowseDialog(
GMenu2X *gmenu2x,
const std::string &title, const std::string &subtitle);
virtual ~BrowseDialog();

void setPath(const std::string &path) {
this->path = path;
fl.browse(path);
}

FileLister fl;
unsigned int selected;

private:
enum Action {
ACT_NONE,
ACT_SELECT,
Expand All @@ -61,40 +58,141 @@ class BrowseDialog : protected Dialog {

bool close, result;

std::string title;
std::string subtitle;
/**
* Sets the current path of the BrowseDialog to the specified value.
* If it is non-empty and does not end with '/', '/' is appended to it.
*/
void setPath(std::string const& path);

FileLister fl;
unsigned int selected;
std::string path;

ButtonBox buttonBox;

SDL_Rect clipRect;

unsigned int topBarHeight;
unsigned int numRows;
unsigned int rowHeight;

OffscreenSurface *iconGoUp;
OffscreenSurface *iconFolder;
OffscreenSurface *iconFile;

ButtonBox buttonBox;

/**
* Initialises the buttonBox member with the buttons used by the dialog.
* This method can use the current selection of member variable 'fl', and
* is called before paint() in each run through the loop in exec.
* The implementation in BrowseDialog clears buttonBox, then creates
* buttons for 'Up one folder' (if applicable), 'Select', 'Confirm' and
* 'Exit'.
*/
virtual void initButtonBox();

/**
* Initialises member icons. The implementation in BrowseDialog creates
* iconGoUp, iconFolder and iconFile.
*/
virtual void initIcons();

/**
* Initialises the display. The implementation in BrowseDialog fills
* clipRect, topBarHeight, numRows and rowHeight.
*/
virtual void initDisplay();

/**
* Sets the initial path of the file browser.
* The implementation in BrowseDialog attempts to resolve the initial path
* in a way that most subclasses will find useful.
*/
virtual void initPath();

/**
* Sets the initial selection (member variable 'selected').
* The implementation in BrowseDialog sets the selection to 0 (the ..
* entry, or first file if directories are not shown in 'fl').
*/
virtual void initSelection();

/**
* Retrieves the BrowseDialog action corresponding to the given
* InputManager button.
* The implementation in BrowseDialog should not need to be overridden.
* It provides all the necessary mappings.
*/
Action getAction(InputManager::Button button);
void handleInput();

void paint();
/**
* Waits for an input, translates it to a BrowseDialog action, then calls
* virtual methods to carry out the action in a subclass-specific manner.
* The implementation in BrowseDialog should not need to be overridden.
*/
void handleInput();

void directoryUp();
void directoryEnter();
/**
* Paints the background to the display surface.
* The implementation in BrowseDialog paints the wallpaper.
*/
virtual void paintBackground();

/**
* Paints the icon to the display surface.
* The implementation in BrowseDialog paints icons/explorer.png.
*/
virtual void paintIcon();

/**
* Paints the entire screen.
* The implementation in BrowseDialog calls paintBackground and paintIcon,
* then paints the title and subtitle, 'buttonBox', and the icons and
* names of visible files and directories.
*/
virtual void paint();

/**
* Navigates to the parent directory. May be overridden to do nothing, if
* directory browsing is unavailable.
* The implementation in BrowseDialog removes the last component of the
* path in member variable 'path' and asks member variable 'fl' for its
* contents, then tries to select (member variable 'selected') the
* previous directory in the parent.
*/
virtual void directoryUp();

/**
* Navigates to the directory selected by 'fl[selected]', both member
* variables. May be overridden to do nothing, if directory browsing is
* unavailable.
* The implementation in BrowseDialog adds the newly-selected directory as
* a path component in member variable 'path'.
*/
virtual void directoryEnter();

/**
* Sets member variables 'close' and 'result' to true to exit the browser.
* The user is considered not to have cancelled the dialog.
*/
void confirm();

/**
* Sets member variable 'close' to true and 'result' to false to exit the
* browser. The user is considered to have cancelled the dialog.
*/
void quit();

public:
bool exec();
/**
* Returns true if the entry at 'fl[selected]' can be returned by this
* BrowseDialog as its result, or false if it is not the kind of entry
* it wants.
* The implementation in BrowseDialog accepts files.
*/
virtual bool canSelect();

private:
OffscreenSurface *iconGoUp;
OffscreenSurface *iconFolder;
OffscreenSurface *iconFile;

const std::string &getPath() {
return path;
}
std::string getFile() {
return fl[selected];
}
std::string title;
std::string subtitle;
};

#endif // INPUTDIALOG_H
5 changes: 5 additions & 0 deletions src/dirdialog.cpp
Expand Up @@ -32,3 +32,8 @@ DirDialog::DirDialog(
fl.setShowFiles(false);
setPath(dir);
}

bool DirDialog::canSelect()
{
return selected < fl.size();
}
2 changes: 2 additions & 0 deletions src/dirdialog.h
Expand Up @@ -28,6 +28,8 @@ class DirDialog : public BrowseDialog {
DirDialog(
GMenu2X *gmenu2x,
const std::string &text, const std::string &dir = "");

virtual bool canSelect() override;
};

#endif // DIRDIALOG_H
9 changes: 0 additions & 9 deletions src/filedialog.cpp
Expand Up @@ -40,12 +40,3 @@ FileDialog::FileDialog(
fl.setFilter(filter);
setPath(path);
}

bool FileDialog::exec() {
bool ret = BrowseDialog::exec();
if (ret && fl.isDirectory(selected)) {
// FileDialog must only pick regular files.
ret = false;
}
return ret;
}
1 change: 0 additions & 1 deletion src/filedialog.h
Expand Up @@ -29,7 +29,6 @@ class FileDialog : public BrowseDialog {
GMenu2X *gmenu2x, const std::string &text,
const std::string &filter="*", const std::string &file="",
const std::string &title = "File Dialog");
bool exec();
};

#endif // FILEDIALOG_H
2 changes: 2 additions & 0 deletions src/filelister.h
Expand Up @@ -52,6 +52,8 @@ class FileLister {

void setFilter(const std::string &filter);

bool getShowDirectories() { return showDirectories; }

void setShowDirectories(bool enabled) { showDirectories = enabled; }
void setShowUpdir(bool enabled) { showUpdir = enabled; }
void setShowFiles(bool enabled) { showFiles = enabled; }
Expand Down
2 changes: 1 addition & 1 deletion src/linkapp.cpp
Expand Up @@ -558,7 +558,7 @@ void LinkApp::selector(int startSelection, const string &selectorDir) {
Selector sel(gmenu2x, *this, selectorDir);
int selection = sel.exec(startSelection);
if (selection!=-1) {
const string &selectedDir = sel.getDir();
const string &selectedDir = sel.getPath();
if (!selectedDir.empty()) {
selectordir = selectedDir;
}
Expand Down
2 changes: 1 addition & 1 deletion src/menusettingfile.cpp
Expand Up @@ -50,6 +50,6 @@ void MenuSettingFile::edit()
{
FileDialog fd(gmenu2x, description, filter, value());
if (fd.exec()) {
setValue(fd.getPath() + "/" + fd.getFile());
setValue(fd.getPath() + fd.getFile());
}
}
2 changes: 1 addition & 1 deletion src/menusettingimage.cpp
Expand Up @@ -36,7 +36,7 @@ MenuSettingImage::MenuSettingImage(

void MenuSettingImage::edit() {
ImageDialog id(gmenu2x, description, filter, value());
if (id.exec()) setValue(id.getPath() + "/" + id.getFile());
if (id.exec()) setValue(id.getPath() + id.getFile());
}

void MenuSettingImage::setValue(const string &value) {
Expand Down

0 comments on commit c649e24

Please sign in to comment.