| OZ++ Class: FolderSelectionBox |
/******************************************************************************
*
* Copyright (c) 2015-2017 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer.
*
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* FolderSelectionBox.h
*
*****************************************************************************/
//2015/08/27
//2017/10/15 Modified to use create method.
#pragma once
#include <oz++/StringT.h>
#include <oz++/StringBufferT.h>
#include <oz++/DirectoryScanner.h>
#include <oz++/motif/Color.h>
#include <oz++/motif/ScrolledWindow.h>
#include <oz++/motif/Form.h>
#include <oz++/motif/Container.h>
#include <oz++/motif/IconGadget.h>
#include <oz++/motif/CompoundString.h>
#include <oz++/motif/Pixelmap.h>
#include <oz++/motif/Label.h>
#include <oz++/motif/TextField.h>
#include <oz++/motif/StrDef.h>
//2017/05/10
#include <oz++/motif/xpm/folder.xpm>
//It contains static const char* folder_xpm[];
namespace OZ {
class FolderSelectionBox :public ScrolledWindow {
public:
enum {OK_BUTTON =0 , CANCEL_BUTTON, FILTER_BUTTON, HELP_BUTTON};
private:
SmartPtr<Container> container;
SmartPtr<IconGadget> root;
SmartPtr<Pixelmap> folderPixmap;
StringT<char> folderName;
StringT<char> rootFolder;
SmartPtr<Action> selectAction;
void selected(Action& action)
{
XmContainerSelectCallbackStruct* cbs =
(XmContainerSelectCallbackStruct*)action.getCallData();
Container* container = (Container*)action.getClientData();
int itemCount = cbs -> selected_item_count;
for (int i = 0; i < itemCount; i++) {
Widget w = cbs->selected_items[i];
IconGadget* selected = (IconGadget*)container->lookup(w);
if (selected) {
StringBufferT<char> path;
selected -> getHierarchy(path);
const char* folder = (const char*)path;
if (StringT<char>::startsWith(folder, "//")) {
folder++;
}
printf ("selected folder: %s\n", folder);
folderName = folder;
if (selected -> hasChildren() == false) {
buildDirTree(container, selected, folder);
}
if (selectAction) {
printf("itemCount %d\n", i);
selectAction -> setCallData((XtPointer)selected);
selectAction -> setClientData((XtPointer)folder);
selectAction -> call(*selectAction);
}
} //selected
} //for loop
}
void buildDirTree(Container* container, IconGadget* node, const char* dir)
{
char path[PATH_MAX];
if (StringT<char>::startsWith(dir, "/") == false) {
sprintf(path, "/%s", dir);
} else {
sprintf(path, "%s", dir);
}
printf("buildDirTree %s\n", path);
DirectoryScanner scanner(path);
DirEntryList dirList;
int m = scanner.scanDir("*", dirList);
printf("DirList dir=%s count=%d\n", dir, m);
for (int i = 0; i<m; i++) {
const char* name = dirList.getName(i);
printf("name %s\n", name);
Args args;
args.reset();
args.set(XmNentryParent, 0);
args.set(XmNoutlineState, XmEXPANDED);
args.set(XmNsmallIconPixmap, folderPixmap);
args.set(XmNviewType, XmSMALL_ICON);
args.set(XmNshadowThickness, 0);
args.set(XmNborderWidth, 0);
IconGadget* child = NULL;
if (node) {
child = node -> add(name, args);
} else {
child = new IconGadget(container, name, args);
}
container->add(child);
}
}
public:
FolderSelectionBox(View* parent, const char* name, Args& args)
:ScrolledWindow()
{
FolderSelectionBox::create(parent, name, args);
}
FolderSelectionBox()
:ScrolledWindow()
{
}
void create(View* parent, const char* name, Args& args)
{
ScrolledWindow::create(parent, name,
args.set(XmNscrollingPolicy, XmAUTOMATIC)
.set(XmNadjustLast, True)
.set(XmNvisualPolicy, XmVARIABLE)
.set(XmNscrollBarDisplayPolicy, XmAS_NEEDED)
.set(XmNspacing, 0)
.set(XmNborderWidth, 0) );
folderName = "";
Args ar;
ar.reset();
Color color(this);
//Pixel selectColor = color.allocNamedColor("lightblue");
Pixel selectColor = color.allocNamedColor("lightcyan");
ar.reset();
ar.set(XmNlayoutType, XmOUTLINE);
ar.set(XmNoutlineLineStyle, XmNO_LINE);
ar.set(XmNselectionPolicy, XmBROWSE_SELECT);
ar.set(XmNprimaryOwnership, XmOWN_MULTIPLE);
//ar.set(XmNprimaryOwnership, XmOWN_NEVER); //XmOWN_MULTIPLE);
ar.set(XmNselectColor, selectColor);
container = new Container(this, "folderSelectionContainer", ar);
/*
Widget hsb = (Widget)get(XmNhorizontalScrollBar);
Widget vsb = (Widget)get(XmNverticalScrollBar);
setArea(hsb, vsb, container->getWidget());
*/
try {
Pixel bg;
container -> get(XmNbackground, (XtArgVal)&bg);
//We use folder_xpm variable included by xpm/folder.xpm
folderPixmap = new Pixelmap(getDisplay(), bg, folder_xpm);
} catch (Exception& ex) {
ex.display();
}
static const char* rootName = "/";
//const char*
rootFolder = rootName;
if (args.has(XmNrootFolderName)) {
rootFolder = (const char*)args.get(XmNrootFolderName);
if(StringT<char>::startsWith(rootFolder, rootName) == false) {
rootFolder = rootName;
} else {
//rootFolder = rootFolder;
}
}
ar.reset();
ar.set(XmNentryParent, 0);
ar.set(XmNoutlineState, XmEXPANDED);
if (folderPixmap) {
ar.set(XmNsmallIconPixmap, folderPixmap);
}
ar.set(XmNviewType, XmSMALL_ICON);
ar.set(XmNshadowThickness, 0);
ar.set(XmNborderWidth, 0);
if (strcmp((const char*)rootFolder, "/") ) {
//If rootFolder is not "/", then we create IconGadget
root = new IconGadget(container, rootFolder, ar);
container -> add(root);
} else {
//else , we don't create IconGadage to "/",
//which means root IconGadget is NULL.
root = NULL;
}
buildDirTree(container, root, rootFolder);
container -> addCallback(XmNselectionCallback, this,
(Callback)&FolderSelectionBox::selected, container);
}
~FolderSelectionBox()
{
}
void getFolderName(StringT<char>& name)
{
name = folderName;
}
//To retrieve a folder name which starts with "/".
void getRootedFolderName(StringT<char>& name)
{
name = "/";
name += folderName;
}
const char* getFolderName()
{
return (const char*)folderName;
}
//To retrieve a folder name which starts with "/".
StringT<char> getRootedFolderName()
{
return (StringT<char>("/") + folderName);
}
void setSelectCallback(CommonObject* object,
Callback callback, XtPointer data)
{
if (selectAction) {
selectAction = NULL;
}
if (selectAction == NULL) {
selectAction = new Action(this, object, callback, data, "");
}
}
};
}