mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-12 13:37:00 -04:00
Change tabs to two spaces.
This commit is contained in:
+199
-199
@@ -20,290 +20,290 @@ DECLARE_TYPEOF_COLLECTION(ChoiceField::ChoiceP);
|
||||
|
||||
class ChoiceThumbnailRequest : public ThumbnailRequest {
|
||||
public:
|
||||
ChoiceThumbnailRequest(ValueViewer* cve, int id, bool from_disk, bool thread_safe);
|
||||
virtual Image generate();
|
||||
virtual void store(const Image&);
|
||||
ChoiceThumbnailRequest(ValueViewer* cve, int id, bool from_disk, bool thread_safe);
|
||||
virtual Image generate();
|
||||
virtual void store(const Image&);
|
||||
|
||||
bool isThreadSafe;
|
||||
virtual bool threadSafe() const {return isThreadSafe;}
|
||||
bool isThreadSafe;
|
||||
virtual bool threadSafe() const {return isThreadSafe;}
|
||||
private:
|
||||
int id;
|
||||
|
||||
inline ChoiceStyle& style() { return *static_cast<ChoiceStyle*>(viewer().getStyle().get()); }
|
||||
inline ValueViewer& viewer() { return *static_cast<ValueViewer*>(owner); }
|
||||
int id;
|
||||
|
||||
inline ChoiceStyle& style() { return *static_cast<ChoiceStyle*>(viewer().getStyle().get()); }
|
||||
inline ValueViewer& viewer() { return *static_cast<ValueViewer*>(owner); }
|
||||
};
|
||||
|
||||
ChoiceThumbnailRequest::ChoiceThumbnailRequest(ValueViewer* viewer, int id, bool from_disk, bool thread_safe)
|
||||
: ThumbnailRequest(
|
||||
static_cast<void*>(viewer),
|
||||
viewer->getStylePackage().name() + _("/") + viewer->getField()->name + _("/") << id,
|
||||
from_disk ? viewer->getStylePackage().lastModified()
|
||||
: wxDateTime::Now()
|
||||
)
|
||||
, isThreadSafe(thread_safe)
|
||||
, id(id)
|
||||
: ThumbnailRequest(
|
||||
static_cast<void*>(viewer),
|
||||
viewer->getStylePackage().name() + _("/") + viewer->getField()->name + _("/") << id,
|
||||
from_disk ? viewer->getStylePackage().lastModified()
|
||||
: wxDateTime::Now()
|
||||
)
|
||||
, isThreadSafe(thread_safe)
|
||||
, id(id)
|
||||
{}
|
||||
|
||||
Image ChoiceThumbnailRequest::generate() {
|
||||
ChoiceStyle& s = style();
|
||||
String name = canonical_name_form(s.field().choices->choiceName(id));
|
||||
ScriptableImage& img = s.choice_images[name];
|
||||
return img.isReady()
|
||||
? img.generate(GeneratedImage::Options(16,16, &viewer().getStylePackage(), &viewer().getLocalPackage(), ASPECT_BORDER, true))
|
||||
: wxImage();
|
||||
ChoiceStyle& s = style();
|
||||
String name = canonical_name_form(s.field().choices->choiceName(id));
|
||||
ScriptableImage& img = s.choice_images[name];
|
||||
return img.isReady()
|
||||
? img.generate(GeneratedImage::Options(16,16, &viewer().getStylePackage(), &viewer().getLocalPackage(), ASPECT_BORDER, true))
|
||||
: wxImage();
|
||||
}
|
||||
|
||||
void ChoiceThumbnailRequest::store(const Image& img) {
|
||||
ChoiceStyle& s = style();
|
||||
wxImageList* il = s.thumbnails;
|
||||
while (id > il->GetImageCount()) {
|
||||
il->Add(wxBitmap(16,16),*wxBLACK);
|
||||
}
|
||||
if (img.Ok()) {
|
||||
#ifdef __WXMSW__
|
||||
// for some reason windows doesn't like completely transparent images if they do not have a mask
|
||||
// HACK:
|
||||
if (img.HasAlpha() && img.GetWidth() == 16 && img.GetHeight() == 16) {
|
||||
// is the image empty?
|
||||
bool empty = true;
|
||||
int* b = (int*)img.GetAlpha();
|
||||
int* e = b + 16*16/sizeof(int);
|
||||
while (b != e) {
|
||||
if (*b++) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if so, use a mask instead
|
||||
if (empty) {
|
||||
const_cast<Image&>(img).ConvertAlphaToMask();
|
||||
}
|
||||
}
|
||||
// Hack ends here
|
||||
#endif
|
||||
if (id == il->GetImageCount()) {
|
||||
il->Add(img);
|
||||
} else {
|
||||
il->Replace(id, img);
|
||||
}
|
||||
s.thumbnails_status[id] = THUMB_OK;
|
||||
}
|
||||
ChoiceStyle& s = style();
|
||||
wxImageList* il = s.thumbnails;
|
||||
while (id > il->GetImageCount()) {
|
||||
il->Add(wxBitmap(16,16),*wxBLACK);
|
||||
}
|
||||
if (img.Ok()) {
|
||||
#ifdef __WXMSW__
|
||||
// for some reason windows doesn't like completely transparent images if they do not have a mask
|
||||
// HACK:
|
||||
if (img.HasAlpha() && img.GetWidth() == 16 && img.GetHeight() == 16) {
|
||||
// is the image empty?
|
||||
bool empty = true;
|
||||
int* b = (int*)img.GetAlpha();
|
||||
int* e = b + 16*16/sizeof(int);
|
||||
while (b != e) {
|
||||
if (*b++) {
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if so, use a mask instead
|
||||
if (empty) {
|
||||
const_cast<Image&>(img).ConvertAlphaToMask();
|
||||
}
|
||||
}
|
||||
// Hack ends here
|
||||
#endif
|
||||
if (id == il->GetImageCount()) {
|
||||
il->Add(img);
|
||||
} else {
|
||||
il->Replace(id, img);
|
||||
}
|
||||
s.thumbnails_status[id] = THUMB_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropDownChoiceListBase
|
||||
|
||||
DropDownChoiceListBase::DropDownChoiceListBase
|
||||
(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group)
|
||||
: DropDownList(parent, is_submenu, is_submenu ? nullptr : &cve)
|
||||
, cve(cve)
|
||||
, group(group)
|
||||
(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group)
|
||||
: DropDownList(parent, is_submenu, is_submenu ? nullptr : &cve)
|
||||
, cve(cve)
|
||||
, group(group)
|
||||
{
|
||||
icon_size.width = 16;
|
||||
icon_size.height = 16;
|
||||
item_size.height = max(16., item_size.height);
|
||||
icon_size.width = 16;
|
||||
icon_size.height = 16;
|
||||
item_size.height = max(16., item_size.height);
|
||||
}
|
||||
|
||||
void DropDownChoiceListBase::onShow() {
|
||||
// update 'enabled'
|
||||
Context& ctx = cve.viewer.getContext();
|
||||
FOR_EACH(c, group->choices) {
|
||||
c->enabled.update(ctx);
|
||||
}
|
||||
// update 'enabled'
|
||||
Context& ctx = cve.viewer.getContext();
|
||||
FOR_EACH(c, group->choices) {
|
||||
c->enabled.update(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
size_t DropDownChoiceListBase::itemCount() const {
|
||||
return group->choices.size() + hasDefault();
|
||||
return group->choices.size() + hasDefault();
|
||||
}
|
||||
|
||||
ChoiceField::ChoiceP DropDownChoiceListBase::getChoice(size_t item) const {
|
||||
if (isGroupDefault(item)) {
|
||||
return group;
|
||||
} else {
|
||||
return group->choices[item - hasDefault()];
|
||||
}
|
||||
if (isGroupDefault(item)) {
|
||||
return group;
|
||||
} else {
|
||||
return group->choices[item - hasDefault()];
|
||||
}
|
||||
}
|
||||
|
||||
String DropDownChoiceListBase::itemText(size_t item) const {
|
||||
if (isFieldDefault(item)) {
|
||||
return field().default_name;
|
||||
} else if (isGroupDefault(item)) {
|
||||
return group->default_name;
|
||||
} else {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
return choice->name;
|
||||
}
|
||||
if (isFieldDefault(item)) {
|
||||
return field().default_name;
|
||||
} else if (isGroupDefault(item)) {
|
||||
return group->default_name;
|
||||
} else {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
return choice->name;
|
||||
}
|
||||
}
|
||||
bool DropDownChoiceListBase::lineBelow(size_t item) const {
|
||||
return isDefault(item) || getChoice(item)->line_below;
|
||||
return isDefault(item) || getChoice(item)->line_below;
|
||||
}
|
||||
bool DropDownChoiceListBase::itemEnabled(size_t item) const {
|
||||
return isDefault(item) || getChoice(item)->enabled;
|
||||
return isDefault(item) || getChoice(item)->enabled;
|
||||
}
|
||||
DropDownList* DropDownChoiceListBase::submenu(size_t item) const {
|
||||
if (isDefault(item)) return nullptr;
|
||||
item -= hasDefault();
|
||||
if (item >= submenus.size()) submenus.resize(item + 1);
|
||||
if (submenus[item]) return submenus[item].get();
|
||||
ChoiceField::ChoiceP choice = group->choices[item];
|
||||
if (choice->isGroup()) {
|
||||
// create submenu
|
||||
submenus[item].reset(createSubMenu(choice));
|
||||
}
|
||||
return submenus[item].get();
|
||||
if (isDefault(item)) return nullptr;
|
||||
item -= hasDefault();
|
||||
if (item >= submenus.size()) submenus.resize(item + 1);
|
||||
if (submenus[item]) return submenus[item].get();
|
||||
ChoiceField::ChoiceP choice = group->choices[item];
|
||||
if (choice->isGroup()) {
|
||||
// create submenu
|
||||
submenus[item].reset(createSubMenu(choice));
|
||||
}
|
||||
return submenus[item].get();
|
||||
}
|
||||
|
||||
void DropDownChoiceListBase::drawIcon(DC& dc, int x, int y, size_t item, bool selected) const {
|
||||
// imagelist to use
|
||||
wxImageList* il = style().thumbnails;
|
||||
assert(il);
|
||||
// find the image for the item
|
||||
int image_id;
|
||||
if (isFieldDefault(item)) {
|
||||
image_id = default_id;
|
||||
} else {
|
||||
image_id = getChoice(item)->first_id;
|
||||
}
|
||||
// draw image
|
||||
if (image_id < il->GetImageCount()) {
|
||||
il->Draw(image_id, dc, x, y, itemEnabled(item) ? wxIMAGELIST_DRAW_NORMAL : wxIMAGELIST_DRAW_TRANSPARENT);
|
||||
}
|
||||
// imagelist to use
|
||||
wxImageList* il = style().thumbnails;
|
||||
assert(il);
|
||||
// find the image for the item
|
||||
int image_id;
|
||||
if (isFieldDefault(item)) {
|
||||
image_id = default_id;
|
||||
} else {
|
||||
image_id = getChoice(item)->first_id;
|
||||
}
|
||||
// draw image
|
||||
if (image_id < il->GetImageCount()) {
|
||||
il->Draw(image_id, dc, x, y, itemEnabled(item) ? wxIMAGELIST_DRAW_NORMAL : wxIMAGELIST_DRAW_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
void DropDownChoiceListBase::generateThumbnailImages() {
|
||||
if (!isRoot()) return;
|
||||
if (!style().thumbnails) {
|
||||
style().thumbnails = new wxImageList(16,16);
|
||||
}
|
||||
int image_count = style().thumbnails->GetImageCount();
|
||||
int end = group->lastId();
|
||||
// init choice images
|
||||
Context& ctx = cve.viewer.getContext();
|
||||
if (style().choice_images.empty() && style().image.isScripted()) {
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
try {
|
||||
String name = canonical_name_form(field().choices->choiceName(i));
|
||||
ctx.setVariable(_("input"), to_script(name));
|
||||
GeneratedImageP img = image_from_script(style().image.getValidScriptP()->eval(ctx));
|
||||
style().choice_images.insert(make_pair(name, ScriptableImage(img)));
|
||||
} catch (const Error& e) {
|
||||
handle_error(Error(e.what() + _("\n while generating choice images for drop down list")));
|
||||
}
|
||||
}
|
||||
}
|
||||
// request thumbnails
|
||||
style().thumbnails_status.resize(end, THUMB_NOT_MADE);
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
ThumbnailStatus& status = style().thumbnails_status[i];
|
||||
if (i >= image_count || status != THUMB_OK) {
|
||||
// update image
|
||||
ChoiceStyle& s = style();
|
||||
String name = canonical_name_form(s.field().choices->choiceName(i));
|
||||
ScriptableImage& img = s.choice_images[name];
|
||||
if (!img.update(ctx) && status == THUMB_CHANGED) {
|
||||
status = THUMB_OK; // no need to rebuild
|
||||
} else if (img.isReady()) {
|
||||
// request this thumbnail
|
||||
thumbnail_thread.request( intrusive(new ChoiceThumbnailRequest(
|
||||
&cve, i, status == THUMB_NOT_MADE && !img.local(), img.threadSafe()
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isRoot()) return;
|
||||
if (!style().thumbnails) {
|
||||
style().thumbnails = new wxImageList(16,16);
|
||||
}
|
||||
int image_count = style().thumbnails->GetImageCount();
|
||||
int end = group->lastId();
|
||||
// init choice images
|
||||
Context& ctx = cve.viewer.getContext();
|
||||
if (style().choice_images.empty() && style().image.isScripted()) {
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
try {
|
||||
String name = canonical_name_form(field().choices->choiceName(i));
|
||||
ctx.setVariable(_("input"), to_script(name));
|
||||
GeneratedImageP img = image_from_script(style().image.getValidScriptP()->eval(ctx));
|
||||
style().choice_images.insert(make_pair(name, ScriptableImage(img)));
|
||||
} catch (const Error& e) {
|
||||
handle_error(Error(e.what() + _("\n while generating choice images for drop down list")));
|
||||
}
|
||||
}
|
||||
}
|
||||
// request thumbnails
|
||||
style().thumbnails_status.resize(end, THUMB_NOT_MADE);
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
ThumbnailStatus& status = style().thumbnails_status[i];
|
||||
if (i >= image_count || status != THUMB_OK) {
|
||||
// update image
|
||||
ChoiceStyle& s = style();
|
||||
String name = canonical_name_form(s.field().choices->choiceName(i));
|
||||
ScriptableImage& img = s.choice_images[name];
|
||||
if (!img.update(ctx) && status == THUMB_CHANGED) {
|
||||
status = THUMB_OK; // no need to rebuild
|
||||
} else if (img.isReady()) {
|
||||
// request this thumbnail
|
||||
thumbnail_thread.request( intrusive(new ChoiceThumbnailRequest(
|
||||
&cve, i, status == THUMB_NOT_MADE && !img.local(), img.threadSafe()
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DropDownChoiceListBase::onIdle(wxIdleEvent& ev) {
|
||||
if (!isRoot()) return;
|
||||
if (thumbnail_thread.done(&cve)) {
|
||||
Refresh(false);
|
||||
}
|
||||
if (!isRoot()) return;
|
||||
if (thumbnail_thread.done(&cve)) {
|
||||
Refresh(false);
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(DropDownChoiceListBase, DropDownList)
|
||||
EVT_IDLE(DropDownChoiceListBase::onIdle)
|
||||
EVT_IDLE(DropDownChoiceListBase::onIdle)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropDownChoiceList
|
||||
|
||||
DropDownChoiceList::DropDownChoiceList(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group)
|
||||
: DropDownChoiceListBase(parent, is_submenu, cve, group)
|
||||
: DropDownChoiceListBase(parent, is_submenu, cve, group)
|
||||
{}
|
||||
|
||||
void DropDownChoiceList::onShow() {
|
||||
DropDownChoiceListBase::onShow();
|
||||
// we need thumbnail images soon
|
||||
generateThumbnailImages();
|
||||
DropDownChoiceListBase::onShow();
|
||||
// we need thumbnail images soon
|
||||
generateThumbnailImages();
|
||||
}
|
||||
|
||||
void DropDownChoiceList::select(size_t item) {
|
||||
if (isFieldDefault(item)) {
|
||||
dynamic_cast<ChoiceValueEditor&>(cve).change( Defaultable<String>() );
|
||||
} else {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
dynamic_cast<ChoiceValueEditor&>(cve).change( field().choices->choiceName(choice->first_id) );
|
||||
}
|
||||
if (isFieldDefault(item)) {
|
||||
dynamic_cast<ChoiceValueEditor&>(cve).change( Defaultable<String>() );
|
||||
} else {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
dynamic_cast<ChoiceValueEditor&>(cve).change( field().choices->choiceName(choice->first_id) );
|
||||
}
|
||||
}
|
||||
|
||||
size_t DropDownChoiceList::selection() const {
|
||||
// selected item
|
||||
const Defaultable<String>& value = dynamic_cast<ChoiceValueEditor&>(cve).value().value();
|
||||
int id = field().choices->choiceId(value);
|
||||
// id of default item
|
||||
if (hasFieldDefault()) {
|
||||
if (value.isDefault()) {
|
||||
// default is selected
|
||||
default_id = id;
|
||||
return 0;
|
||||
} else {
|
||||
// run default script to find out what the default choice would be
|
||||
String default_choice = *field().default_script.invoke( cve.viewer.getContext() );
|
||||
default_id = group->choiceId(default_choice);
|
||||
}
|
||||
}
|
||||
// item corresponding to id
|
||||
size_t i = hasDefault();
|
||||
FOR_EACH(c, group->choices) {
|
||||
if (id >= c->first_id && id < c->lastId()) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return NO_SELECTION;
|
||||
// selected item
|
||||
const Defaultable<String>& value = dynamic_cast<ChoiceValueEditor&>(cve).value().value();
|
||||
int id = field().choices->choiceId(value);
|
||||
// id of default item
|
||||
if (hasFieldDefault()) {
|
||||
if (value.isDefault()) {
|
||||
// default is selected
|
||||
default_id = id;
|
||||
return 0;
|
||||
} else {
|
||||
// run default script to find out what the default choice would be
|
||||
String default_choice = *field().default_script.invoke( cve.viewer.getContext() );
|
||||
default_id = group->choiceId(default_choice);
|
||||
}
|
||||
}
|
||||
// item corresponding to id
|
||||
size_t i = hasDefault();
|
||||
FOR_EACH(c, group->choices) {
|
||||
if (id >= c->first_id && id < c->lastId()) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return NO_SELECTION;
|
||||
}
|
||||
|
||||
DropDownList* DropDownChoiceList::createSubMenu(ChoiceField::ChoiceP group) const {
|
||||
return new DropDownChoiceList(static_cast<Window*>(const_cast<DropDownChoiceList*>(this)), true, cve, group);
|
||||
return new DropDownChoiceList(static_cast<Window*>(const_cast<DropDownChoiceList*>(this)), true, cve, group);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : ChoiceValueEditor
|
||||
|
||||
IMPLEMENT_VALUE_EDITOR(Choice)
|
||||
, drop_down(new DropDownChoiceList(&editor(), false, *this, field().choices))
|
||||
, drop_down(new DropDownChoiceList(&editor(), false, *this, field().choices))
|
||||
{}
|
||||
|
||||
ChoiceValueEditor::~ChoiceValueEditor() {
|
||||
thumbnail_thread.abort(this);
|
||||
thumbnail_thread.abort(this);
|
||||
}
|
||||
|
||||
bool ChoiceValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
|
||||
return drop_down->onMouseInParent(ev, style().popup_style == POPUP_DROPDOWN_IN_PLACE && !nativeLook());
|
||||
return drop_down->onMouseInParent(ev, style().popup_style == POPUP_DROPDOWN_IN_PLACE && !nativeLook());
|
||||
}
|
||||
bool ChoiceValueEditor::onChar(wxKeyEvent& ev) {
|
||||
return drop_down->onCharInParent(ev);
|
||||
return drop_down->onCharInParent(ev);
|
||||
}
|
||||
void ChoiceValueEditor::onLoseFocus() {
|
||||
drop_down->hide(false);
|
||||
drop_down->hide(false);
|
||||
}
|
||||
|
||||
void ChoiceValueEditor::draw(RotatedDC& dc) {
|
||||
ChoiceValueViewer::draw(dc);
|
||||
if (nativeLook()) {
|
||||
draw_drop_down_arrow(&editor(), dc.getDC(), dc.trRectToBB(style().getInternalRect().grow(1)), drop_down->IsShown());
|
||||
}
|
||||
ChoiceValueViewer::draw(dc);
|
||||
if (nativeLook()) {
|
||||
draw_drop_down_arrow(&editor(), dc.getDC(), dc.trRectToBB(style().getInternalRect().grow(1)), drop_down->IsShown());
|
||||
}
|
||||
}
|
||||
void ChoiceValueEditor::determineSize(bool) {
|
||||
style().height = max(style().height(), 16.);
|
||||
style().height = max(style().height(), 16.);
|
||||
}
|
||||
|
||||
void ChoiceValueEditor::change(const Defaultable<String>& c) {
|
||||
addAction(value_action(valueP(), c));
|
||||
addAction(value_action(valueP(), c));
|
||||
}
|
||||
|
||||
+56
-56
@@ -22,22 +22,22 @@ DECLARE_POINTER_TYPE(ThumbnailRequest);
|
||||
/// An editor 'control' for editing ChoiceValues
|
||||
class ChoiceValueEditor : public ChoiceValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(Choice);
|
||||
~ChoiceValueEditor();
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
virtual bool onLeftDown(const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void determineSize(bool);
|
||||
|
||||
DECLARE_VALUE_EDITOR(Choice);
|
||||
~ChoiceValueEditor();
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
virtual bool onLeftDown(const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void determineSize(bool);
|
||||
|
||||
private:
|
||||
DropDownListP drop_down;
|
||||
friend class DropDownChoiceList;
|
||||
/// Change the choice
|
||||
void change(const Defaultable<String>& c);
|
||||
DropDownListP drop_down;
|
||||
friend class DropDownChoiceList;
|
||||
/// Change the choice
|
||||
void change(const Defaultable<String>& c);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropDownChoiceList
|
||||
@@ -46,44 +46,44 @@ class ChoiceValueEditor : public ChoiceValueViewer, public ValueEditor {
|
||||
/** This is a base class, used for single and multiple choice fields */
|
||||
class DropDownChoiceListBase : public DropDownList {
|
||||
public:
|
||||
DropDownChoiceListBase(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group);
|
||||
|
||||
DropDownChoiceListBase(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group);
|
||||
|
||||
protected:
|
||||
virtual void onShow();
|
||||
virtual size_t itemCount() const;
|
||||
virtual bool lineBelow(size_t item) const;
|
||||
virtual bool itemEnabled(size_t item) const;
|
||||
virtual String itemText(size_t item) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
virtual DropDownList* submenu(size_t item) const;
|
||||
|
||||
virtual void onShow();
|
||||
virtual size_t itemCount() const;
|
||||
virtual bool lineBelow(size_t item) const;
|
||||
virtual bool itemEnabled(size_t item) const;
|
||||
virtual String itemText(size_t item) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
virtual DropDownList* submenu(size_t item) const;
|
||||
|
||||
protected:
|
||||
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const = 0;
|
||||
|
||||
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const = 0;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
ValueViewer& cve; ///< Editor this list belongs to
|
||||
ChoiceField::ChoiceP group; ///< Group this menu shows
|
||||
mutable vector<DropDownListP> submenus;
|
||||
mutable int default_id; ///< Item id for the default item (if !hasFieldDefault()) this is undefined)
|
||||
|
||||
inline ChoiceField& field() const { return static_cast<ChoiceField&>(*cve.getField()); }
|
||||
inline ChoiceStyle& style() const { return static_cast<ChoiceStyle&>(*cve.getStyle()); }
|
||||
|
||||
inline bool isRoot() const { return group == field().choices; }
|
||||
inline bool hasFieldDefault() const { return isRoot() && field().default_script; }
|
||||
inline bool hasGroupDefault() const { return group->hasDefault(); }
|
||||
virtual bool hasDefault() const { return hasFieldDefault() || hasGroupDefault(); }
|
||||
inline bool isFieldDefault(size_t item) const { return item == 0 && hasFieldDefault(); }
|
||||
inline bool isGroupDefault(size_t item) const { return item == 0 && hasGroupDefault(); }
|
||||
inline bool isDefault (size_t item) const { return item == 0 && hasDefault(); }
|
||||
|
||||
// Find an item in the group of choices
|
||||
ChoiceField::ChoiceP getChoice(size_t item) const;
|
||||
/// Start generating thumbnail images
|
||||
void generateThumbnailImages();
|
||||
void onIdle(wxIdleEvent&);
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
ValueViewer& cve; ///< Editor this list belongs to
|
||||
ChoiceField::ChoiceP group; ///< Group this menu shows
|
||||
mutable vector<DropDownListP> submenus;
|
||||
mutable int default_id; ///< Item id for the default item (if !hasFieldDefault()) this is undefined)
|
||||
|
||||
inline ChoiceField& field() const { return static_cast<ChoiceField&>(*cve.getField()); }
|
||||
inline ChoiceStyle& style() const { return static_cast<ChoiceStyle&>(*cve.getStyle()); }
|
||||
|
||||
inline bool isRoot() const { return group == field().choices; }
|
||||
inline bool hasFieldDefault() const { return isRoot() && field().default_script; }
|
||||
inline bool hasGroupDefault() const { return group->hasDefault(); }
|
||||
virtual bool hasDefault() const { return hasFieldDefault() || hasGroupDefault(); }
|
||||
inline bool isFieldDefault(size_t item) const { return item == 0 && hasFieldDefault(); }
|
||||
inline bool isGroupDefault(size_t item) const { return item == 0 && hasGroupDefault(); }
|
||||
inline bool isDefault (size_t item) const { return item == 0 && hasDefault(); }
|
||||
|
||||
// Find an item in the group of choices
|
||||
ChoiceField::ChoiceP getChoice(size_t item) const;
|
||||
/// Start generating thumbnail images
|
||||
void generateThumbnailImages();
|
||||
void onIdle(wxIdleEvent&);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropDownChoiceList
|
||||
@@ -91,13 +91,13 @@ class DropDownChoiceListBase : public DropDownList {
|
||||
/// A drop down list of choices
|
||||
class DropDownChoiceList : public DropDownChoiceListBase {
|
||||
public:
|
||||
DropDownChoiceList(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group);
|
||||
|
||||
DropDownChoiceList(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group);
|
||||
|
||||
protected:
|
||||
virtual void onShow();
|
||||
virtual void select(size_t item);
|
||||
virtual size_t selection() const;
|
||||
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const;
|
||||
virtual void onShow();
|
||||
virtual void select(size_t item);
|
||||
virtual size_t selection() const;
|
||||
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
+90
-90
@@ -20,139 +20,139 @@ DECLARE_TYPEOF_COLLECTION(ColorField::ChoiceP);
|
||||
// A drop down list of color choices
|
||||
class DropDownColorList : public DropDownList {
|
||||
public:
|
||||
DropDownColorList(Window* parent, ColorValueEditor& cve);
|
||||
|
||||
protected:
|
||||
virtual size_t itemCount() const;
|
||||
virtual bool lineBelow(size_t item) const;
|
||||
virtual String itemText(size_t item) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
|
||||
virtual void select(size_t item);
|
||||
virtual size_t selection() const;
|
||||
|
||||
DropDownColorList(Window* parent, ColorValueEditor& cve);
|
||||
|
||||
protected:
|
||||
virtual size_t itemCount() const;
|
||||
virtual bool lineBelow(size_t item) const;
|
||||
virtual String itemText(size_t item) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
|
||||
virtual void select(size_t item);
|
||||
virtual size_t selection() const;
|
||||
|
||||
private:
|
||||
ColorValueEditor& cve;
|
||||
mutable Color default_color;
|
||||
ColorValueEditor& cve;
|
||||
mutable Color default_color;
|
||||
|
||||
inline const ColorField& field() const { return cve.field(); }
|
||||
// default, custom item
|
||||
bool hasDefault() const { return field().default_script; }
|
||||
bool hasCustom() const { return field().allow_custom; }
|
||||
bool isDefault(size_t item) const {
|
||||
return item == 0 && hasDefault();
|
||||
}
|
||||
bool isCustom(size_t item) const {
|
||||
return item == itemCount() - 1 && hasCustom();
|
||||
}
|
||||
inline const ColorField& field() const { return cve.field(); }
|
||||
// default, custom item
|
||||
bool hasDefault() const { return field().default_script; }
|
||||
bool hasCustom() const { return field().allow_custom; }
|
||||
bool isDefault(size_t item) const {
|
||||
return item == 0 && hasDefault();
|
||||
}
|
||||
bool isCustom(size_t item) const {
|
||||
return item == itemCount() - 1 && hasCustom();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
DropDownColorList::DropDownColorList(Window* parent, ColorValueEditor& cve)
|
||||
: DropDownList(parent, false, &cve)
|
||||
, cve(cve)
|
||||
: DropDownList(parent, false, &cve)
|
||||
, cve(cve)
|
||||
{
|
||||
icon_size.width = 25;
|
||||
if (item_size.height < 16) {
|
||||
text_offset = (16 - (int)item_size.height) / 2;
|
||||
item_size.height = 16;
|
||||
}
|
||||
icon_size.width = 25;
|
||||
if (item_size.height < 16) {
|
||||
text_offset = (16 - (int)item_size.height) / 2;
|
||||
item_size.height = 16;
|
||||
}
|
||||
}
|
||||
|
||||
size_t DropDownColorList::itemCount() const {
|
||||
return cve.field().choices.size() + hasDefault() + hasCustom();
|
||||
return cve.field().choices.size() + hasDefault() + hasCustom();
|
||||
}
|
||||
bool DropDownColorList::lineBelow(size_t item) const {
|
||||
return isDefault(item) || isCustom(item + 1); // below default item, above custom item
|
||||
return isDefault(item) || isCustom(item + 1); // below default item, above custom item
|
||||
}
|
||||
String DropDownColorList::itemText(size_t item) const {
|
||||
if (isDefault(item)) {
|
||||
return field().default_name;
|
||||
} else if (isCustom(item)) {
|
||||
return _("Custom...");
|
||||
} else {
|
||||
return field().choices[item - hasDefault()]->name;
|
||||
}
|
||||
if (isDefault(item)) {
|
||||
return field().default_name;
|
||||
} else if (isCustom(item)) {
|
||||
return _("Custom...");
|
||||
} else {
|
||||
return field().choices[item - hasDefault()]->name;
|
||||
}
|
||||
}
|
||||
|
||||
void DropDownColorList::drawIcon(DC& dc, int x, int y, size_t item, bool selected) const {
|
||||
Color col;
|
||||
if (isDefault(item)) {
|
||||
col = default_color;
|
||||
} else if (isCustom(item)) {
|
||||
col = cve.value().value();
|
||||
} else {
|
||||
col = field().choices[item - hasDefault()]->color;
|
||||
}
|
||||
// draw a rectangle with the right color
|
||||
dc.SetPen(wxSystemSettings::GetColour(selected ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT));
|
||||
dc.SetBrush(col);
|
||||
dc.DrawRectangle(x+1, y+1, (int)icon_size.width-2, (int)item_size.height-2);
|
||||
Color col;
|
||||
if (isDefault(item)) {
|
||||
col = default_color;
|
||||
} else if (isCustom(item)) {
|
||||
col = cve.value().value();
|
||||
} else {
|
||||
col = field().choices[item - hasDefault()]->color;
|
||||
}
|
||||
// draw a rectangle with the right color
|
||||
dc.SetPen(wxSystemSettings::GetColour(selected ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT));
|
||||
dc.SetBrush(col);
|
||||
dc.DrawRectangle(x+1, y+1, (int)icon_size.width-2, (int)item_size.height-2);
|
||||
}
|
||||
|
||||
|
||||
size_t DropDownColorList::selection() const {
|
||||
// find selected color
|
||||
size_t selection = hasCustom() ? itemCount() - 1 : NO_SELECTION;
|
||||
size_t i = 0;
|
||||
FOR_EACH_CONST(c, field().choices) {
|
||||
if (c->color == cve.value().value()) {
|
||||
selection = i + hasDefault();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// has default item?
|
||||
if (hasDefault() && cve.value().value.isDefault()) {
|
||||
// default is selected
|
||||
default_color = cve.value().value();
|
||||
return 0;
|
||||
} else if (hasDefault()) {
|
||||
// evaluate script to find default color
|
||||
default_color = *field().default_script.invoke(cve.viewer.getContext());
|
||||
}
|
||||
return selection;
|
||||
// find selected color
|
||||
size_t selection = hasCustom() ? itemCount() - 1 : NO_SELECTION;
|
||||
size_t i = 0;
|
||||
FOR_EACH_CONST(c, field().choices) {
|
||||
if (c->color == cve.value().value()) {
|
||||
selection = i + hasDefault();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// has default item?
|
||||
if (hasDefault() && cve.value().value.isDefault()) {
|
||||
// default is selected
|
||||
default_color = cve.value().value();
|
||||
return 0;
|
||||
} else if (hasDefault()) {
|
||||
// evaluate script to find default color
|
||||
default_color = *field().default_script.invoke(cve.viewer.getContext());
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
void DropDownColorList::select(size_t item) {
|
||||
if (isDefault(item)) {
|
||||
cve.change( Defaultable<Color>());
|
||||
} else if (isCustom(item)) {
|
||||
cve.changeCustom();
|
||||
} else {
|
||||
cve.change(field().choices[item - hasDefault()]->color);
|
||||
}
|
||||
if (isDefault(item)) {
|
||||
cve.change( Defaultable<Color>());
|
||||
} else if (isCustom(item)) {
|
||||
cve.changeCustom();
|
||||
} else {
|
||||
cve.change(field().choices[item - hasDefault()]->color);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : ColorValueEditor
|
||||
|
||||
IMPLEMENT_VALUE_EDITOR(Color)
|
||||
, drop_down(new DropDownColorList(&editor(), *this))
|
||||
, drop_down(new DropDownColorList(&editor(), *this))
|
||||
{}
|
||||
|
||||
bool ColorValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
|
||||
return drop_down->onMouseInParent(ev, !nativeLook());
|
||||
return drop_down->onMouseInParent(ev, !nativeLook());
|
||||
}
|
||||
bool ColorValueEditor::onChar(wxKeyEvent& ev) {
|
||||
return drop_down->onCharInParent(ev);
|
||||
return drop_down->onCharInParent(ev);
|
||||
}
|
||||
void ColorValueEditor::onLoseFocus() {
|
||||
drop_down->hide(false);
|
||||
drop_down->hide(false);
|
||||
}
|
||||
|
||||
void ColorValueEditor::draw(RotatedDC& dc) {
|
||||
ColorValueViewer::draw(dc);
|
||||
if (nativeLook()) {
|
||||
draw_drop_down_arrow(&editor(), dc.getDC(), dc.trRectToBB(dc.getInternalRect().grow(1)), drop_down->IsShown());
|
||||
}
|
||||
ColorValueViewer::draw(dc);
|
||||
if (nativeLook()) {
|
||||
draw_drop_down_arrow(&editor(), dc.getDC(), dc.trRectToBB(dc.getInternalRect().grow(1)), drop_down->IsShown());
|
||||
}
|
||||
}
|
||||
void ColorValueEditor::determineSize(bool) {
|
||||
style().height = 20;
|
||||
style().height = 20;
|
||||
}
|
||||
|
||||
void ColorValueEditor::change(const Defaultable<Color>& c) {
|
||||
addAction(value_action(valueP(), c));
|
||||
addAction(value_action(valueP(), c));
|
||||
}
|
||||
void ColorValueEditor::changeCustom() {
|
||||
Color c = wxGetColourFromUser(0, value().value());
|
||||
if (c.Ok()) change(c);
|
||||
Color c = wxGetColourFromUser(0, value().value());
|
||||
if (c.Ok()) change(c);
|
||||
}
|
||||
|
||||
+16
-16
@@ -20,23 +20,23 @@ DECLARE_SHARED_POINTER_TYPE(DropDownList);
|
||||
/// An editor 'control' for editing ColorValues
|
||||
class ColorValueEditor : public ColorValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(Color);
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
virtual bool onLeftDown(const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void determineSize(bool);
|
||||
|
||||
DECLARE_VALUE_EDITOR(Color);
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
virtual bool onLeftDown(const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void determineSize(bool);
|
||||
|
||||
private:
|
||||
DropDownListP drop_down;
|
||||
friend class DropDownColorList;
|
||||
/// Change the color
|
||||
void change(const Defaultable<Color>& c);
|
||||
/// Change to a custom color
|
||||
void changeCustom();
|
||||
DropDownListP drop_down;
|
||||
friend class DropDownColorList;
|
||||
/// Change the color
|
||||
void change(const Defaultable<Color>& c);
|
||||
/// Change to a custom color
|
||||
void changeCustom();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// ----------------------------------------------------------------------------- : ValueEditor
|
||||
|
||||
void ValueEditor::addAction(ValueAction* a) {
|
||||
if (a) {
|
||||
a->isOnCard(editor().getCard().get());
|
||||
editor().addAction(a);
|
||||
}
|
||||
if (a) {
|
||||
a->isOnCard(editor().getCard().get());
|
||||
editor().addAction(a);
|
||||
}
|
||||
}
|
||||
|
||||
+111
-111
@@ -35,123 +35,123 @@ DECLARE_POINTER_TYPE(ValueActionPerformer);
|
||||
*/
|
||||
class ValueEditor {
|
||||
public:
|
||||
virtual ~ValueEditor() {}
|
||||
// --------------------------------------------------- : Events
|
||||
|
||||
/// This editor gains focus
|
||||
virtual void onFocus() {}
|
||||
/// This editor loses focus
|
||||
virtual void onLoseFocus() {}
|
||||
|
||||
/// Handle mouse events, return true if the event is used
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onLeftUp (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onLeftDClick (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onRightDown (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onMotion (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual void onMouseLeave (const RealPoint& pos, wxMouseEvent& ev) {}
|
||||
virtual bool onMouseWheel (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
|
||||
/// Key events
|
||||
virtual bool onChar(wxKeyEvent& ev) { return false; }
|
||||
|
||||
/// a context menu is requested, add extra items to the menu m
|
||||
/** return false to suppress menu */
|
||||
virtual bool onContextMenu(IconMenu& m, wxContextMenuEvent& ev) { return true; }
|
||||
/// Get a special menu, events will be sent to onMenu
|
||||
virtual wxMenu* getMenu(int type) const { return nullptr; }
|
||||
/// A menu item was selected, return true if the command was processed
|
||||
virtual bool onCommand(int id) { return false; }
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
|
||||
/// This editor can be copied from right now
|
||||
virtual bool canCopy() const { return false; }
|
||||
/// This editor can be cut from right now
|
||||
virtual bool canCut() const { return canCopy(); }
|
||||
/// This editor can be pasted to right now
|
||||
/** this function should also check the data on the clipboard has the right format */
|
||||
virtual bool canPaste() const { return false; }
|
||||
/// Copies from this field editor, returns success
|
||||
virtual bool doCopy() { return false; }
|
||||
/// Deletes the selection from this field editor, cut = copy + delete, returns success
|
||||
virtual bool doDelete() { return false; }
|
||||
/// Cuts the selection from this field editor
|
||||
bool doCut() { return doCopy() && doDelete(); }
|
||||
/// Initiate pasting in this field editor,
|
||||
/** should again check if pasting is possible and fail silently if not, returns success */
|
||||
virtual bool doPaste() { return false; }
|
||||
|
||||
// --------------------------------------------------- : Formating
|
||||
|
||||
/// Is the given type of formatting change supported?
|
||||
virtual bool canFormat(int type) const { return false; }
|
||||
/// Is the given type of formatting enabled for the current selection?
|
||||
virtual bool hasFormat(int type) const { return false; }
|
||||
/// Toggle the given type of formatting for the current selection
|
||||
virtual void doFormat(int type) { assert(false); }
|
||||
|
||||
// --------------------------------------------------- : Selection
|
||||
|
||||
/// Select the specified range (if it makes sense)
|
||||
virtual void select(size_t start, size_t end) {}
|
||||
/// Determine the selected range
|
||||
virtual size_t selectionStart() const { return 0; }
|
||||
virtual size_t selectionEnd() const { return 0; }
|
||||
|
||||
/// Insert the given text (replacing the current selection)
|
||||
virtual void insert(const String& text, const String& action_name) {};
|
||||
|
||||
// --------------------------------------------------- : Search / replace
|
||||
|
||||
/// Do a search or replace action for the given FindInfo
|
||||
/** If from_start == false: searches only from the current selection onward (or backward),
|
||||
* excluding the sellection itself.
|
||||
* If from_start == true: searches everything
|
||||
*
|
||||
* Returns true if we are done and searching should be ended.
|
||||
*/
|
||||
virtual bool search(FindInfo& find, bool from_start) { return false; }
|
||||
|
||||
// --------------------------------------------------- : Other
|
||||
|
||||
/// The cursor type to use when the mouse is over this control
|
||||
virtual wxCursor cursor(const RealPoint& pos) const { return wxCursor(); }
|
||||
/// Determines prefered size in the native look, update the style
|
||||
virtual void determineSize(bool force_fit = false) {}
|
||||
/// Should a label and control border be drawn in the native look?
|
||||
virtual bool drawLabel() const { return true; }
|
||||
/// The editor is shown or hidden
|
||||
virtual void onShow(bool) {}
|
||||
|
||||
// --------------------------------------------------- : Helpers
|
||||
virtual ~ValueEditor() {}
|
||||
// --------------------------------------------------- : Events
|
||||
|
||||
/// This editor gains focus
|
||||
virtual void onFocus() {}
|
||||
/// This editor loses focus
|
||||
virtual void onLoseFocus() {}
|
||||
|
||||
/// Handle mouse events, return true if the event is used
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onLeftUp (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onLeftDClick (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onRightDown (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual bool onMotion (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
virtual void onMouseLeave (const RealPoint& pos, wxMouseEvent& ev) {}
|
||||
virtual bool onMouseWheel (const RealPoint& pos, wxMouseEvent& ev) { return false; }
|
||||
|
||||
/// Key events
|
||||
virtual bool onChar(wxKeyEvent& ev) { return false; }
|
||||
|
||||
/// a context menu is requested, add extra items to the menu m
|
||||
/** return false to suppress menu */
|
||||
virtual bool onContextMenu(IconMenu& m, wxContextMenuEvent& ev) { return true; }
|
||||
/// Get a special menu, events will be sent to onMenu
|
||||
virtual wxMenu* getMenu(int type) const { return nullptr; }
|
||||
/// A menu item was selected, return true if the command was processed
|
||||
virtual bool onCommand(int id) { return false; }
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
|
||||
/// This editor can be copied from right now
|
||||
virtual bool canCopy() const { return false; }
|
||||
/// This editor can be cut from right now
|
||||
virtual bool canCut() const { return canCopy(); }
|
||||
/// This editor can be pasted to right now
|
||||
/** this function should also check the data on the clipboard has the right format */
|
||||
virtual bool canPaste() const { return false; }
|
||||
/// Copies from this field editor, returns success
|
||||
virtual bool doCopy() { return false; }
|
||||
/// Deletes the selection from this field editor, cut = copy + delete, returns success
|
||||
virtual bool doDelete() { return false; }
|
||||
/// Cuts the selection from this field editor
|
||||
bool doCut() { return doCopy() && doDelete(); }
|
||||
/// Initiate pasting in this field editor,
|
||||
/** should again check if pasting is possible and fail silently if not, returns success */
|
||||
virtual bool doPaste() { return false; }
|
||||
|
||||
// --------------------------------------------------- : Formating
|
||||
|
||||
/// Is the given type of formatting change supported?
|
||||
virtual bool canFormat(int type) const { return false; }
|
||||
/// Is the given type of formatting enabled for the current selection?
|
||||
virtual bool hasFormat(int type) const { return false; }
|
||||
/// Toggle the given type of formatting for the current selection
|
||||
virtual void doFormat(int type) { assert(false); }
|
||||
|
||||
// --------------------------------------------------- : Selection
|
||||
|
||||
/// Select the specified range (if it makes sense)
|
||||
virtual void select(size_t start, size_t end) {}
|
||||
/// Determine the selected range
|
||||
virtual size_t selectionStart() const { return 0; }
|
||||
virtual size_t selectionEnd() const { return 0; }
|
||||
|
||||
/// Insert the given text (replacing the current selection)
|
||||
virtual void insert(const String& text, const String& action_name) {};
|
||||
|
||||
// --------------------------------------------------- : Search / replace
|
||||
|
||||
/// Do a search or replace action for the given FindInfo
|
||||
/** If from_start == false: searches only from the current selection onward (or backward),
|
||||
* excluding the sellection itself.
|
||||
* If from_start == true: searches everything
|
||||
*
|
||||
* Returns true if we are done and searching should be ended.
|
||||
*/
|
||||
virtual bool search(FindInfo& find, bool from_start) { return false; }
|
||||
|
||||
// --------------------------------------------------- : Other
|
||||
|
||||
/// The cursor type to use when the mouse is over this control
|
||||
virtual wxCursor cursor(const RealPoint& pos) const { return wxCursor(); }
|
||||
/// Determines prefered size in the native look, update the style
|
||||
virtual void determineSize(bool force_fit = false) {}
|
||||
/// Should a label and control border be drawn in the native look?
|
||||
virtual bool drawLabel() const { return true; }
|
||||
/// The editor is shown or hidden
|
||||
virtual void onShow(bool) {}
|
||||
|
||||
// --------------------------------------------------- : Helpers
|
||||
protected:
|
||||
/// Retrieve the parent editor object
|
||||
virtual DataEditor& editor() const = 0;
|
||||
|
||||
/// Perform an action
|
||||
void addAction(ValueAction* a);
|
||||
/// Retrieve the parent editor object
|
||||
virtual DataEditor& editor() const = 0;
|
||||
|
||||
/// Perform an action
|
||||
void addAction(ValueAction* a);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Utility
|
||||
|
||||
#define DECLARE_VALUE_EDITOR(Type) \
|
||||
Type##ValueEditor(DataEditor& parent, const Type##StyleP& style); \
|
||||
virtual ValueEditor* getEditor() { return this; } \
|
||||
private: \
|
||||
/** Retrieve the parent editor object */ \
|
||||
inline DataEditor& editor() const { \
|
||||
return static_cast<DataEditor&>(viewer); \
|
||||
} \
|
||||
public:
|
||||
#define DECLARE_VALUE_EDITOR(Type) \
|
||||
Type##ValueEditor(DataEditor& parent, const Type##StyleP& style); \
|
||||
virtual ValueEditor* getEditor() { return this; } \
|
||||
private: \
|
||||
/** Retrieve the parent editor object */ \
|
||||
inline DataEditor& editor() const { \
|
||||
return static_cast<DataEditor&>(viewer); \
|
||||
} \
|
||||
public:
|
||||
|
||||
#define IMPLEMENT_VALUE_EDITOR(Type) \
|
||||
ValueViewerP Type##Style::makeEditor(DataEditor& parent, const StyleP& thisP) { \
|
||||
assert(thisP.get() == this); \
|
||||
return ValueViewerP(new Type##ValueEditor(parent, static_pointer_cast<Type##Style>(thisP))); \
|
||||
} \
|
||||
Type##ValueEditor::Type##ValueEditor(DataEditor& parent, const Type##StyleP& style) \
|
||||
: Type##ValueViewer(parent, style)
|
||||
#define IMPLEMENT_VALUE_EDITOR(Type) \
|
||||
ValueViewerP Type##Style::makeEditor(DataEditor& parent, const StyleP& thisP) { \
|
||||
assert(thisP.get() == this); \
|
||||
return ValueViewerP(new Type##ValueEditor(parent, static_pointer_cast<Type##Style>(thisP))); \
|
||||
} \
|
||||
Type##ValueEditor::Type##ValueEditor(DataEditor& parent, const Type##StyleP& style) \
|
||||
: Type##ValueViewer(parent, style)
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
|
||||
+54
-54
@@ -18,82 +18,82 @@
|
||||
IMPLEMENT_VALUE_EDITOR(Image) {}
|
||||
|
||||
bool ImageValueEditor::onLeftDClick(const RealPoint&, wxMouseEvent&) {
|
||||
String filename = wxFileSelector(_("Open image file"), settings.default_image_dir, _(""), _(""),
|
||||
_("All images|*.bmp;*.jpg;*.png;*.gif|Windows bitmaps (*.bmp)|*.bmp|JPEG images (*.jpg;*.jpeg)|*.jpg;*.jpeg|PNG images (*.png)|*.png|GIF images (*.gif)|*.gif|TIFF images (*.tif;*.tiff)|*.tif;*.tiff"),
|
||||
wxOPEN, wxGetTopLevelParent(&editor()));
|
||||
if (!filename.empty()) {
|
||||
settings.default_image_dir = wxPathOnly(filename);
|
||||
sliceImage(wxImage(filename));
|
||||
}
|
||||
return true;
|
||||
String filename = wxFileSelector(_("Open image file"), settings.default_image_dir, _(""), _(""),
|
||||
_("All images|*.bmp;*.jpg;*.png;*.gif|Windows bitmaps (*.bmp)|*.bmp|JPEG images (*.jpg;*.jpeg)|*.jpg;*.jpeg|PNG images (*.png)|*.png|GIF images (*.gif)|*.gif|TIFF images (*.tif;*.tiff)|*.tif;*.tiff"),
|
||||
wxOPEN, wxGetTopLevelParent(&editor()));
|
||||
if (!filename.empty()) {
|
||||
settings.default_image_dir = wxPathOnly(filename);
|
||||
sliceImage(wxImage(filename));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImageValueEditor::sliceImage(const Image& image) {
|
||||
if (!image.Ok()) return;
|
||||
// mask
|
||||
GeneratedImage::Options options((int)style().width, (int)style().height, &viewer.getStylePackage(), &viewer.getLocalPackage());
|
||||
AlphaMask mask;
|
||||
style().mask.getNoCache(options,mask);
|
||||
// slice
|
||||
ImageSliceWindow s(wxGetTopLevelParent(&editor()), image, style().getSize(), mask);
|
||||
// clicked ok?
|
||||
if (s.ShowModal() == wxID_OK) {
|
||||
// store the image into the set
|
||||
FileName new_image_file = getLocalPackage().newFileName(field().name,_("")); // a new unique name in the package
|
||||
Image img = s.getImage();
|
||||
img.SaveFile(getLocalPackage().nameOut(new_image_file), wxBITMAP_TYPE_PNG); // always use PNG images, see #69. Disk space is cheap anyway.
|
||||
addAction(value_action(valueP(), new_image_file));
|
||||
}
|
||||
if (!image.Ok()) return;
|
||||
// mask
|
||||
GeneratedImage::Options options((int)style().width, (int)style().height, &viewer.getStylePackage(), &viewer.getLocalPackage());
|
||||
AlphaMask mask;
|
||||
style().mask.getNoCache(options,mask);
|
||||
// slice
|
||||
ImageSliceWindow s(wxGetTopLevelParent(&editor()), image, style().getSize(), mask);
|
||||
// clicked ok?
|
||||
if (s.ShowModal() == wxID_OK) {
|
||||
// store the image into the set
|
||||
FileName new_image_file = getLocalPackage().newFileName(field().name,_("")); // a new unique name in the package
|
||||
Image img = s.getImage();
|
||||
img.SaveFile(getLocalPackage().nameOut(new_image_file), wxBITMAP_TYPE_PNG); // always use PNG images, see #69. Disk space is cheap anyway.
|
||||
addAction(value_action(valueP(), new_image_file));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Clipboard
|
||||
|
||||
bool ImageValueEditor::canCopy() const {
|
||||
return !value().filename.empty();
|
||||
return !value().filename.empty();
|
||||
}
|
||||
|
||||
bool ImageValueEditor::canPaste() const {
|
||||
return wxTheClipboard->IsSupported(wxDF_BITMAP) &&
|
||||
!wxTheClipboard->IsSupported(CardsDataObject::format); // we don't want to (accidentally) paste card images
|
||||
return wxTheClipboard->IsSupported(wxDF_BITMAP) &&
|
||||
!wxTheClipboard->IsSupported(CardsDataObject::format); // we don't want to (accidentally) paste card images
|
||||
}
|
||||
|
||||
bool ImageValueEditor::doCopy() {
|
||||
// load image
|
||||
InputStreamP image_file = getLocalPackage().openIn(value().filename);
|
||||
Image image;
|
||||
if (!image.LoadFile(*image_file)) return false;
|
||||
// set data
|
||||
if (!wxTheClipboard->Open()) return false;
|
||||
bool ok = wxTheClipboard->SetData(new wxBitmapDataObject(image));
|
||||
wxTheClipboard->Close();
|
||||
return ok;
|
||||
// load image
|
||||
InputStreamP image_file = getLocalPackage().openIn(value().filename);
|
||||
Image image;
|
||||
if (!image.LoadFile(*image_file)) return false;
|
||||
// set data
|
||||
if (!wxTheClipboard->Open()) return false;
|
||||
bool ok = wxTheClipboard->SetData(new wxBitmapDataObject(image));
|
||||
wxTheClipboard->Close();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool ImageValueEditor::doPaste() {
|
||||
// get bitmap
|
||||
if (!wxTheClipboard->Open()) return false;
|
||||
wxBitmapDataObject data;
|
||||
bool ok = wxTheClipboard->GetData(data);
|
||||
wxTheClipboard->Close();
|
||||
if (!ok) return false;
|
||||
// slice
|
||||
sliceImage(data.GetBitmap().ConvertToImage());
|
||||
return true;
|
||||
// get bitmap
|
||||
if (!wxTheClipboard->Open()) return false;
|
||||
wxBitmapDataObject data;
|
||||
bool ok = wxTheClipboard->GetData(data);
|
||||
wxTheClipboard->Close();
|
||||
if (!ok) return false;
|
||||
// slice
|
||||
sliceImage(data.GetBitmap().ConvertToImage());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageValueEditor::doDelete() {
|
||||
addAction(value_action(valueP(), FileName()));
|
||||
return true;
|
||||
addAction(value_action(valueP(), FileName()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ImageValueEditor::onChar(wxKeyEvent& ev) {
|
||||
if (ev.AltDown() || ev.ShiftDown() || ev.ControlDown()) return false;
|
||||
switch (ev.GetKeyCode()) {
|
||||
case WXK_DELETE:
|
||||
doDelete();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (ev.AltDown() || ev.ShiftDown() || ev.ControlDown()) return false;
|
||||
switch (ev.GetKeyCode()) {
|
||||
case WXK_DELETE:
|
||||
doDelete();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-16
@@ -18,23 +18,23 @@
|
||||
/// An editor 'control' for editing ImageValues
|
||||
class ImageValueEditor : public ImageValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(Image);
|
||||
|
||||
virtual bool onLeftDClick(const RealPoint&, wxMouseEvent&);
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
|
||||
virtual bool canCopy() const;
|
||||
virtual bool canPaste() const;
|
||||
virtual bool doCopy();
|
||||
virtual bool doPaste();
|
||||
virtual bool doDelete();
|
||||
|
||||
virtual bool onChar(wxKeyEvent&);
|
||||
|
||||
DECLARE_VALUE_EDITOR(Image);
|
||||
|
||||
virtual bool onLeftDClick(const RealPoint&, wxMouseEvent&);
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
|
||||
virtual bool canCopy() const;
|
||||
virtual bool canPaste() const;
|
||||
virtual bool doCopy();
|
||||
virtual bool doPaste();
|
||||
virtual bool doDelete();
|
||||
|
||||
virtual bool onChar(wxKeyEvent&);
|
||||
|
||||
private:
|
||||
// Open the image slice window showing the give image
|
||||
void sliceImage(const Image&);
|
||||
// Open the image slice window showing the give image
|
||||
void sliceImage(const Image&);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
IMPLEMENT_VALUE_EDITOR(Info) {}
|
||||
|
||||
void InfoValueEditor::determineSize(bool) {
|
||||
style().height = 26;
|
||||
style().height = 26;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
/// An editor 'control' for editing InfoValues
|
||||
class InfoValueEditor : public InfoValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(Info);
|
||||
|
||||
virtual void determineSize(bool);
|
||||
virtual bool drawLabel() const { return false; }
|
||||
DECLARE_VALUE_EDITOR(Info);
|
||||
|
||||
virtual void determineSize(bool);
|
||||
virtual bool drawLabel() const { return false; }
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
+116
-116
@@ -17,73 +17,73 @@
|
||||
/// A drop down list of color choices
|
||||
class DropDownMultipleChoiceList : public DropDownChoiceListBase {
|
||||
public:
|
||||
DropDownMultipleChoiceList(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group);
|
||||
|
||||
DropDownMultipleChoiceList(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group);
|
||||
|
||||
protected:
|
||||
virtual void onShow();
|
||||
virtual void select(size_t item);
|
||||
virtual size_t selection() const;
|
||||
virtual bool stayOpen(size_t selection) const { return true; }
|
||||
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
virtual void onShow();
|
||||
virtual void select(size_t item);
|
||||
virtual size_t selection() const;
|
||||
virtual bool stayOpen(size_t selection) const { return true; }
|
||||
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
};
|
||||
|
||||
DropDownMultipleChoiceList::DropDownMultipleChoiceList
|
||||
(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group)
|
||||
: DropDownChoiceListBase(parent, is_submenu, cve, group)
|
||||
(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group)
|
||||
: DropDownChoiceListBase(parent, is_submenu, cve, group)
|
||||
{
|
||||
icon_size.width += 16;
|
||||
icon_size.width += 16;
|
||||
}
|
||||
|
||||
void DropDownMultipleChoiceList::select(size_t item) {
|
||||
MultipleChoiceValueEditor& mcve = dynamic_cast<MultipleChoiceValueEditor&>(cve);
|
||||
if (isFieldDefault(item)) {
|
||||
mcve.toggleDefault();
|
||||
} else {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
mcve.toggle(choice->first_id);
|
||||
}
|
||||
// keep the box open
|
||||
DropDownChoiceListBase::onShow(); // update 'enabled'
|
||||
MultipleChoiceValueEditor& mcve = dynamic_cast<MultipleChoiceValueEditor&>(cve);
|
||||
if (isFieldDefault(item)) {
|
||||
mcve.toggleDefault();
|
||||
} else {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
mcve.toggle(choice->first_id);
|
||||
}
|
||||
// keep the box open
|
||||
DropDownChoiceListBase::onShow(); // update 'enabled'
|
||||
}
|
||||
|
||||
void DropDownMultipleChoiceList::drawIcon(DC& dc, int x, int y, size_t item, bool selected) const {
|
||||
// is this item active/checked?
|
||||
bool active = false;
|
||||
bool radio = false;
|
||||
if (!isFieldDefault(item)) {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
active = dynamic_cast<MultipleChoiceValueEditor&>(cve).active[choice->first_id];
|
||||
radio = choice->type == CHOICE_TYPE_RADIO;
|
||||
} else {
|
||||
active = dynamic_cast<MultipleChoiceValueEditor&>(cve).value().value.isDefault();
|
||||
}
|
||||
// draw checkbox
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
dc.DrawRectangle(x,y,16,16);
|
||||
wxRect rect = RealRect(x+2,y+2,12,12);
|
||||
if (radio) {
|
||||
draw_radiobox(nullptr, dc, rect, active, itemEnabled(item));
|
||||
} else {
|
||||
draw_checkbox(nullptr, dc, rect, active, itemEnabled(item));
|
||||
}
|
||||
// draw icon
|
||||
DropDownChoiceListBase::drawIcon(dc, x + 16, y, item, selected);
|
||||
// is this item active/checked?
|
||||
bool active = false;
|
||||
bool radio = false;
|
||||
if (!isFieldDefault(item)) {
|
||||
ChoiceField::ChoiceP choice = getChoice(item);
|
||||
active = dynamic_cast<MultipleChoiceValueEditor&>(cve).active[choice->first_id];
|
||||
radio = choice->type == CHOICE_TYPE_RADIO;
|
||||
} else {
|
||||
active = dynamic_cast<MultipleChoiceValueEditor&>(cve).value().value.isDefault();
|
||||
}
|
||||
// draw checkbox
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
dc.DrawRectangle(x,y,16,16);
|
||||
wxRect rect = RealRect(x+2,y+2,12,12);
|
||||
if (radio) {
|
||||
draw_radiobox(nullptr, dc, rect, active, itemEnabled(item));
|
||||
} else {
|
||||
draw_checkbox(nullptr, dc, rect, active, itemEnabled(item));
|
||||
}
|
||||
// draw icon
|
||||
DropDownChoiceListBase::drawIcon(dc, x + 16, y, item, selected);
|
||||
}
|
||||
|
||||
void DropDownMultipleChoiceList::onShow() {
|
||||
DropDownChoiceListBase::onShow();
|
||||
// we need thumbnail images soon
|
||||
const_cast<DropDownMultipleChoiceList*>(this)->generateThumbnailImages();
|
||||
DropDownChoiceListBase::onShow();
|
||||
// we need thumbnail images soon
|
||||
const_cast<DropDownMultipleChoiceList*>(this)->generateThumbnailImages();
|
||||
}
|
||||
|
||||
size_t DropDownMultipleChoiceList::selection() const {
|
||||
return NO_SELECTION; // we don't know the selection
|
||||
return NO_SELECTION; // we don't know the selection
|
||||
}
|
||||
|
||||
DropDownList* DropDownMultipleChoiceList::createSubMenu(ChoiceField::ChoiceP group) const {
|
||||
return new DropDownMultipleChoiceList(static_cast<Window*>(const_cast<DropDownMultipleChoiceList*>(this)), true, cve, group);
|
||||
return new DropDownMultipleChoiceList(static_cast<Window*>(const_cast<DropDownMultipleChoiceList*>(this)), true, cve, group);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : MultipleChoiceValueEditor
|
||||
@@ -91,95 +91,95 @@ DropDownList* DropDownMultipleChoiceList::createSubMenu(ChoiceField::ChoiceP gro
|
||||
IMPLEMENT_VALUE_EDITOR(MultipleChoice) {}
|
||||
|
||||
MultipleChoiceValueEditor::~MultipleChoiceValueEditor() {
|
||||
thumbnail_thread.abort(this);
|
||||
thumbnail_thread.abort(this);
|
||||
}
|
||||
|
||||
DropDownList& MultipleChoiceValueEditor::initDropDown() {
|
||||
if (!drop_down) {
|
||||
drop_down.reset(new DropDownMultipleChoiceList(&editor(), false, *this, field().choices));
|
||||
}
|
||||
return *drop_down;
|
||||
if (!drop_down) {
|
||||
drop_down.reset(new DropDownMultipleChoiceList(&editor(), false, *this, field().choices));
|
||||
}
|
||||
return *drop_down;
|
||||
}
|
||||
|
||||
void MultipleChoiceValueEditor::determineSize(bool force_fit) {
|
||||
if (!nativeLook()) return;
|
||||
// item height
|
||||
item_height = 16;
|
||||
// height depends on number of items and item height
|
||||
int item_count = field().choices->lastId();
|
||||
style().height = item_count * item_height;
|
||||
if (!nativeLook()) return;
|
||||
// item height
|
||||
item_height = 16;
|
||||
// height depends on number of items and item height
|
||||
int item_count = field().choices->lastId();
|
||||
style().height = item_count * item_height;
|
||||
}
|
||||
|
||||
bool MultipleChoiceValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
|
||||
// find item under cursor
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
// TODO: determine actual item height
|
||||
if (item_height == 0) item_height = 16;
|
||||
|
||||
int id = (int)(pos.y / item_height);
|
||||
int end = field().choices->lastId();
|
||||
if (id >= 0 && id < end) {
|
||||
toggle(id);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// open a drop down menu
|
||||
return initDropDown().onMouseInParent(ev, style().popup_style == POPUP_DROPDOWN_IN_PLACE && !nativeLook());
|
||||
}
|
||||
return false;
|
||||
// find item under cursor
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
// TODO: determine actual item height
|
||||
if (item_height == 0) item_height = 16;
|
||||
|
||||
int id = (int)(pos.y / item_height);
|
||||
int end = field().choices->lastId();
|
||||
if (id >= 0 && id < end) {
|
||||
toggle(id);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// open a drop down menu
|
||||
return initDropDown().onMouseInParent(ev, style().popup_style == POPUP_DROPDOWN_IN_PLACE && !nativeLook());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool MultipleChoiceValueEditor::onChar(wxKeyEvent& ev) {
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
// todo;
|
||||
return false;
|
||||
} else {
|
||||
return initDropDown().onCharInParent(ev);
|
||||
}
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
// todo;
|
||||
return false;
|
||||
} else {
|
||||
return initDropDown().onCharInParent(ev);
|
||||
}
|
||||
}
|
||||
void MultipleChoiceValueEditor::onLoseFocus() {
|
||||
if (drop_down) drop_down->hide(false);
|
||||
if (drop_down) drop_down->hide(false);
|
||||
}
|
||||
|
||||
void MultipleChoiceValueEditor::onValueChange() {
|
||||
MultipleChoiceValueViewer::onValueChange();
|
||||
// determine active values
|
||||
active.clear();
|
||||
vector<String> selected;
|
||||
value().get(selected);
|
||||
vector<String>::iterator select_it = selected.begin();
|
||||
// for each choice...
|
||||
int end = field().choices->lastId();
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String choice = field().choices->choiceName(i);
|
||||
bool is_active = select_it != selected.end() && *select_it == choice;
|
||||
if (is_active) select_it++;
|
||||
active.push_back(is_active);
|
||||
}
|
||||
MultipleChoiceValueViewer::onValueChange();
|
||||
// determine active values
|
||||
active.clear();
|
||||
vector<String> selected;
|
||||
value().get(selected);
|
||||
vector<String>::iterator select_it = selected.begin();
|
||||
// for each choice...
|
||||
int end = field().choices->lastId();
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String choice = field().choices->choiceName(i);
|
||||
bool is_active = select_it != selected.end() && *select_it == choice;
|
||||
if (is_active) select_it++;
|
||||
active.push_back(is_active);
|
||||
}
|
||||
}
|
||||
|
||||
void MultipleChoiceValueEditor::toggle(int id) {
|
||||
String new_value;
|
||||
String toggled_choice;
|
||||
// old selection
|
||||
vector<String> selected;
|
||||
value().get(selected);
|
||||
vector<String>::iterator select_it = selected.begin();
|
||||
// copy selected choices to new value
|
||||
int end = field().choices->lastId();
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String choice = field().choices->choiceName(i);
|
||||
bool active = select_it != selected.end() && *select_it == choice;
|
||||
if (active) select_it++;
|
||||
if (active != (i == id)) {
|
||||
if (!new_value.empty()) new_value += _(", ");
|
||||
new_value += choice;
|
||||
}
|
||||
if (i == id) toggled_choice = choice;
|
||||
}
|
||||
// store value
|
||||
addAction(value_action(valueP(), new_value, toggled_choice));
|
||||
String new_value;
|
||||
String toggled_choice;
|
||||
// old selection
|
||||
vector<String> selected;
|
||||
value().get(selected);
|
||||
vector<String>::iterator select_it = selected.begin();
|
||||
// copy selected choices to new value
|
||||
int end = field().choices->lastId();
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String choice = field().choices->choiceName(i);
|
||||
bool active = select_it != selected.end() && *select_it == choice;
|
||||
if (active) select_it++;
|
||||
if (active != (i == id)) {
|
||||
if (!new_value.empty()) new_value += _(", ");
|
||||
new_value += choice;
|
||||
}
|
||||
if (i == id) toggled_choice = choice;
|
||||
}
|
||||
// store value
|
||||
addAction(value_action(valueP(), new_value, toggled_choice));
|
||||
}
|
||||
|
||||
void MultipleChoiceValueEditor::toggleDefault() {
|
||||
addAction(value_action(valueP(), Defaultable<String>(value().value(), !value().value.isDefault()), _("")));
|
||||
addAction(value_action(valueP(), Defaultable<String>(value().value(), !value().value.isDefault()), _("")));
|
||||
}
|
||||
|
||||
@@ -19,27 +19,27 @@
|
||||
/// An editor 'control' for editing MultipleChoiceValues
|
||||
class MultipleChoiceValueEditor : public MultipleChoiceValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(MultipleChoice);
|
||||
~MultipleChoiceValueEditor();
|
||||
|
||||
virtual void onValueChange();
|
||||
|
||||
virtual void determineSize(bool force_fit);
|
||||
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
DECLARE_VALUE_EDITOR(MultipleChoice);
|
||||
~MultipleChoiceValueEditor();
|
||||
|
||||
virtual void onValueChange();
|
||||
|
||||
virtual void determineSize(bool force_fit);
|
||||
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
private:
|
||||
DropDownListP drop_down;
|
||||
vector<int> active; ///< Which choices are active? (note: vector<bool> is evil)
|
||||
friend class DropDownMultipleChoiceList;
|
||||
/// Initialize the drop down list
|
||||
DropDownList& initDropDown();
|
||||
/// Toggle a choice or on or off
|
||||
void toggle(int id);
|
||||
/// Toggle defaultness or on or off
|
||||
void toggleDefault();
|
||||
DropDownListP drop_down;
|
||||
vector<int> active; ///< Which choices are active? (note: vector<bool> is evil)
|
||||
friend class DropDownMultipleChoiceList;
|
||||
/// Initialize the drop down list
|
||||
DropDownList& initDropDown();
|
||||
/// Toggle a choice or on or off
|
||||
void toggle(int id);
|
||||
/// Toggle defaultness or on or off
|
||||
void toggleDefault();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -19,69 +19,69 @@ DECLARE_TYPEOF_COLLECTION(PackageChoiceValueViewer::Item);
|
||||
/// A drop down list of color choices
|
||||
class DropDownPackageChoiceList : public DropDownList {
|
||||
public:
|
||||
DropDownPackageChoiceList(Window* parent, PackageChoiceValueEditor* editor);
|
||||
|
||||
DropDownPackageChoiceList(Window* parent, PackageChoiceValueEditor* editor);
|
||||
|
||||
protected:
|
||||
virtual size_t itemCount() const;
|
||||
virtual String itemText(size_t item) const;
|
||||
virtual bool lineBelow(size_t item) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
virtual void select(size_t selection);
|
||||
virtual size_t selection() const;
|
||||
|
||||
virtual size_t itemCount() const;
|
||||
virtual String itemText(size_t item) const;
|
||||
virtual bool lineBelow(size_t item) const;
|
||||
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
|
||||
virtual void select(size_t selection);
|
||||
virtual size_t selection() const;
|
||||
|
||||
private:
|
||||
PackageChoiceValueEditor& editor;
|
||||
PackageChoiceValueEditor& editor;
|
||||
};
|
||||
|
||||
DropDownPackageChoiceList::DropDownPackageChoiceList(Window* parent, PackageChoiceValueEditor* editor)
|
||||
: DropDownList(parent, false, editor)
|
||||
, editor(*editor)
|
||||
: DropDownList(parent, false, editor)
|
||||
, editor(*editor)
|
||||
{
|
||||
icon_size.width = 16;
|
||||
icon_size.height = 16;
|
||||
item_size.height = max(16., item_size.height);
|
||||
icon_size.width = 16;
|
||||
icon_size.height = 16;
|
||||
item_size.height = max(16., item_size.height);
|
||||
}
|
||||
|
||||
size_t DropDownPackageChoiceList::itemCount() const {
|
||||
return editor.items.size() + (editor.field().required ? 0 : 1);
|
||||
return editor.items.size() + (editor.field().required ? 0 : 1);
|
||||
}
|
||||
String DropDownPackageChoiceList::itemText(size_t item) const {
|
||||
if (item == 0 && !editor.field().required) return editor.field().empty_name;
|
||||
else {
|
||||
size_t i = item - !editor.field().required;
|
||||
return editor.items[i].name;
|
||||
}
|
||||
if (item == 0 && !editor.field().required) return editor.field().empty_name;
|
||||
else {
|
||||
size_t i = item - !editor.field().required;
|
||||
return editor.items[i].name;
|
||||
}
|
||||
}
|
||||
bool DropDownPackageChoiceList::lineBelow(size_t item) const {
|
||||
return item == 0 && !editor.field().required;
|
||||
return item == 0 && !editor.field().required;
|
||||
}
|
||||
|
||||
void DropDownPackageChoiceList::drawIcon(DC& dc, int x, int y, size_t item, bool selected) const {
|
||||
if (item == 0 && !editor.field().required) return;
|
||||
size_t i = item - !editor.field().required;
|
||||
const Bitmap& bmp = editor.items[i].image;
|
||||
if (bmp.Ok()) dc.DrawBitmap(bmp, x, y);
|
||||
if (item == 0 && !editor.field().required) return;
|
||||
size_t i = item - !editor.field().required;
|
||||
const Bitmap& bmp = editor.items[i].image;
|
||||
if (bmp.Ok()) dc.DrawBitmap(bmp, x, y);
|
||||
}
|
||||
|
||||
|
||||
void DropDownPackageChoiceList::select(size_t item) {
|
||||
String new_value;
|
||||
if (item != 0 || editor.field().required) {
|
||||
size_t i = item - !editor.field().required;
|
||||
new_value = editor.items[i].package_name;
|
||||
}
|
||||
editor.change(new_value);
|
||||
String new_value;
|
||||
if (item != 0 || editor.field().required) {
|
||||
size_t i = item - !editor.field().required;
|
||||
new_value = editor.items[i].package_name;
|
||||
}
|
||||
editor.change(new_value);
|
||||
}
|
||||
|
||||
size_t DropDownPackageChoiceList::selection() const {
|
||||
size_t n = 0;
|
||||
FOR_EACH(i, editor.items) {
|
||||
if (editor.value().package_name == i.package_name) {
|
||||
return n + !editor.field().required;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
return editor.field().required ? NO_SELECTION : 0;
|
||||
size_t n = 0;
|
||||
FOR_EACH(i, editor.items) {
|
||||
if (editor.value().package_name == i.package_name) {
|
||||
return n + !editor.field().required;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
return editor.field().required ? NO_SELECTION : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : PackageChoiceValueEditor
|
||||
@@ -89,32 +89,32 @@ size_t DropDownPackageChoiceList::selection() const {
|
||||
IMPLEMENT_VALUE_EDITOR(PackageChoice) {}
|
||||
|
||||
bool PackageChoiceValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
|
||||
if (!drop_down) initDropDown();
|
||||
return drop_down->onMouseInParent(ev, false);
|
||||
if (!drop_down) initDropDown();
|
||||
return drop_down->onMouseInParent(ev, false);
|
||||
}
|
||||
bool PackageChoiceValueEditor::onChar(wxKeyEvent& ev) {
|
||||
if (!drop_down) initDropDown();
|
||||
return drop_down->onCharInParent(ev);
|
||||
if (!drop_down) initDropDown();
|
||||
return drop_down->onCharInParent(ev);
|
||||
}
|
||||
void PackageChoiceValueEditor::onLoseFocus() {
|
||||
if (drop_down) drop_down->hide(false);
|
||||
if (drop_down) drop_down->hide(false);
|
||||
}
|
||||
|
||||
void PackageChoiceValueEditor::draw(RotatedDC& dc) {
|
||||
PackageChoiceValueViewer::draw(dc);
|
||||
if (nativeLook()) {
|
||||
draw_drop_down_arrow(&editor(), dc.getDC(), dc.trRectToBB(style().getInternalRect().grow(1)), drop_down && drop_down->IsShown());
|
||||
}
|
||||
PackageChoiceValueViewer::draw(dc);
|
||||
if (nativeLook()) {
|
||||
draw_drop_down_arrow(&editor(), dc.getDC(), dc.trRectToBB(style().getInternalRect().grow(1)), drop_down && drop_down->IsShown());
|
||||
}
|
||||
}
|
||||
void PackageChoiceValueEditor::determineSize(bool) {
|
||||
style().height = max(style().height(), 16.);
|
||||
style().height = max(style().height(), 16.);
|
||||
}
|
||||
|
||||
void PackageChoiceValueEditor::change(const String& c) {
|
||||
addAction(value_action(valueP(), c));
|
||||
addAction(value_action(valueP(), c));
|
||||
}
|
||||
|
||||
void PackageChoiceValueEditor::initDropDown() {
|
||||
if (drop_down) return;
|
||||
drop_down = shared(new DropDownPackageChoiceList(&editor(), this));
|
||||
if (drop_down) return;
|
||||
drop_down = shared(new DropDownPackageChoiceList(&editor(), this));
|
||||
}
|
||||
|
||||
@@ -20,21 +20,21 @@ DECLARE_SHARED_POINTER_TYPE(DropDownList);
|
||||
/// An editor 'control' for editing PackageChoiceValues
|
||||
class PackageChoiceValueEditor : public PackageChoiceValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(PackageChoice);
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void determineSize(bool force_fit);
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
DECLARE_VALUE_EDITOR(PackageChoice);
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void determineSize(bool force_fit);
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent& ev);
|
||||
virtual bool onChar(wxKeyEvent& ev);
|
||||
virtual void onLoseFocus();
|
||||
|
||||
private:
|
||||
DropDownListP drop_down;
|
||||
friend class DropDownPackageChoiceList;
|
||||
/// Change the choice
|
||||
void change(const String& c);
|
||||
/// Initialize the drop down list
|
||||
void initDropDown();
|
||||
DropDownListP drop_down;
|
||||
friend class DropDownPackageChoiceList;
|
||||
/// Change the choice
|
||||
void change(const String& c);
|
||||
/// Initialize the drop down list
|
||||
void initDropDown();
|
||||
};
|
||||
|
||||
|
||||
|
||||
+73
-73
@@ -15,107 +15,107 @@
|
||||
// ----------------------------------------------------------------------------- : SymbolValueEditor
|
||||
|
||||
IMPLEMENT_VALUE_EDITOR(Symbol)
|
||||
, button_down(-2)
|
||||
, button_down(-2)
|
||||
{
|
||||
button_images[0] = Bitmap(load_resource_image(_("edit_symbol")));
|
||||
button_images[0] = Bitmap(load_resource_image(_("edit_symbol")));
|
||||
}
|
||||
|
||||
void SymbolValueEditor::draw(RotatedDC& dc) {
|
||||
SymbolValueViewer::draw(dc);
|
||||
// draw helper text if there are no symbols
|
||||
if (symbols.empty()) {
|
||||
dc.SetFont(wxFont(10,wxSWISS,wxNORMAL,wxNORMAL));
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
RealSize text_size = dc.GetTextExtent(_("double click to edit symbol"));
|
||||
dc.DrawText(_("double click to edit symbol"), align_in_rect(ALIGN_MIDDLE_CENTER, text_size, style().getInternalRect()));
|
||||
}
|
||||
if (nativeLook()) {
|
||||
// draw editor buttons
|
||||
dc.SetFont(*wxNORMAL_FONT);
|
||||
drawButton(dc, 0, _BUTTON_("edit symbol"));
|
||||
//drawButton(dc, 1, _BUTTON_("symbol gallery"));
|
||||
}
|
||||
SymbolValueViewer::draw(dc);
|
||||
// draw helper text if there are no symbols
|
||||
if (symbols.empty()) {
|
||||
dc.SetFont(wxFont(10,wxSWISS,wxNORMAL,wxNORMAL));
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
RealSize text_size = dc.GetTextExtent(_("double click to edit symbol"));
|
||||
dc.DrawText(_("double click to edit symbol"), align_in_rect(ALIGN_MIDDLE_CENTER, text_size, style().getInternalRect()));
|
||||
}
|
||||
if (nativeLook()) {
|
||||
// draw editor buttons
|
||||
dc.SetFont(*wxNORMAL_FONT);
|
||||
drawButton(dc, 0, _BUTTON_("edit symbol"));
|
||||
//drawButton(dc, 1, _BUTTON_("symbol gallery"));
|
||||
}
|
||||
}
|
||||
void SymbolValueEditor::drawButton(RotatedDC& dc, int button, const String& text) {
|
||||
bool down = button == button_down;
|
||||
double height = style().height;
|
||||
double width = style().height + 2;
|
||||
double x = style().width - width - (width + 1) * button;
|
||||
double y = 0;
|
||||
// draw button
|
||||
draw_button(&editor(), dc.getDC(), dc.trRectToBB(RealRect(x,y,width,height)), false, down, true);
|
||||
// draw text
|
||||
RealSize text_size = dc.GetTextExtent(text);
|
||||
dc.DrawText(text, align_in_rect((Alignment)(ALIGN_BOTTOM | ALIGN_CENTER), text_size, RealRect(x, y, width,height*0.9)));
|
||||
// draw image
|
||||
const Bitmap& bmp = button_images[button];
|
||||
RealSize image_size(bmp.GetWidth(), bmp.GetHeight());
|
||||
dc.DrawBitmap(bmp, align_in_rect(ALIGN_MIDDLE_CENTER, image_size, RealRect(x,y,width,height * 0.8)));
|
||||
bool down = button == button_down;
|
||||
double height = style().height;
|
||||
double width = style().height + 2;
|
||||
double x = style().width - width - (width + 1) * button;
|
||||
double y = 0;
|
||||
// draw button
|
||||
draw_button(&editor(), dc.getDC(), dc.trRectToBB(RealRect(x,y,width,height)), false, down, true);
|
||||
// draw text
|
||||
RealSize text_size = dc.GetTextExtent(text);
|
||||
dc.DrawText(text, align_in_rect((Alignment)(ALIGN_BOTTOM | ALIGN_CENTER), text_size, RealRect(x, y, width,height*0.9)));
|
||||
// draw image
|
||||
const Bitmap& bmp = button_images[button];
|
||||
RealSize image_size(bmp.GetWidth(), bmp.GetHeight());
|
||||
dc.DrawBitmap(bmp, align_in_rect(ALIGN_MIDDLE_CENTER, image_size, RealRect(x,y,width,height * 0.8)));
|
||||
}
|
||||
|
||||
int SymbolValueEditor::findButton(const RealPoint& pos) {
|
||||
if (pos.y < 0 || pos.y >= style().height) return -1;
|
||||
int button = (int)floor( (style().width - pos.x) / (style().height + 3) );
|
||||
if (button >= 0 && button <= 1) return button;
|
||||
return -1;
|
||||
if (pos.y < 0 || pos.y >= style().height) return -1;
|
||||
int button = (int)floor( (style().width - pos.x) / (style().height + 3) );
|
||||
if (button >= 0 && button <= 1) return button;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SymbolValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent&) {
|
||||
if (!nativeLook()) return false;
|
||||
int button = findButton(pos);
|
||||
if (button != button_down) {
|
||||
button_down = button;
|
||||
viewer.redraw(*this);
|
||||
}
|
||||
return true;
|
||||
if (!nativeLook()) return false;
|
||||
int button = findButton(pos);
|
||||
if (button != button_down) {
|
||||
button_down = button;
|
||||
viewer.redraw(*this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SymbolValueEditor::onMotion(const RealPoint& pos, wxMouseEvent& ev) {
|
||||
if (button_down != -2) {
|
||||
int button = findButton(pos);
|
||||
if (button != button_down) {
|
||||
button_down = button;
|
||||
viewer.redraw(*this);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (button_down != -2) {
|
||||
int button = findButton(pos);
|
||||
if (button != button_down) {
|
||||
button_down = button;
|
||||
viewer.redraw(*this);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolValueEditor::onLeftUp(const RealPoint& pos, wxMouseEvent&) {
|
||||
if (!nativeLook()) return false;
|
||||
if (button_down == 0) {
|
||||
// edit
|
||||
button_down = -2;
|
||||
viewer.redraw(*this);
|
||||
editSymbol();
|
||||
return true;
|
||||
} else if (button_down == 1) {
|
||||
// gallery
|
||||
button_down = -2;
|
||||
viewer.redraw(*this);
|
||||
// TODO
|
||||
return true;
|
||||
} else {
|
||||
button_down = -2;
|
||||
return false;
|
||||
}
|
||||
if (!nativeLook()) return false;
|
||||
if (button_down == 0) {
|
||||
// edit
|
||||
button_down = -2;
|
||||
viewer.redraw(*this);
|
||||
editSymbol();
|
||||
return true;
|
||||
} else if (button_down == 1) {
|
||||
// gallery
|
||||
button_down = -2;
|
||||
viewer.redraw(*this);
|
||||
// TODO
|
||||
return true;
|
||||
} else {
|
||||
button_down = -2;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SymbolValueEditor::onLeftDClick(const RealPoint& pos, wxMouseEvent&) {
|
||||
// Use SetWindow as parent? Maybe not, the symbol editor will stay open when mainwindow closes
|
||||
editSymbol();
|
||||
return true;
|
||||
// Use SetWindow as parent? Maybe not, the symbol editor will stay open when mainwindow closes
|
||||
editSymbol();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SymbolValueEditor::determineSize(bool) {
|
||||
style().height = 50;
|
||||
style().height = 50;
|
||||
}
|
||||
|
||||
|
||||
void SymbolValueEditor::editSymbol() {
|
||||
SymbolWindow* wnd = new SymbolWindow(nullptr, getActionPerformer());
|
||||
wnd->Show();
|
||||
SymbolWindow* wnd = new SymbolWindow(nullptr, getActionPerformer());
|
||||
wnd->Show();
|
||||
}
|
||||
|
||||
ValueActionPerformer* SymbolValueEditor::getActionPerformer() {
|
||||
return new ValueActionPerformer(valueP(), editor().getCard().get(), editor().getSetForActions());
|
||||
return new ValueActionPerformer(valueP(), editor().getCard().get(), editor().getSetForActions());
|
||||
}
|
||||
|
||||
+20
-20
@@ -20,27 +20,27 @@ class ValueActionPerformer;
|
||||
/// An editor 'control' for editing SymbolValues
|
||||
class SymbolValueEditor : public SymbolValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(Symbol);
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftUp (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftDClick(const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onMotion (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual void determineSize(bool);
|
||||
DECLARE_VALUE_EDITOR(Symbol);
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftUp (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftDClick(const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onMotion (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual void determineSize(bool);
|
||||
private:
|
||||
/// Draw a button, buttons are numbered from the right
|
||||
void drawButton(RotatedDC& dc, int button, const String& text);
|
||||
/// Is there a button at the given position? returns the button index, or -1 if there is no button
|
||||
int findButton(const RealPoint& pos);
|
||||
/// Show the symbol editor
|
||||
void editSymbol();
|
||||
/// Get an object to perform actions for us
|
||||
ValueActionPerformer* getActionPerformer();
|
||||
|
||||
// button, or -1 for mouse down, but not on button, or -2 for mouse not down
|
||||
int button_down;
|
||||
Bitmap button_images[1];
|
||||
/// Draw a button, buttons are numbered from the right
|
||||
void drawButton(RotatedDC& dc, int button, const String& text);
|
||||
/// Is there a button at the given position? returns the button index, or -1 if there is no button
|
||||
int findButton(const RealPoint& pos);
|
||||
/// Show the symbol editor
|
||||
void editSymbol();
|
||||
/// Get an object to perform actions for us
|
||||
ValueActionPerformer* getActionPerformer();
|
||||
|
||||
// button, or -1 for mouse down, but not on button, or -2 for mouse not down
|
||||
int button_down;
|
||||
Bitmap button_images[1];
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
+1179
-1179
File diff suppressed because it is too large
Load Diff
+154
-154
@@ -21,8 +21,8 @@ DECLARE_SHARED_POINTER_TYPE(DropDownWordList);
|
||||
// ----------------------------------------------------------------------------- : TextValueEditor
|
||||
|
||||
enum IndexType
|
||||
{ TYPE_CURSOR ///< Positions are cursor positions
|
||||
, TYPE_INDEX ///< Positions are character indices
|
||||
{ TYPE_CURSOR ///< Positions are cursor positions
|
||||
, TYPE_INDEX ///< Positions are character indices
|
||||
};
|
||||
|
||||
/// An editor 'control' for editing TextValues
|
||||
@@ -30,161 +30,161 @@ enum IndexType
|
||||
*/
|
||||
class TextValueEditor : public TextValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(Text);
|
||||
~TextValueEditor();
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
|
||||
virtual void onFocus();
|
||||
virtual void onLoseFocus();
|
||||
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftUp (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftDClick(const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onRightDown (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onMotion (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual void onMouseLeave(const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onMouseWheel(const RealPoint& pos, wxMouseEvent&);
|
||||
|
||||
virtual bool onContextMenu(IconMenu& m, wxContextMenuEvent&);
|
||||
virtual wxMenu* getMenu(int type) const;
|
||||
virtual bool onCommand(int);
|
||||
|
||||
virtual bool onChar(wxKeyEvent&);
|
||||
|
||||
// --------------------------------------------------- : Actions
|
||||
|
||||
virtual void onValueChange();
|
||||
virtual void onAction(const Action&, bool undone);
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
|
||||
virtual bool canCopy() const;
|
||||
virtual bool canPaste() const;
|
||||
virtual bool doCopy();
|
||||
virtual bool doPaste();
|
||||
virtual bool doDelete();
|
||||
|
||||
// --------------------------------------------------- : Formating
|
||||
|
||||
virtual bool canFormat(int type) const;
|
||||
virtual bool hasFormat(int type) const;
|
||||
virtual void doFormat(int type);
|
||||
|
||||
// --------------------------------------------------- : Selection
|
||||
|
||||
virtual void select(size_t start, size_t end);
|
||||
virtual size_t selectionStart() const { return selection_start; }
|
||||
virtual size_t selectionEnd() const { return selection_end; }
|
||||
|
||||
virtual void insert(const String& text, const String& action_name);
|
||||
|
||||
// --------------------------------------------------- : Search/replace
|
||||
|
||||
virtual bool search(FindInfo& find, bool from_start);
|
||||
DECLARE_VALUE_EDITOR(Text);
|
||||
~TextValueEditor();
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
|
||||
virtual void onFocus();
|
||||
virtual void onLoseFocus();
|
||||
|
||||
virtual bool onLeftDown (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftUp (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onLeftDClick(const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onRightDown (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onMotion (const RealPoint& pos, wxMouseEvent&);
|
||||
virtual void onMouseLeave(const RealPoint& pos, wxMouseEvent&);
|
||||
virtual bool onMouseWheel(const RealPoint& pos, wxMouseEvent&);
|
||||
|
||||
virtual bool onContextMenu(IconMenu& m, wxContextMenuEvent&);
|
||||
virtual wxMenu* getMenu(int type) const;
|
||||
virtual bool onCommand(int);
|
||||
|
||||
virtual bool onChar(wxKeyEvent&);
|
||||
|
||||
// --------------------------------------------------- : Actions
|
||||
|
||||
virtual void onValueChange();
|
||||
virtual void onAction(const Action&, bool undone);
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
|
||||
virtual bool canCopy() const;
|
||||
virtual bool canPaste() const;
|
||||
virtual bool doCopy();
|
||||
virtual bool doPaste();
|
||||
virtual bool doDelete();
|
||||
|
||||
// --------------------------------------------------- : Formating
|
||||
|
||||
virtual bool canFormat(int type) const;
|
||||
virtual bool hasFormat(int type) const;
|
||||
virtual void doFormat(int type);
|
||||
|
||||
// --------------------------------------------------- : Selection
|
||||
|
||||
virtual void select(size_t start, size_t end);
|
||||
virtual size_t selectionStart() const { return selection_start; }
|
||||
virtual size_t selectionEnd() const { return selection_end; }
|
||||
|
||||
virtual void insert(const String& text, const String& action_name);
|
||||
|
||||
// --------------------------------------------------- : Search/replace
|
||||
|
||||
virtual bool search(FindInfo& find, bool from_start);
|
||||
private:
|
||||
bool matchSubstr(const String& s, size_t pos, FindInfo& find);
|
||||
bool matchSubstr(const String& s, size_t pos, FindInfo& find);
|
||||
public:
|
||||
|
||||
// --------------------------------------------------- : Other
|
||||
|
||||
virtual wxCursor cursor(const RealPoint& pos) const;
|
||||
virtual void determineSize(bool force_fit = false);
|
||||
virtual bool containsPoint(const RealPoint& p) const;
|
||||
virtual RealRect boundingBox() const;
|
||||
virtual void onShow(bool);
|
||||
virtual void draw(RotatedDC&);
|
||||
|
||||
// --------------------------------------------------- : Data
|
||||
|
||||
// --------------------------------------------------- : Other
|
||||
|
||||
virtual wxCursor cursor(const RealPoint& pos) const;
|
||||
virtual void determineSize(bool force_fit = false);
|
||||
virtual bool containsPoint(const RealPoint& p) const;
|
||||
virtual RealRect boundingBox() const;
|
||||
virtual void onShow(bool);
|
||||
virtual void draw(RotatedDC&);
|
||||
|
||||
// --------------------------------------------------- : Data
|
||||
private:
|
||||
size_t selection_start, selection_end; ///< Cursor position/selection (if any), cursor positions
|
||||
size_t selection_start_i, selection_end_i; ///< Cursor position/selection, character indices
|
||||
bool selecting; ///< Selecting text?
|
||||
bool select_words; ///< Select whole words when dragging the mouse?
|
||||
TextValueEditorScrollBar* scrollbar; ///< Scrollbar for multiline fields in native look
|
||||
bool scroll_with_cursor; ///< When the cursor moves, should the scrollposition change?
|
||||
vector<WordListPosP> word_lists; ///< Word lists in the text
|
||||
|
||||
// --------------------------------------------------- : Selection / movement
|
||||
|
||||
/// Move the selection to a new location, clears the previously drawn selection.
|
||||
/** t specifies what kind of position new_end is */
|
||||
void moveSelection(IndexType t, size_t new_end, bool also_move_start=true, Movement dir = MOVE_MID);
|
||||
/// Move the selection to a new location, but does not redraw.
|
||||
/** t specifies what kind of position new_end is */
|
||||
void moveSelectionNoRedraw(IndexType t, size_t new_end, bool also_move_start=true, Movement dir = MOVE_MID);
|
||||
|
||||
/// Redraw the selection
|
||||
void redrawSelection(size_t old_selection_start_i, size_t old_selection_end_i, bool old_drop_down_shown);
|
||||
|
||||
/// Replace the current selection with 'replacement', name the action
|
||||
/** replacement should be a tagged string (i.e. already escaped) */
|
||||
void replaceSelection(const String& replacement, const String& name, bool allow_auto_replace = false, bool select_on_undo = true);
|
||||
/// Try to autoreplace at the position before the cursor
|
||||
void tryAutoReplace();
|
||||
|
||||
/// Make sure the selection satisfies its constraints
|
||||
/** - selection_start and selection_end are inside the text
|
||||
* - not inside tags
|
||||
* - the selection does not contain a <sep> or </sep> tag
|
||||
*
|
||||
* When correcting the selection, move in the given direction
|
||||
*/
|
||||
void fixSelection(IndexType t = TYPE_CURSOR, Movement dir = MOVE_MID);
|
||||
|
||||
/// Return a position resulting from moving pos outside the range [start...end), in the direction dir
|
||||
static size_t move(size_t pos, size_t start, size_t end, Movement dir);
|
||||
|
||||
/// Move the caret to the selection_end position and show it
|
||||
void showCaret();
|
||||
|
||||
/// Position of previous visible & selectable character
|
||||
/** Uses cursor positions */
|
||||
size_t prevCharBoundary(size_t pos) const;
|
||||
size_t nextCharBoundary(size_t pos) const;
|
||||
/// Front of previous word, used witch Ctrl+Left/right
|
||||
/** Uses character indices */
|
||||
size_t prevWordBoundary(size_t pos_i) const;
|
||||
size_t nextWordBoundary(size_t pos_i) const;
|
||||
bool isWordBoundary(size_t pos_i) const;
|
||||
|
||||
// --------------------------------------------------- : Scrolling
|
||||
|
||||
friend class TextValueEditorScrollBar;
|
||||
|
||||
/// Scroll to the given position, called by scrollbar
|
||||
void scrollTo(int pos);
|
||||
/// Update the scrollbar to show the current scroll position
|
||||
void updateScrollbar();
|
||||
/// Scrolls to ensure the caret stays visible, return true if the control is scrolled
|
||||
bool ensureCaretVisible();
|
||||
/// Prepare for drawing if there is a scrollbar
|
||||
void prepareDrawScrollbar(RotatedDC& dc);
|
||||
|
||||
// --------------------------------------------------- : Word lists
|
||||
|
||||
friend class DropDownWordList;
|
||||
DropDownWordListP drop_down;
|
||||
bool dropDownShown() const;
|
||||
mutable WordListPos* hovered_words;
|
||||
|
||||
/// Find all word lists in the current value
|
||||
void findWordLists();
|
||||
/// Draw word list indicators
|
||||
void drawWordListIndicators(RotatedDC& dc, bool redrawing = false);
|
||||
/// Remove word list indicators
|
||||
void clearWordListIndicators(RotatedDC& dc);
|
||||
/// Re-draw word list indicators
|
||||
void redrawWordListIndicators(bool toggling_dropdown = false);
|
||||
/// Find a WordListPos under the mouse cursor (if any), pos is in internal coordinates
|
||||
WordListPosP findWordList(const RealPoint& pos) const;
|
||||
/// Find a WordListPos rectangle under the mouse cursor (if any), pos is in internal coordinates
|
||||
WordListPosP findWordListBody(const RealPoint& pos) const;
|
||||
/// Find a WordListPos for a index position
|
||||
WordListPosP findWordList(size_t index) const;
|
||||
/// Show a word list drop down menu, if wl. Returns true if a list is shown
|
||||
bool wordListDropDown(const WordListPosP& wl);
|
||||
|
||||
size_t selection_start, selection_end; ///< Cursor position/selection (if any), cursor positions
|
||||
size_t selection_start_i, selection_end_i; ///< Cursor position/selection, character indices
|
||||
bool selecting; ///< Selecting text?
|
||||
bool select_words; ///< Select whole words when dragging the mouse?
|
||||
TextValueEditorScrollBar* scrollbar; ///< Scrollbar for multiline fields in native look
|
||||
bool scroll_with_cursor; ///< When the cursor moves, should the scrollposition change?
|
||||
vector<WordListPosP> word_lists; ///< Word lists in the text
|
||||
|
||||
// --------------------------------------------------- : Selection / movement
|
||||
|
||||
/// Move the selection to a new location, clears the previously drawn selection.
|
||||
/** t specifies what kind of position new_end is */
|
||||
void moveSelection(IndexType t, size_t new_end, bool also_move_start=true, Movement dir = MOVE_MID);
|
||||
/// Move the selection to a new location, but does not redraw.
|
||||
/** t specifies what kind of position new_end is */
|
||||
void moveSelectionNoRedraw(IndexType t, size_t new_end, bool also_move_start=true, Movement dir = MOVE_MID);
|
||||
|
||||
/// Redraw the selection
|
||||
void redrawSelection(size_t old_selection_start_i, size_t old_selection_end_i, bool old_drop_down_shown);
|
||||
|
||||
/// Replace the current selection with 'replacement', name the action
|
||||
/** replacement should be a tagged string (i.e. already escaped) */
|
||||
void replaceSelection(const String& replacement, const String& name, bool allow_auto_replace = false, bool select_on_undo = true);
|
||||
/// Try to autoreplace at the position before the cursor
|
||||
void tryAutoReplace();
|
||||
|
||||
/// Make sure the selection satisfies its constraints
|
||||
/** - selection_start and selection_end are inside the text
|
||||
* - not inside tags
|
||||
* - the selection does not contain a <sep> or </sep> tag
|
||||
*
|
||||
* When correcting the selection, move in the given direction
|
||||
*/
|
||||
void fixSelection(IndexType t = TYPE_CURSOR, Movement dir = MOVE_MID);
|
||||
|
||||
/// Return a position resulting from moving pos outside the range [start...end), in the direction dir
|
||||
static size_t move(size_t pos, size_t start, size_t end, Movement dir);
|
||||
|
||||
/// Move the caret to the selection_end position and show it
|
||||
void showCaret();
|
||||
|
||||
/// Position of previous visible & selectable character
|
||||
/** Uses cursor positions */
|
||||
size_t prevCharBoundary(size_t pos) const;
|
||||
size_t nextCharBoundary(size_t pos) const;
|
||||
/// Front of previous word, used witch Ctrl+Left/right
|
||||
/** Uses character indices */
|
||||
size_t prevWordBoundary(size_t pos_i) const;
|
||||
size_t nextWordBoundary(size_t pos_i) const;
|
||||
bool isWordBoundary(size_t pos_i) const;
|
||||
|
||||
// --------------------------------------------------- : Scrolling
|
||||
|
||||
friend class TextValueEditorScrollBar;
|
||||
|
||||
/// Scroll to the given position, called by scrollbar
|
||||
void scrollTo(int pos);
|
||||
/// Update the scrollbar to show the current scroll position
|
||||
void updateScrollbar();
|
||||
/// Scrolls to ensure the caret stays visible, return true if the control is scrolled
|
||||
bool ensureCaretVisible();
|
||||
/// Prepare for drawing if there is a scrollbar
|
||||
void prepareDrawScrollbar(RotatedDC& dc);
|
||||
|
||||
// --------------------------------------------------- : Word lists
|
||||
|
||||
friend class DropDownWordList;
|
||||
DropDownWordListP drop_down;
|
||||
bool dropDownShown() const;
|
||||
mutable WordListPos* hovered_words;
|
||||
|
||||
/// Find all word lists in the current value
|
||||
void findWordLists();
|
||||
/// Draw word list indicators
|
||||
void drawWordListIndicators(RotatedDC& dc, bool redrawing = false);
|
||||
/// Remove word list indicators
|
||||
void clearWordListIndicators(RotatedDC& dc);
|
||||
/// Re-draw word list indicators
|
||||
void redrawWordListIndicators(bool toggling_dropdown = false);
|
||||
/// Find a WordListPos under the mouse cursor (if any), pos is in internal coordinates
|
||||
WordListPosP findWordList(const RealPoint& pos) const;
|
||||
/// Find a WordListPos rectangle under the mouse cursor (if any), pos is in internal coordinates
|
||||
WordListPosP findWordListBody(const RealPoint& pos) const;
|
||||
/// Find a WordListPos for a index position
|
||||
WordListPosP findWordList(size_t index) const;
|
||||
/// Show a word list drop down menu, if wl. Returns true if a list is shown
|
||||
bool wordListDropDown(const WordListPosP& wl);
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
Reference in New Issue
Block a user