Show WndEditor.h syntax highlighted
// -*- C++ -*-
/* GG is a GUI for SDL and OpenGL.
Copyright (C) 2003 T. Zachary Laine
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1
of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
If you do not wish to comply with the terms of the LGPL please
contact the author as other terms are available for a fee.
Zach Laine
whatwasthataddress@hotmail.com */
/** \file WndEditor.h
Contains the WndEditor class, a window that contains controls that can alter the properties of a Wnd
interactively. */
#ifndef _GG_WndEditor_h_
#define _GG_WndEditor_h_
#include <GG/DropDownList.h>
#include <GG/Edit.h>
#include <GG/GUI.h>
#include <GG/ListBox.h>
#include <GG/dialogs/ColorDlg.h>
#include <boost/type_traits.hpp>
namespace GG {
namespace detail {
GG_API extern const int ATTRIBUTE_ROW_HEIGHT;
GG_API extern const int ATTRIBUTE_ROW_CONTROL_WIDTH;
}
struct AttributeRowBase;
/** This is the base class for functors that respond to a change in a Wnd attribute edited by a WndEditor. This is
needed when a change in a value within a Wnd must be accompanied by some action that is taken in response to that
change. */
template <class T>
struct AttributeChangedAction
{
virtual ~AttributeChangedAction() {}
virtual void operator()(const T& value) {}
};
/** Allows Wnds to be edited texually in a GUI, primarily for use in GG Sketch. WndEditor takes an assigned Wnd and
queries it for controls that can be used to edit it. Each Wnd to be edited calls methods in the WndEditor that
create the appropriate controls, and provides references to its internal members that may be altered by the controls
created.*/
class GG_API WndEditor : public Wnd
{
public:
/** Contains a Flags object and the AttributeChangedAction associated with it. */
template <class FlagType>
struct FlagsAndAction
{
Flags<FlagType>* m_flags;
boost::shared_ptr<AttributeChangedAction<Flags<FlagType> > > m_action;
};
/** basic ctor. Note that WndEditor has an integral width. */
WndEditor(int h, const boost::shared_ptr<Font>& font);
/** Returns the font used by this WndEditor to create its attribute rows. */
const boost::shared_ptr<Font>& GetFont() const;
/** Returns the Wnd currently being edited. */
const Wnd* GetWnd() const;
virtual void Render ();
/** sets the edited window to \a wnd, and updates the contents of WndEditor's controls to contain the controls that
edit the new Wnd. */
void SetWnd(Wnd* wnd, const std::string& name = "");
/** creates a row containing just the text \a name. */
void Label(const std::string& name);
/** adds \a row and attaches to its ChangedSignal */
void Attribute(AttributeRowBase* row);
/** creates a row containing an edit box controlling the value of \a value. */
template <class T>
void Attribute(const std::string& name, T& value,
const boost::shared_ptr<AttributeChangedAction<T> >& attribute_changed_action);
/** creates a row containing an edit box controlling the value of \a value. */
template <class T>
void Attribute(const std::string& name, T& value);
/** creates a row containing an edit box controlling the value of \a value. The legal values for \a value are
restricted to the range [\a min, \a max].*/
template <class T>
void Attribute(const std::string& name, T& value, const T& min, const T& max,
const boost::shared_ptr<AttributeChangedAction<T> >& attribute_changed_action);
/** creates a row containing an edit box controlling the value of \a value. The legal values for \a value are
restricted to the range [\a min, \a max].*/
template <class T>
void Attribute(const std::string& name, T& value, const T& min, const T& max);
/** creates a row containing the uneditable string representation of \a value. */
template <class T>
void ConstAttribute(const std::string& name, const T& value);
/** creates a row that displays the uneditable result of calling \a functor on the edited Wnd. */
template <class T>
void CustomText(const std::string& name, const T& functor);
/** marks the beginning of a section of flag and flag-group rows. Until EndFlags() is called, all Flag() and
FlagGroup() calls will set values in \a flags. */
template <class FlagType>
void BeginFlags(Flags<FlagType>& flags,
const boost::shared_ptr<AttributeChangedAction<Flags<FlagType> > >& attribute_changed_action);
/** marks the beginning of a section of flag and flag-group rows. Until EndFlags() is called, all Flag() and
FlagGroup() calls will set values in \a flags. */
template <class FlagType>
void BeginFlags(Flags<FlagType>& flags);
/** creates a row representing a single bit flag in the currently-set flags variable. */
template <class FlagType>
void Flag(const std::string& name, FlagType flag);
/** creates a row representing a group of bit flags in the currently-set flags variable. Exactly one of the given
flags will be enabled at one time. */
template <class FlagType>
void FlagGroup(const std::string& name, const std::vector<FlagType>& group_values);
/** marks the end of a section of flag and flag-group rows. */
void EndFlags();
mutable boost::signal<void (Wnd*, const std::string&)> WndNameChangedSignal; ///< emitted when the edited window's name has been changed
mutable boost::signal<void (Wnd*)> WndChangedSignal; ///< emitted when the edited window has been changed
private:
void Init();
void AttributeChangedSlot();
void NameChangedSlot(const std::string& name);
Wnd* m_wnd;
ListBox* m_list_box;
boost::shared_ptr<Font> m_font;
boost::shared_ptr<Font> m_label_font;
boost::any m_current_flags_and_action;
};
/** the base class for the hierarchy of rows of controls used by WndEditor to accept user modifications of its edited
Wnd. */
struct GG_API AttributeRowBase : ListBox::Row
{
virtual void Refresh(); ///< refreshes the contents of the row to match the value associated with the row every frame
virtual void Update(); ///< updates the contents of the row to match the value associated with the row on response to a change in the edited Wnd
mutable boost::signal<void ()> ChangedSignal; ///< emitted when the row has modified its associated value
};
/** the most general form of attribute row, which displays an editable value in an edit box. */
template <class T>
struct AttributeRow : AttributeRowBase
{
AttributeRow(const std::string& name, T& value, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const T&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void TextChanged(const std::string& value_text);
T& m_value;
Edit* m_edit;
boost::signals::connection m_edit_connection;
};
/** the specialization of AttributeRow<T> for Pt. */
template <>
struct GG_API AttributeRow<Pt> : AttributeRowBase
{
AttributeRow(const std::string& name, Pt& value, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const Pt&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
Pt& m_value;
Edit* m_x_edit;
Edit* m_y_edit;
boost::signals::connection m_x_connection;
boost::signals::connection m_y_connection;
};
/** the specialization of AttributeRow<T> for Clr. */
template <>
struct GG_API AttributeRow<Clr> : AttributeRowBase
{
AttributeRow(const std::string& name, Clr& value, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const Clr&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void ColorButtonClicked();
Clr& m_value;
ColorDlg::ColorButton* m_color_button;
boost::shared_ptr<Font> m_font;
};
/** the specialization of AttributeRow<T> for bool. */
template <>
struct GG_API AttributeRow<bool> : AttributeRowBase
{
AttributeRow(const std::string& name, bool& value, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const bool&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void SelectionChanged(int selection);
bool& m_value;
RadioButtonGroup* m_radio_button_group;
boost::signals::connection m_button_group_connection;
};
/** the specialization of AttributeRow<T> for Font shared pointers. */
template <>
struct GG_API AttributeRow<boost::shared_ptr<Font> > : AttributeRowBase
{
AttributeRow(const std::string& name, boost::shared_ptr<Font>& value, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const boost::shared_ptr<Font>&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void FilenameChanged(const std::string& filename_text);
void PointsChanged(const std::string& points_text);
boost::shared_ptr<Font>& m_value;
Edit* m_filename_edit;
Edit* m_points_edit;
boost::signals::connection m_filename_connection;
boost::signals::connection m_points_connection;
};
/** a AttributeRowBase subclass that is restricted to a certain range of values. Note that all this type of row should
be used for all enum types, since the range of valid enum values must be known for the control to display them
all. */
template <class T, bool is_enum = boost::is_enum<T>::value>
struct RangedAttributeRow : AttributeRowBase
{
RangedAttributeRow(const std::string& name, T& value, const T& min, const T& max, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const T&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void TextChanged(const std::string& value_text);
T& m_value;
T m_min;
T m_max;
Edit* m_edit;
boost::signals::connection m_edit_connection;
};
/** the specialization of RangedAttributeRow<T, bool> for enum types. */
template <class T>
struct RangedAttributeRow<T, true> : AttributeRowBase
{
RangedAttributeRow(const std::string& name, T& value, const T& min, const T& max, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const T&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void SelectionChanged(int selection);
T& m_value;
T m_min;
DropDownList* m_enum_drop_list;
boost::signals::connection m_drop_list_connection;
};
/** an uneditable attribute row. */
template <class T>
struct ConstAttributeRow : AttributeRowBase
{
ConstAttributeRow(const std::string& name, const T& value, const boost::shared_ptr<Font>& font);
virtual void Refresh();
private:
const T& m_value;
TextControl* m_value_text;
};
/** the specialization of ConstAttributeRow<T> for Pt. */
template <>
struct GG_API ConstAttributeRow<Pt> : AttributeRowBase
{
ConstAttributeRow(const std::string& name, const Pt& value, const boost::shared_ptr<Font>& font);
virtual void Refresh();
private:
const Pt& m_value;
TextControl* m_value_text;
};
/** the specialization of ConstAttributeRow<Clr> for Pt. */
template <>
struct GG_API ConstAttributeRow<Clr> : AttributeRowBase
{
ConstAttributeRow(const std::string& name, const Clr& value, const boost::shared_ptr<Font>& font);
virtual void Refresh();
private:
const Clr& m_value;
TextControl* m_value_text;
};
/** the subclass of AttributeRowBase used to represent a single flag attribute. */
template <class FlagType>
struct FlagAttributeRow : AttributeRowBase
{
/** basic ctor. \a flags should be the variable that holds all the flag values, and \a value should be the flag
represented by this row. */
FlagAttributeRow(const std::string& name, Flags<FlagType>& flags, FlagType value, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const Flags<FlagType>&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void CheckChanged(bool checked);
Flags<FlagType>& m_flags;
FlagType m_value;
StateButton* m_check_box;
boost::signals::connection m_check_box_connection;
};
/** the AttributeRowBase subclass used to represent a group of mutually-exclusive flag attributes, one of which must be
set to true at all times. */
template <class FlagType>
struct FlagGroupAttributeRow : AttributeRowBase
{
/** basic ctor. \a flags should be the variable that holds all the flag values, and \a min and \a max should define
the range of flags represented by this row. */
FlagGroupAttributeRow(const std::string& name, Flags<FlagType>& flags, FlagType value, const std::vector<FlagType>& group_values, const boost::shared_ptr<Font>& font);
virtual void Update();
mutable boost::signal<void (const Flags<FlagType>&)> ValueChangedSignal; ///< when the row has modified its associated value, this emits the new value
private:
void SelectionChanged(int selection);
Flags<FlagType>& m_flags;
FlagType m_value;
std::vector<FlagType> m_group_values;
DropDownList* m_flag_drop_list;
boost::signals::connection m_drop_list_connection;
};
/** the AttributeRowBase subclass used to display some custom text about a Wnd, that does not necessarily correspond to
a single data member in that Wnd. CustomTextRow accepts a functor with the signature std::string (const Wnd*);
when the row's Refresh() method is called, the row will set its text to <i>functor</i>(<i>m_wnd</i>). This allows a
Wnd subclass to display arbitrary (uneditable) information about itself, without being restricted to displaying just
data members. */
template <class T>
struct CustomTextRow : AttributeRowBase
{
CustomTextRow(const std::string& name, const T& functor, const Wnd*& wnd, const boost::shared_ptr<Font>& font);
virtual void Refresh();
private:
T m_functor;
const Wnd*& m_wnd;
TextControl* m_display_text;
};
// template implementations
template <class T>
void WndEditor::Attribute(const std::string& name, T& value,
const boost::shared_ptr<AttributeChangedAction<T> >& attribute_changed_action)
{
AttributeRow<T>* attribute = new AttributeRow<T>(name, value, m_font);
m_list_box->Insert(attribute);
if (attribute_changed_action)
Connect(attribute->ValueChangedSignal, &AttributeChangedAction<T>::operator(), attribute_changed_action);
Connect(attribute->ChangedSignal, &WndEditor::AttributeChangedSlot, this);
}
template <class T>
void WndEditor::Attribute(const std::string& name, T& value)
{
AttributeRow<T>* attribute = new AttributeRow<T>(name, value, m_font);
m_list_box->Insert(attribute);
Connect(attribute->ChangedSignal, &WndEditor::AttributeChangedSlot, this);
}
template <class T>
void WndEditor::Attribute(const std::string& name, T& value, const T& min, const T& max,
const boost::shared_ptr<AttributeChangedAction<T> >& attribute_changed_action)
{
RangedAttributeRow<T>* attribute = new RangedAttributeRow<T>(name, value, min, max, m_font);
m_list_box->Insert(attribute);
if (attribute_changed_action)
Connect(attribute->ValueChangedSignal, &AttributeChangedAction<T>::operator(), attribute_changed_action);
Connect(attribute->ChangedSignal, &WndEditor::AttributeChangedSlot, this);
}
template <class T>
void WndEditor::Attribute(const std::string& name, T& value, const T& min, const T& max)
{
RangedAttributeRow<T>* attribute = new RangedAttributeRow<T>(name, value, min, max, m_font);
m_list_box->Insert(attribute);
Connect(attribute->ChangedSignal, &WndEditor::AttributeChangedSlot, this);
}
template <class T>
void WndEditor::ConstAttribute(const std::string& name, const T& value)
{
ConstAttributeRow<T>* attribute = new ConstAttributeRow<T>(name, value, m_font);
m_list_box->Insert(attribute);
}
template <class T>
void WndEditor::CustomText(const std::string& name, const T& functor)
{
CustomTextRow<T>* display_row = new CustomTextRow<T>(name, functor, const_cast<const Wnd*&>(m_wnd), m_font);
m_list_box->Insert(display_row);
}
template <class FlagType>
void WndEditor::BeginFlags(Flags<FlagType>& flags,
const boost::shared_ptr<AttributeChangedAction<Flags<FlagType> > >& attribute_changed_action)
{
FlagsAndAction<FlagType> flags_and_action;
flags_and_action.m_flags = &flags;
flags_and_action.m_action = attribute_changed_action;
m_current_flags_and_action = flags_and_action;
}
template <class FlagType>
void WndEditor::BeginFlags(Flags<FlagType>& flags)
{
FlagsAndAction<FlagType> flags_and_action;
flags_and_action.m_flags = &flags;
m_current_flags_and_action = flags_and_action;
}
template <class FlagType>
void WndEditor::Flag(const std::string& name, FlagType flag)
{
if (m_current_flags_and_action.empty()) {
throw std::runtime_error("WndEditor::Flag() : Attempted to create a flag outside of a BeginFlags()/EndFlags() "
"block.");
}
FlagsAndAction<FlagType> flags_and_action;
try {
flags_and_action = boost::any_cast<FlagsAndAction<FlagType> >(m_current_flags_and_action);
} catch (const boost::bad_any_cast&) {
throw std::runtime_error("WndEditor::Flag() : Attempted to initialize a flag group from a set of flags "
"of a type that does not match the most recent call to BeginFlags().");
}
FlagAttributeRow<FlagType>* flag_attribute = new FlagAttributeRow<FlagType>(name, *flags_and_action.m_flags, flag, m_font);
m_list_box->Insert(flag_attribute);
if (flags_and_action.m_action)
Connect(flag_attribute->ValueChangedSignal, &AttributeChangedAction<Flags<FlagType> >::operator(), flags_and_action.m_action);
Connect(flag_attribute->ChangedSignal, &WndEditor::AttributeChangedSlot, this);
}
template <class FlagType>
void WndEditor::FlagGroup(const std::string& name, const std::vector<FlagType>& group_values)
{
if (m_current_flags_and_action.empty()) {
throw std::runtime_error("WndEditor::FlagGroup() : Attempted to create a flag group outside of a BeginFlags()/"
"EndFlags() block.");
}
FlagsAndAction<FlagType> flags_and_action;
try {
flags_and_action = boost::any_cast<FlagsAndAction<FlagType> >(m_current_flags_and_action);
} catch (const boost::bad_any_cast&) {
throw std::runtime_error("WndEditor::FlagGroup() : Attempted to initialize a flag group from a set of flags "
"of a type that does not match the type of the flags given to the most recent call "
"to BeginFlags().");
}
if (group_values.empty()) {
throw std::runtime_error("WndEditor::FlagGroup() : Attempted to initialize a flag group from a n empty set of flags.");
}
bool value_found = false;
FlagType value;
for (unsigned int i = 0; i < group_values.size(); ++i) {
if (*flags_and_action.m_flags & group_values[i]) {
value = group_values[i];
value_found = true;
break;
}
}
FlagGroupAttributeRow<FlagType>* flag_group = new FlagGroupAttributeRow<FlagType>(name, *flags_and_action.m_flags, value, group_values, m_font);
m_list_box->Insert(flag_group);
if (flags_and_action.m_action)
Connect(flag_group->ValueChangedSignal, &AttributeChangedAction<Flags<FlagType> >::operator(), flags_and_action.m_action);
Connect(flag_group->ChangedSignal, &WndEditor::AttributeChangedSlot, this);
}
template <class T>
AttributeRow<T>::AttributeRow(const std::string& name, T& value, const boost::shared_ptr<Font>& font) :
m_value(value),
m_edit(0)
{
push_back(CreateControl(name, font, CLR_BLACK));
m_edit = new Edit(0, 0, 1, "", font, CLR_GRAY, CLR_BLACK, CLR_WHITE);
m_edit->Resize(Pt(detail::ATTRIBUTE_ROW_CONTROL_WIDTH, m_edit->Height()));
Resize(m_edit->Size());
push_back(m_edit);
*m_edit << value;
m_edit_connection = Connect(m_edit->FocusUpdateSignal, &AttributeRow::TextChanged, this);
}
template <class T>
void AttributeRow<T>::TextChanged(const std::string& value_text)
{
try {
T value = boost::lexical_cast<T>(value_text);
m_value = value;
m_edit->SetTextColor(CLR_BLACK);
ValueChangedSignal(m_value);
ChangedSignal();
} catch (const boost::bad_lexical_cast& e) {
m_edit->SetTextColor(CLR_RED);
}
}
template <class T>
void AttributeRow<T>::Update()
{
m_edit_connection.block();
*m_edit << m_value;
m_edit_connection.unblock();
}
template <class T, bool is_enum>
RangedAttributeRow<T, is_enum>::RangedAttributeRow(const std::string& name, T& value, const T& min, const T& max, const boost::shared_ptr<Font>& font) :
m_value(value),
m_min(min),
m_max(max),
m_edit(0)
{
push_back(CreateControl(name, font, CLR_BLACK));
m_edit = new Edit(0, 0, 1, "", font, CLR_GRAY, CLR_BLACK, CLR_WHITE);
m_edit->Resize(Pt(detail::ATTRIBUTE_ROW_CONTROL_WIDTH, m_edit->Height()));
Resize(m_edit->Size());
push_back(m_edit);
*m_edit << value;
m_edit_connection = Connect(m_edit->FocusUpdateSignal, &RangedAttributeRow::TextChanged, this);
}
template <class T, bool is_enum>
void RangedAttributeRow<T, is_enum>::TextChanged(const std::string& value_text)
{
try {
T value = boost::lexical_cast<T>(value_text);
if (value < m_min || m_max < value)
throw boost::bad_lexical_cast();
m_value = value;
m_edit->SetTextColor(CLR_BLACK);
ValueChangedSignal(m_value);
ChangedSignal();
} catch (const boost::bad_lexical_cast& e) {
m_edit->SetTextColor(CLR_RED);
}
}
template <class T, bool is_enum>
void RangedAttributeRow<T, is_enum>::Update()
{
m_edit_connection.block();
*m_edit << m_value;
m_edit_connection.unblock();
}
template <class T>
RangedAttributeRow<T, true>::RangedAttributeRow(const std::string& name, T& value, const T& min, const T& max, const boost::shared_ptr<Font>& font) :
m_value(value),
m_min(min),
m_enum_drop_list(0)
{
push_back(CreateControl(name, font, CLR_BLACK));
m_enum_drop_list = new DropDownList(0, 0, detail::ATTRIBUTE_ROW_CONTROL_WIDTH, detail::ATTRIBUTE_ROW_HEIGHT, detail::ATTRIBUTE_ROW_HEIGHT * (max - min + 1) + 4, CLR_GRAY);
m_enum_drop_list->SetInteriorColor(CLR_WHITE);
m_enum_drop_list->SetStyle(LIST_NOSORT);
for (T i = min; i <= max; i = T(i + 1)) {
Row* row = new ListBox::Row();
std::string enum_label = boost::lexical_cast<std::string>(i);
std::string::size_type pos = enum_label.find_last_of(':');
if (pos != std::string::npos) {
++pos;
enum_label = enum_label.substr(pos);
}
row->push_back(CreateControl(enum_label, font, CLR_BLACK));
m_enum_drop_list->Insert(row);
}
push_back(m_enum_drop_list);
m_enum_drop_list->Select(m_value - m_min);
m_drop_list_connection = Connect(m_enum_drop_list->SelChangedSignal, &RangedAttributeRow::SelectionChanged, this);
}
template <class T>
void RangedAttributeRow<T, true>::SelectionChanged(int selection)
{
m_value = T(m_min + selection);
ValueChangedSignal(m_value);
ChangedSignal();
}
template <class T>
void RangedAttributeRow<T, true>::Update()
{
m_drop_list_connection.block();
m_enum_drop_list->Select(m_value - m_min);
m_drop_list_connection.unblock();
}
template <class T>
ConstAttributeRow<T>::ConstAttributeRow(const std::string& name, const T& value, const boost::shared_ptr<Font>& font) :
m_value(value),
m_value_text(0)
{
push_back(CreateControl(name, font, CLR_BLACK));
m_value_text = new TextControl(0, 0, detail::ATTRIBUTE_ROW_CONTROL_WIDTH, detail::ATTRIBUTE_ROW_HEIGHT, boost::lexical_cast<std::string>(m_value), font, CLR_BLACK, FORMAT_LEFT);
push_back(m_value_text);
}
template <class T>
void ConstAttributeRow<T>::Refresh()
{
m_value_text->SetText(boost::lexical_cast<std::string>(m_value));
}
template <class FlagType>
FlagAttributeRow<FlagType>::FlagAttributeRow(const std::string& name, Flags<FlagType>& flags, FlagType value, const boost::shared_ptr<Font>& font) :
m_flags(flags),
m_value(value),
m_check_box(0)
{
boost::shared_ptr<Font> font_to_use = GUI::GetGUI()->GetFont(font->FontName(), font->PointSize() + 2);
push_back(CreateControl(name, font, CLR_BLACK));
m_check_box = new StateButton(0, 0, detail::ATTRIBUTE_ROW_CONTROL_WIDTH, detail::ATTRIBUTE_ROW_HEIGHT, "", font_to_use, FORMAT_LEFT, CLR_GRAY);
m_check_box->SetCheck(m_flags & m_value);
push_back(m_check_box);
m_check_box_connection = Connect(m_check_box->CheckedSignal, &FlagAttributeRow::CheckChanged, this);
}
template <class FlagType>
void FlagAttributeRow<FlagType>::CheckChanged(bool checked)
{
if (checked)
m_flags |= m_value;
else
m_flags &= ~m_value;
ValueChangedSignal(m_flags);
ChangedSignal();
}
template <class FlagType>
void FlagAttributeRow<FlagType>::Update()
{
m_check_box_connection.block();
m_check_box->SetCheck(m_flags & m_value);
m_check_box_connection.unblock();
}
template <class FlagType>
FlagGroupAttributeRow<FlagType>::FlagGroupAttributeRow(const std::string& name, Flags<FlagType>& flags, FlagType value, const std::vector<FlagType>& group_values, const boost::shared_ptr<Font>& font) :
m_flags(flags),
m_value(value),
m_group_values(group_values),
m_flag_drop_list(0)
{
push_back(CreateControl(name, font, CLR_BLACK));
m_flag_drop_list = new DropDownList(0, 0, detail::ATTRIBUTE_ROW_CONTROL_WIDTH, font->Height() + 8, detail::ATTRIBUTE_ROW_HEIGHT * static_cast<int>(m_group_values.size()) + 4, CLR_GRAY);
Resize(m_flag_drop_list->Size());
m_flag_drop_list->SetInteriorColor(CLR_WHITE);
m_flag_drop_list->SetStyle(LIST_NOSORT);
for (unsigned int i = 0; i < m_group_values.size(); ++i) {
Row* row = new ListBox::Row();
row->push_back(CreateControl(boost::lexical_cast<std::string>(m_group_values[i]), font, CLR_BLACK));
m_flag_drop_list->Insert(row);
}
push_back(m_flag_drop_list);
unsigned int index = 0;
for (; index < m_group_values.size(); ++index) {
if (m_group_values[index] == value)
break;
}
if (index == m_group_values.size()) {
throw std::runtime_error("FlagGroupAttributeRow::FlagGroupAttributeRow() : Attempted to initialize a "
"flag group's drop-down list with a value that is not in the given set of group values.");
}
m_flag_drop_list->Select(index);
m_drop_list_connection = Connect(m_flag_drop_list->SelChangedSignal, &FlagGroupAttributeRow::SelectionChanged, this);
}
template <class FlagType>
void FlagGroupAttributeRow<FlagType>::SelectionChanged(int selection)
{
m_flags &= ~m_value;
m_value = m_group_values[selection];
m_flags |= m_value;
ValueChangedSignal(m_flags);
ChangedSignal();
}
template <class FlagType>
void FlagGroupAttributeRow<FlagType>::Update()
{
m_drop_list_connection.block();
unsigned int index = 0;
for (; index < m_group_values.size(); ++index) {
if (m_group_values[index] == m_value)
break;
}
m_flag_drop_list->Select(index);
m_drop_list_connection.unblock();
}
template <class T>
CustomTextRow<T>::CustomTextRow(const std::string& name, const T& functor, const Wnd*& wnd, const boost::shared_ptr<Font>& font) :
m_functor(functor),
m_wnd(wnd),
m_display_text(0)
{
push_back(CreateControl(name, font, CLR_BLACK));
m_display_text = new TextControl(0, 0, detail::ATTRIBUTE_ROW_CONTROL_WIDTH, detail::ATTRIBUTE_ROW_HEIGHT, m_functor(m_wnd), font, CLR_BLACK, FORMAT_LEFT);
Resize(m_display_text->Size());
push_back(m_display_text);
}
template <class T>
void CustomTextRow<T>::Refresh()
{
m_display_text->SetText(m_functor(m_wnd));
}
} // namespace GG
#endif // _GG_WndEditor_h_
See more files for this project here