Files
commandergenius/project/jni/application/enigma/src/gui/LevelPackConfig.cpp
T
2010-10-13 17:30:44 +03:00

541 lines
22 KiB
C++

/*
* Copyright (C) 2006, 2007 Ronald Lamprecht
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "gui/LevelPackConfig.hh"
#include "gui/LevelPackComposer.hh"
#include "ecl.hh"
#include "errors.hh"
#include "nls.hh"
#include "video.hh"
#include "lev/Index.hh"
#include "main.hh"
using namespace ecl;
using namespace std;
namespace enigma { namespace gui {
GroupButton::GroupButton(std::vector<std::string> groups, int pos) :
ValueButton(0, groups.size() - 1),
position (pos), groupNames (groups) {
init();
}
int GroupButton::get_value() const {
return position;
}
void GroupButton::set_value(int value) {
position = value;
}
std::string GroupButton::get_text(int value) const {
return groupNames[value];
}
/* ------------------- LevelmodeButton -------------------- */
LevelmodeButton::LevelmodeButton(bool initialMode) :
ImageButton("ic-link_copy","ic-link_copy",this), mode (initialMode) {
update();
}
bool LevelmodeButton::isLinkOnly() {
return mode;
}
void LevelmodeButton::update() {
if (mode)
ImageButton::set_images("ic-link","ic-link_copy");
else
ImageButton::set_images("ic-link_copy","ic-link");
}
void LevelmodeButton::on_action(Widget *)
{
mode = !mode;
update();
invalidate();
}
void LevelmodeButton::draw(ecl::GC &gc, const ecl::Rect &r) {
update();
ImageButton::draw(gc, r);
}
LevelPackConfig::LevelPackConfig(std::string indexName, std::string groupName,
bool forceGroupReasign) : isReasignOnly (forceGroupReasign),
undo_quit (false), didEditMetaData (false), titleTF (NULL) {
const video::VMInfo &vminfo = *video::GetInfo();
if (indexName.empty())
// new levelpack
packIndex = new lev::PersistentIndex(" ", false,
INDEX_DEFAULT_PACK_LOCATION, "",
INDEX_STD_FILENAME, lev::Index::getCurrentGroup()); // mark as incomplete
else
packIndex = lev::Index::findIndex(indexName);
ASSERT (packIndex != NULL, XFrontend, "not existing index Name");
persIndex = dynamic_cast<lev::PersistentIndex *>(packIndex);
isPersistent = (persIndex != NULL);
isEditable = isPersistent ? persIndex->isUserEditable() : false;
// build a list of allowed group
std::vector<std::string> groups = lev::Index::getGroupNames();
// eliminate pseudo group "All Packs"
std::vector<std::string>::iterator itg = groups.begin();
while (itg != groups.end()) {
if (*itg == INDEX_ALL_PACKS) {
itg = groups.erase(itg);
break;
}
if (itg != groups.end())
itg++;
}
// add pseudo group "[Every Group]"
groups.push_back(std::string("[") + INDEX_EVERY_GROUP +"]");
intialGroupPosition = groups.size() - 1; // INDEX_EVERY_GROUP as default
// mark index's default group with square brackets and find current group
bool defaultGroupFound = false;
for (int i = 0; i < groups.size(); i++) {
if (groups[i] == packIndex->getGroupName()) {
intialGroupPosition = i;
}
if (groups[i] == packIndex->getDefaultGroupName()) {
groups[i] = std::string("[") + groups[i] +"]";
defaultGroupFound = true;
}
}
if (!defaultGroupFound) {
groups.push_back(std::string("[") + packIndex->getDefaultGroupName() +"]");
}
groupButton = new GroupButton(groups, intialGroupPosition);
// index location list setup
std::vector<lev::Index *> * allIndices = lev::Index::getGroup(INDEX_ALL_PACKS);
for (int i = 0; i < allIndices->size(); i++)
locationList.push_back((*allIndices)[i]->getName());
position = -1;
for (int i = 0; i < locationList.size(); i++) {
if (locationList[i] == indexName) {
position = i;
break;
}
}
oldPosition = position;
if (position < 0) {
// append new levelpack as last
locationList.push_back(indexName);
position = locationList.size() - 1;
}
VList * titleLeftVList = new VList;
titleLeftVList->set_spacing(11);
titleLeftVList->set_alignment(HALIGN_LEFT, VALIGN_CENTER);
titleLeftVList->set_default_size(140, 35);
Label * titleLabel = new Label(N_("Levelpack:"), HALIGN_RIGHT);
Label * ownerLabel = new Label(N_("Owner:"), HALIGN_RIGHT);
Label * groupLabel = new Label(N_("Group:"), HALIGN_RIGHT);
Label * loactionLabel1 = new Label(N_("Location"), HALIGN_LEFT);
Label * loactionLabel2 = new Label(N_("in [All Packs]:"), HALIGN_RIGHT);
titleLeftVList->add_back(titleLabel);
if (!isReasignOnly) {
titleLeftVList->add_back(ownerLabel);
}
titleLeftVList->add_back(groupLabel);
if (!isReasignOnly) {
titleLeftVList->add_back(new Label());
titleLeftVList->add_back(loactionLabel1);
titleLeftVList->add_back(loactionLabel2);
titleLeftVList->add_back(new Label());
titleLeftVList->add_back(new Label());
}
valueLeftVList = new VList;
valueLeftVList->set_spacing(11);
valueLeftVList->set_alignment(HALIGN_LEFT, VALIGN_CENTER);
valueLeftVList->set_default_size(160, 35);
titleValueLabel = new UntranslatedLabel(indexName, HALIGN_CENTER);
ownerValueLabel = new UntranslatedLabel(isPersistent ? persIndex->getOwner() : "System");
pre2Index = new UntranslatedLabel();
pre1Index = new UntranslatedLabel();
thisIndex = new UntranslatedLabel();
post1Index = new UntranslatedLabel();
post2Index = new UntranslatedLabel();
valueLeftVList->add_back(titleValueLabel);
if (!isReasignOnly) {
valueLeftVList->add_back(ownerValueLabel);
}
valueLeftVList->add_back(groupButton);
if (!isReasignOnly) {
valueLeftVList->add_back(pre2Index);
valueLeftVList->add_back(pre1Index);
valueLeftVList->add_back(thisIndex);
valueLeftVList->add_back(post1Index);
valueLeftVList->add_back(post2Index);
}
VList * scrollVList = new VList;
scrollVList->set_spacing(12);
scrollVList->set_alignment(HALIGN_LEFT, VALIGN_CENTER);
scrollVList->set_default_size(30, 35);
scrollUp = new ImageButton("ic-up", "ic-up1", this);
scrollDown = new ImageButton("ic-down", "ic-down1", this);
scrollVList->add_back(scrollUp);
scrollVList->add_back(scrollDown);
VList * metaVList = new VList;
metaVList->set_spacing(12);
metaVList->set_alignment(HALIGN_LEFT, VALIGN_CENTER);
metaVList->set_default_size(140, 35);
if (isEditable)
but_metadata = new StaticTextButton(N_("Edit Metadata"), this);
else
but_metadata = new Label();
Label * releaseLabel = new Label(N_("Release:"), HALIGN_RIGHT);
Label * revisionLabel = new Label(N_("Revision:"), HALIGN_RIGHT);
Label * compatibilityLabel = new Label(N_("Compatibility:"), HALIGN_RIGHT);
Label * defLocationLabel = new Label(N_("Default Location:"), HALIGN_RIGHT);
Label * crossmodeLabel = new Label(N_("Level types:"), HALIGN_RIGHT);
if (!isReasignOnly) {
metaVList->add_back(but_metadata);
metaVList->add_back(new Label());
if (WizardMode) {
metaVList->add_back(releaseLabel);
metaVList->add_back(revisionLabel);
} else {
metaVList->add_back(new Label());
metaVList->add_back(new Label());
}
metaVList->add_back(crossmodeLabel);
if (WizardMode) {
metaVList->add_back(compatibilityLabel);
} else {
metaVList->add_back(new Label());
}
metaVList->add_back(defLocationLabel);
metaVList->add_back(new Label());
}
valueMetaVList = new VList;
valueMetaVList->set_spacing(12);
valueMetaVList->set_alignment(HALIGN_CENTER, VALIGN_CENTER);
valueMetaVList->set_default_size(75, 35);
Widget * levelmodeWidget;
if (indexName.empty()){
levelmode = new LevelmodeButton(false);
levelmodeWidget = levelmode;
} else {
levelmodeWidget = new Image(isPersistent && !(persIndex->isCross()) ?
"ic-link_copy" : "ic-link");
}
defLocationValueLabel = new Label(ecl::strf("%g", packIndex->getDefaultLocation()));
releaseValueLabel = new Label(isPersistent ? ecl::strf("%d", persIndex->getRelease()) : "-");
revisionValueLabel = new Label(isPersistent ? ecl::strf("%d", persIndex->getRevision()) : "-");
compatibilityValueLabel = new Label(isPersistent ? ecl::strf("%.2f", persIndex->getCompatibility()) : "-");
if (!isReasignOnly) {
valueMetaVList->add_back(new Label());
valueMetaVList->add_back(new Label());
if (WizardMode) {
valueMetaVList->add_back(releaseValueLabel);
valueMetaVList->add_back(revisionValueLabel);
} else {
valueMetaVList->add_back(new Label());
valueMetaVList->add_back(new Label());
}
valueMetaVList->add_back(levelmodeWidget);
if (WizardMode) {
valueMetaVList->add_back(compatibilityValueLabel);
} else {
valueMetaVList->add_back(new Label());
}
valueMetaVList->add_back(defLocationValueLabel);
valueMetaVList->add_back(new Label());
}
if (isReasignOnly) {
this->add(titleLeftVList, Rect(vminfo.width/2 - 270, 15, 140, vminfo.height-97));
this->add(valueLeftVList, Rect(vminfo.width/2 - 80, 15, 160, vminfo.height-97));
} else {
this->add(titleLeftVList, Rect(vminfo.width/2 - 300, 15, 140, vminfo.height-97));
this->add(valueLeftVList, Rect(vminfo.width/2 - 140, 15, 160, vminfo.height-97));
this->add(scrollVList, Rect(vminfo.width/2 + 30, 15+3*(35+12) + (vminfo.height-480)/2, 30, 5*35+4*12));
this->add(metaVList, Rect(vminfo.width/2 + 80, 15, 140, vminfo.height-97));
this->add(valueMetaVList, Rect(vminfo.width/2 + 235, 15, 75, vminfo.height-97));
}
errorLabel = new Label("", HALIGN_CENTER);
this->add(errorLabel, Rect(10, vminfo.height-97, vminfo.width-20, 35));
if (isReasignOnly)
errorLabel->set_text(N_("Please reasign levelpack to another group for group deletion"));
// Create buttons - positioning identical to Levelmenu
but_edit = new StaticTextButton(N_("Compose Pack"), this);
if (isPersistent && persIndex->isUpdatable() && persIndex->isCross()) {
but_update = new StaticTextButton(N_("Update Pack"), this);
} else {
but_update = new Label();
}
but_ignore = new StaticTextButton(N_("Undo"), this);
but_back = new StaticTextButton(N_("Ok"), this);
HList * commandHList = new HList;
commandHList->set_spacing(10);
commandHList->set_alignment(HALIGN_CENTER, VALIGN_TOP);
commandHList->set_default_size(140, 35);
if (isReasignOnly) {
commandHList->add_back(new Label());
commandHList->add_back(new Label());
} else {
commandHList->add_back(but_edit);
commandHList->add_back(but_update);
}
commandHList->add_back(but_ignore);
commandHList->add_back(but_back);
this->add(commandHList, Rect(10, vminfo.height-50, vminfo.width-20, 35));
updateLocationList();
if (indexName.empty())
// new levelpack
switchToMetadataEdit();
}
void LevelPackConfig::updateLocationList() {
pre2Index->set_text((position > 1) ? locationList[position - 2] : "");
pre1Index->set_text((position > 0) ? locationList[position - 1] : "");
thisIndex->set_text(didEditMetaData ? titleTF->getText() : packIndex->getName());
post1Index->set_text((position < locationList.size() - 1) ? locationList[position + 1] : "");
post2Index->set_text((position < locationList.size() - 2) ? locationList[position + 2] : "");
}
void LevelPackConfig::switchToMetadataEdit() {
if (!didEditMetaData) {
didEditMetaData = true;
titleTF = new TextField(titleValueLabel->getText(), this);
valueLeftVList->exchange_child(titleValueLabel, titleTF);
delete titleValueLabel;
ownerTF = new TextField(ownerValueLabel->getText());
valueLeftVList->exchange_child(ownerValueLabel, ownerTF);
delete ownerValueLabel;
defLocationTF = new TextField(defLocationValueLabel->getText());
valueMetaVList->exchange_child(defLocationValueLabel, defLocationTF);
delete defLocationValueLabel;
if (WizardMode) {
releaseTF = new TextField(releaseValueLabel->getText());
valueMetaVList->exchange_child(releaseValueLabel, releaseTF);
delete releaseValueLabel;
revisionTF = new TextField(revisionValueLabel->getText());
valueMetaVList->exchange_child(revisionValueLabel, revisionTF);
delete revisionValueLabel;
compatibilityTF = new TextField(compatibilityValueLabel->getText());
valueMetaVList->exchange_child(compatibilityValueLabel, compatibilityTF);
delete compatibilityValueLabel;
}
}
}
bool LevelPackConfig::isUndoQuit() {
return undo_quit;
}
bool LevelPackConfig::doChanges() {
// change metadata
if (didEditMetaData) {
// the Index is persistent, user editabel and the user did switch to edit mode
bool needSave = false;
bool isNewIndex = persIndex->getName().empty();
// check for valid input
// title
std::string newtitle = titleTF->getText();
std::string::size_type lastChar = newtitle.find_last_not_of(" ");
if (lastChar == std::string::npos) {
// the title is effectively an empty string
errorLabel->set_text(N_("Error: empty title not allowed - press \"Undo\" to exit without modifications"));
return false;
}
// strip off trailing and leading spaces
newtitle = newtitle.substr(0 , lastChar + 1);
newtitle = newtitle.substr(newtitle.find_first_not_of(" "));
if (newtitle != persIndex->getName()) {
if (isNewIndex) {
// check for filename usability of title
const std::string validChars("_- .#0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
if (newtitle.find_first_not_of(validChars, 0) != std::string::npos ||
(newtitle.length() >= 1 && newtitle[0] == '.')) {
errorLabel->set_text(N_("Error: use only \"a-zA-Z0-9 _-#\" for levelpack title"));
return false;
}
// set packPath to cross if link only
if (levelmode->isLinkOnly())
persIndex->markNewAsCross();
}
if (!persIndex->setName(newtitle)) {
errorLabel->set_text(N_("Error: title already in use - choose another title"));
return false;
}
needSave = true;
}
// check rest for need of save
if (ownerTF->getText() != persIndex->getOwner()) {
persIndex->setOwner(ownerTF->getText());
needSave = true;
}
if (defLocationTF->getText() != ecl::strf("%g", packIndex->getDefaultLocation())) {
double d = 0;
// check value - keep old value on error
if ((sscanf(defLocationTF->getText().c_str(),"%lg", &d) == 1) &&
d > 0) {
packIndex->setDefaultLocation(d);
needSave = true;
}
}
if (WizardMode) {
if (releaseTF->getText() != ecl::strf("%d", persIndex->getRelease())) {
int i = 0;
// check value - keep old value on error
if ((sscanf(releaseTF->getText().c_str(),"%d", &i) == 1) &&
i > 0) {
persIndex->setRelease(i);
needSave = true;
}
}
if (revisionTF->getText() != ecl::strf("%d", persIndex->getRevision())) {
int i = 0;
// check value - keep old value on error
if ((sscanf(revisionTF->getText().c_str(),"%d", &i) == 1) &&
i > 0) {
persIndex->setRevision(i);
needSave = true;
}
}
if (compatibilityTF->getText() != ecl::strf("%.2f", persIndex->getCompatibility())) {
double d = 0;
// check value - keep old value on error
if ((sscanf(compatibilityTF->getText().c_str(),"%lg", &d) == 1) &&
d >= 1) {
persIndex->setCompatibility(d);
needSave = true;
}
}
}
// save
if (needSave)
persIndex->save();
if (isNewIndex) {
lev::Index::registerIndex(persIndex);
lev::Index::setCurrentIndex(persIndex->getName());
}
}
// regroup
if (groupButton->get_value() != intialGroupPosition) {
std::string newGroupName = groupButton->get_text(groupButton->get_value());
// strip off square brackets used to mark default and pseudo groups
if (newGroupName.size() > 2 && newGroupName[0] == '[' &&
newGroupName[newGroupName.size() -1] == ']') {
newGroupName = newGroupName.substr(1, newGroupName.size() - 2);
}
packIndex->moveToGroup(newGroupName);
} else if (isReasignOnly) {
// the user did not reasign - take as an undo request
undo_quit = true;
}
// relocate
if (position != oldPosition)
packIndex->locateBehind(position > 0 ? locationList[position - 1] : "");
return true;
}
void LevelPackConfig::on_action(Widget *w) {
if (w == but_back) {
if (doChanges())
Menu::quit();
else
invalidate_all();
} else if (w == but_ignore) {
if (packIndex->getName().empty()) {
delete packIndex;
}
undo_quit = true;
Menu::quit();
} else if (w == but_update) {
if (isPersistent && doChanges()) {
persIndex->load(false, true);
persIndex->save(true);
Menu::quit();
}
invalidate_all();
} else if (w == but_edit) {
if (doChanges()) {
LevelPackComposer m(isEditable);
m.manage();
Menu::quit();
} else {
invalidate_all();
}
} else if (w == scrollUp) {
if (position > 0) {
std::string tmp = locationList[position];
locationList[position] = locationList[position - 1];
locationList[position - 1] = tmp;
position--;
updateLocationList();
invalidate_all();
}
} else if (w == scrollDown) {
if (position < locationList.size() - 1) {
std::string tmp = locationList[position];
locationList[position] = locationList[position + 1];
locationList[position + 1] = tmp;
position++;
updateLocationList();
invalidate_all();
}
} else if (w == but_metadata && !didEditMetaData) {
switchToMetadataEdit();
invalidate_all();
} else if (w == titleTF && w != NULL) {
thisIndex->set_text(titleTF->getText());
}
}
void LevelPackConfig::draw_background(ecl::GC &gc) {
video::SetCaption(("Enigma - Level Pack Configuration"));
blit(gc, 0,0, enigma::GetImage("menu_bg", ".jpg"));
}
}} // namespace enigma::gui