Commit 42e66d0d authored by twanvl's avatar twanvl

Added support for custom colors for graphs;

Moved 'choice colors' from styel to field, split into 'choice colors' and 'choice colors cardlist';
Added support for pie graphs (no gui to use them, though);
Fixed bugs caused by selecting a card before the set was changed on all panels.
parent e8d995ee
......@@ -133,16 +133,3 @@ choice images:
hybrid vertical black / artifact : script: card_hybrid_2v("ba")
hybrid vertical red / artifact : script: card_hybrid_2v("ra")
hybrid vertical green / artifact : script: card_hybrid_2v("ga")
# Also define colors for card list
card list colors: true
choice colors:
white : rgb(130,130,110)
blue : rgb(0,64,168)
black : rgb(0,0,0)
red : rgb(168,0,0)
green : rgb(0,168,0)
colorless : rgb(72,90,100)
artifact : rgb(72,90,100)
multicolor : rgb(120,120,0)
land : rgb(84,84,60)
......@@ -163,4 +163,151 @@ choice:
choice: artifact / blue
choice: artifact / black
choice: artifact / red
choice: artifact / green
\ No newline at end of file
choice: artifact / green
# Also define colors for statistics
choice colors:
white : rgb(255,237,202)
blue : rgb(42,141,255)
black : rgb(33,33,33)
red : rgb(255,52,0)
green : rgb(138,230,0)
colorless : rgb(122,85,85)
artifact : rgb(188,192,195)
multicolor : rgb(255,188,14)
land : rgb(109,62,39)
# Sub menus, same colors
multicolor 2 color white / blue : rgb(255,188,14)
multicolor 2 color blue / black : rgb(255,188,14)
multicolor 2 color black / red : rgb(255,188,14)
multicolor 2 color red / green : rgb(255,188,14)
multicolor 2 color green / white : rgb(255,188,14)
multicolor 2 color white / black : rgb(255,188,14)
multicolor 2 color blue / red : rgb(255,188,14)
multicolor 2 color black / green : rgb(255,188,14)
multicolor 2 color red / white : rgb(255,188,14)
multicolor 2 color green / blue : rgb(255,188,14)
multicolor 3 color white / blue / black : rgb(255,188,14)
multicolor 3 color blue / black / red : rgb(255,188,14)
multicolor 3 color black / red / green : rgb(255,188,14)
multicolor 3 color red / green / white : rgb(255,188,14)
multicolor 3 color green / white / blue : rgb(255,188,14)
multicolor 3 color white / black / red : rgb(255,188,14)
multicolor 3 color blue / red / green : rgb(255,188,14)
multicolor 3 color black / green / white : rgb(255,188,14)
multicolor 3 color red / white / blue : rgb(255,188,14)
multicolor 3 color green / blue / black : rgb(255,188,14)
multicolor 4 color white / blue / black / red : rgb(255,188,14)
multicolor 4 color blue / black / red / green : rgb(255,188,14)
multicolor 4 color black / red / green / white : rgb(255,188,14)
multicolor 4 color red / green / white / blue : rgb(255,188,14)
multicolor 4 color green / white / blue / black : rgb(255,188,14)
multicolor 5 color white / blue / black / red / green : rgb(255,188,14)
multicolor 5 color horizontal white / blue / black / red / green: rgb(255,188,14)
land 1 color white : rgb(109,62,39)
land 1 color blue : rgb(109,62,39)
land 1 color black : rgb(109,62,39)
land 1 color red : rgb(109,62,39)
land 1 color green : rgb(109,62,39)
land 1 color multicolor : rgb(109,62,39)
land 2 color white / blue : rgb(109,62,39)
land 2 color blue / black : rgb(109,62,39)
land 2 color black / red : rgb(109,62,39)
land 2 color red / green : rgb(109,62,39)
land 2 color green / white : rgb(109,62,39)
land 2 color white / black : rgb(109,62,39)
land 2 color blue / red : rgb(109,62,39)
land 2 color black / green : rgb(109,62,39)
land 2 color red / white : rgb(109,62,39)
land 2 color green / blue : rgb(109,62,39)
hybrid 2 color white / blue : rgb(243,26,136) # purple
hybrid 2 color blue / black : rgb(243,26,136)
hybrid 2 color black / red : rgb(243,26,136)
hybrid 2 color red / green : rgb(243,26,136)
hybrid 2 color green / white : rgb(243,26,136)
hybrid 2 color white / black : rgb(243,26,136)
hybrid 2 color blue / red : rgb(243,26,136)
hybrid 2 color black / green : rgb(243,26,136)
hybrid 2 color red / white : rgb(243,26,136)
hybrid 2 color green / blue : rgb(243,26,136)
hybrid 2 color artifact / white : rgb(243,26,136)
hybrid 2 color artifact / blue : rgb(243,26,136)
hybrid 2 color artifact / black : rgb(243,26,136)
hybrid 2 color artifact / red : rgb(243,26,136)
hybrid 2 color artifact / green : rgb(243,26,136)
hybrid 3 color white / blue / black : rgb(243,26,136)
hybrid 3 color blue / black / red : rgb(243,26,136)
hybrid 3 color black / red / green : rgb(243,26,136)
hybrid 3 color red / green / white : rgb(243,26,136)
hybrid 3 color green / white / blue : rgb(243,26,136)
hybrid 3 color white / black / red : rgb(243,26,136)
hybrid 3 color blue / red / green : rgb(243,26,136)
hybrid 3 color black / green / white : rgb(243,26,136)
hybrid 3 color red / white / blue : rgb(243,26,136)
hybrid 3 color green / blue / black : rgb(243,26,136)
hybrid 3 color horizontal white / blue / black : rgb(243,26,136)
hybrid 3 color horizontal blue / black / red : rgb(243,26,136)
hybrid 3 color horizontal black / red / green : rgb(243,26,136)
hybrid 3 color horizontal red / green / white : rgb(243,26,136)
hybrid 3 color horizontal green / white / blue : rgb(243,26,136)
hybrid 3 color horizontal white / black / red : rgb(243,26,136)
hybrid 3 color horizontal blue / red / green : rgb(243,26,136)
hybrid 3 color horizontal black / green / white : rgb(243,26,136)
hybrid 3 color horizontal red / white / blue : rgb(243,26,136)
hybrid 3 color horizontal green / blue / black : rgb(243,26,136)
hybrid 4 color white / blue / black / red : rgb(243,26,136)
hybrid 4 color blue / black / red / green : rgb(243,26,136)
hybrid 4 color black / red / green / white : rgb(243,26,136)
hybrid 4 color red / green / white / blue : rgb(243,26,136)
hybrid 4 color green / white / blue / black : rgb(243,26,136)
hybrid 4 color horizontal white / blue / black / red : rgb(243,26,136)
hybrid 4 color horizontal blue / black / red / green : rgb(243,26,136)
hybrid 4 color horizontal black / red / green / white : rgb(243,26,136)
hybrid 4 color horizontal red / green / white / blue : rgb(243,26,136)
hybrid 4 color horizontal green / white / blue / black : rgb(243,26,136)
hybrid 5 color white / blue / black / red / green : rgb(243,26,136)
hybrid 5 color horizontal white / blue / black / red / green : rgb(243,26,136)
hybrid vertical white / blue : rgb(243,26,136)
hybrid vertical white / black : rgb(243,26,136)
hybrid vertical white / red : rgb(243,26,136)
hybrid vertical white / green : rgb(243,26,136)
hybrid vertical blue / white : rgb(243,26,136)
hybrid vertical blue / black : rgb(243,26,136)
hybrid vertical blue / red : rgb(243,26,136)
hybrid vertical blue / green : rgb(243,26,136)
hybrid vertical black / white : rgb(243,26,136)
hybrid vertical black / blue : rgb(243,26,136)
hybrid vertical black / red : rgb(243,26,136)
hybrid vertical black / green : rgb(243,26,136)
hybrid vertical red / white : rgb(243,26,136)
hybrid vertical red / blue : rgb(243,26,136)
hybrid vertical red / black : rgb(243,26,136)
hybrid vertical red / green : rgb(243,26,136)
hybrid vertical green / white : rgb(243,26,136)
hybrid vertical green / blue : rgb(243,26,136)
hybrid vertical green / red : rgb(243,26,136)
hybrid vertical green / black : rgb(243,26,136)
hybrid vertical artifact / white : rgb(243,26,136)
hybrid vertical artifact / blue : rgb(243,26,136)
hybrid vertical artifact / black : rgb(243,26,136)
hybrid vertical artifact / red : rgb(243,26,136)
hybrid vertical artifact / green : rgb(243,26,136)
hybrid vertical white / artifact : rgb(243,26,136)
hybrid vertical blue / artifact : rgb(243,26,136)
hybrid vertical black / artifact : rgb(243,26,136)
hybrid vertical red / artifact : rgb(243,26,136)
hybrid vertical green / artifact : rgb(243,26,136)
# TODO : Add the rest
# ... and for the card list
choice colors cardlist:
white : rgb(130,130,110)
blue : rgb(0,64,168)
black : rgb(0,0,0)
red : rgb(168,0,0)
green : rgb(0,168,0)
colorless : rgb(72,90,100)
artifact : rgb(72,90,100)
multicolor : rgb(120,120,0)
land : rgb(84,84,60)
# TODO : Add the rest
......@@ -333,6 +333,7 @@ init script:
number_of_items(in: sort(order: "WUBRG")) # colored mana
- number_of_items(in: sort(order:"/")) # guild mana, W/U -> 2 - 1
}
primary_card_color := filter_rule(match:"^[^ ]+")
# TODO : somewhere else?
#card to conversion:
......@@ -624,6 +625,12 @@ card field:
card list visible: true
card list column: 6
description: The rarity of the card, to edit the symbol switch to the 'set info' tab
choice colors:
basic land: rgb(109,62,39)
common: rgb(33,33,33)
uncommon: rgb(224,224,224)
rare: rgb(214,196,94)
special: rgb(58,7,80)
############################# Text box
card field:
......@@ -947,6 +954,22 @@ card field:
############################################################## Statistics categories
statistics dimension:
name: card color
script: primary_card_color(card.card_color)
icon: stats/card_color.png
colors:
white : rgb(255,237,202)
blue : rgb(42,141,255)
black : rgb(33,33,33)
red : rgb(255,52,0)
green : rgb(138,230,0)
colorless : rgb(122,85,85)
artifact : rgb(188,192,195)
multicolor : rgb(255,188,14)
land : rgb(109,62,39)
hybrid : rgb(243,26,136)
statistics dimension:
name: converted mana cost
script: cmc(card.casting_cost)
......
......@@ -34,15 +34,6 @@ card style:
equipment: card-equipment.jpg
location: card-location.jpg
plot twist: card-plot-twist.jpg
colors card list: true
choice colors:
character: rgb(120,18,0)
character dual: rgb(120,18,0)
concealed: rgb(26,26,26)
concealed dual: rgb(26,26,26)
equipment: rgb(80,80,80)
location: rgb(30,110,0)
plot twist: rgb(10,0,110)
############################# Name line
name:
......
......@@ -32,15 +32,6 @@ card style:
equipment: card-equipment.jpg
location: card-location.jpg
plot twist: card-plot-twist.jpg
colors card list: true
choice colors:
character: rgb(120,18,0)
character dual: rgb(120,18,0)
concealed: rgb(26,26,26)
concealed dual: rgb(26,26,26)
equipment: rgb(80,80,80)
location: rgb(30,110,0)
plot twist: rgb(10,0,110)
############################# Name line
name:
......
......@@ -186,7 +186,22 @@ card field:
choice: location
choice: plot twist
default: card_type()
show statistics: false
choice colors:
character: rgb(240,36,0)
character dual: rgb(240,36,0)
concealed: rgb(33,33,33)
concealed dual: rgb(33,33,33)
equipment: rgb(160,160,160)
location: rgb(60,220,0)
plot twist: rgb(20,0,220)
choice colors cardlist:
character: rgb(120,18,0)
character dual: rgb(120,18,0)
concealed: rgb(26,26,26)
concealed dual: rgb(26,26,26)
equipment: rgb(80,80,80)
location: rgb(30,110,0)
plot twist: rgb(10,0,110)
############################# Name line
card field:
......
......@@ -34,18 +34,6 @@ card style:
legendary dragons: card-dragons.jpg
spell card: card-spell.jpg
trap card: card-trap.jpg
colors card list: true
choice colors:
normal monster: rgb(120,18,0)
effect monster: rgb(120,18,0)
ritual monster: rgb(26,26,26)
fusion monster: rgb(26,26,26)
obelisk: rgb(26,26,26)
slifer: rgb(26,26,26)
ra: rgb(26,26,26)
legendary dragons: rgb(26,26,26)
spell card: rgb(80,80,80)
trap card: rgb(30,110,0)
############################# Name line
name:
......
......@@ -147,6 +147,17 @@ card field:
choice: spell card
choice: trap card
default: card_type()
choice colors cardlist:
normal monster: rgb(120,18,0)
effect monster: rgb(120,18,0)
ritual monster: rgb(26,26,26)
fusion monster: rgb(26,26,26)
obelisk: rgb(26,26,26)
slifer: rgb(26,26,26)
ra: rgb(26,26,26)
legendary dragons: rgb(26,26,26)
spell card: rgb(80,80,80)
trap card: rgb(30,110,0)
############################# Name line
card field:
......
......@@ -41,6 +41,8 @@ IMPLEMENT_REFLECTION(ChoiceField) {
REFLECT_IF_READING {
choices->initIds();
}
REFLECT(choice_colors);
REFLECT(choice_colors_cardlist);
}
// ----------------------------------------------------------------------------- : ChoiceField::Choice
......@@ -162,7 +164,6 @@ ChoiceStyle::ChoiceStyle(const ChoiceFieldP& field)
: Style(field)
, popup_style(POPUP_DROPDOWN)
, render_style(RENDER_TEXT)
, colors_card_list(false)
, combine(COMBINE_NORMAL)
, alignment(ALIGN_STRETCH)
, angle(0)
......@@ -242,10 +243,8 @@ IMPLEMENT_REFLECTION(ChoiceStyle) {
REFLECT(combine);
REFLECT(alignment);
REFLECT(angle);
REFLECT(colors_card_list);
REFLECT(font);
REFLECT(choice_images);
REFLECT(choice_colors);
}
// ----------------------------------------------------------------------------- : ChoiceValue
......
......@@ -37,6 +37,8 @@ class ChoiceField : public Field {
OptionalScript default_script; ///< Script that generates the default value
String initial; ///< Initial choice of a new value, or ""
String default_name; ///< Name of "default" value
map<String,Color> choice_colors; ///< Colors for the various choices (when color_cardlist)
map<String,Color> choice_colors_cardlist; ///< Colors for the various choices, for in the card list
virtual void initDependencies(Context&, const Dependency&) const;
......@@ -131,8 +133,6 @@ class ChoiceStyle : public Style {
ChoiceRenderStyle render_style; ///< Style of rendering
Font font; ///< Font for drawing text (when RENDER_TEXT)
map<String,ScriptableImage> choice_images; ///< Images for the various choices (when RENDER_IMAGE)
map<String,Color> choice_colors; ///< Colors for the various choices (when color_cardlist)
bool colors_card_list; ///< Does this field determine colors of the rows in the card list?
Scriptable<String> mask_filename; ///< Filename of an additional mask over the images
ImageCombine combine; ///< Combining mode for drawing the images
Alignment alignment; ///< Alignment of images
......
......@@ -8,21 +8,29 @@
#include <data/statistics.hpp>
#include <data/field.hpp>
#include <data/field/choice.hpp>
// ----------------------------------------------------------------------------- : Statistics dimension
StatsDimension::StatsDimension()
: automatic(false)
, numeric(false)
: automatic (false)
, numeric (false)
, show_empty(false)
{}
StatsDimension::StatsDimension(const Field& field)
: automatic(true)
: automatic (true)
, name (field.name)
, description (field.description)
, icon_filename(field.icon_filename)
, numeric(false)
, numeric (false)
, show_empty (false)
{
// choice colors?
const ChoiceField* choice_field = dynamic_cast<const ChoiceField*>(&field);
if (choice_field) {
colors = choice_field->choice_colors;
}
// initialize script, card.{field_name}
Script& s = script.getScript();
s.addInstruction(I_GET_VAR, string_to_variable(_("card")));
......@@ -37,6 +45,8 @@ IMPLEMENT_REFLECTION(StatsDimension) {
REFLECT_N("icon", icon_filename);
REFLECT(script);
REFLECT(numeric);
REFLECT(show_empty);
REFLECT(colors);
}
}
......
......@@ -26,12 +26,14 @@ class StatsDimension {
StatsDimension();
StatsDimension(const Field&);
bool automatic; ///< Based on a card field?
String name; ///< Name of this dimension
String description; ///< Description, used in status bar
String icon_filename; ///< Icon for lists
OptionalScript script; ///< Script that determines the value(s)
bool numeric; ///< Are the values numeric? If so, they require special sorting
bool automatic; ///< Based on a card field?
String name; ///< Name of this dimension
String description; ///< Description, used in status bar
String icon_filename; ///< Icon for lists
OptionalScript script; ///< Script that determines the value(s)
bool numeric; ///< Are the values numeric? If so, they require special sorting
bool show_empty; ///< Should "" be shown?
map<String,Color> colors; ///< Colors for the categories
DECLARE_REFLECTION();
};
......
......@@ -176,6 +176,7 @@ void CardListBase::rebuild() {
column_fields.clear();
selected_item_pos = -1;
onRebuild();
if (!set) return;
// determine column order
map<int,FieldP> new_column_fields;
FOR_EACH(f, set->game->card_fields) {
......@@ -197,7 +198,7 @@ void CardListBase::rebuild() {
column_fields.push_back(f.second);
}
// find field that determines color
color_style = findColorStyle();
color_field = findColorField();
// determine sort settings
GameSettings& gs = settings.gameSettingsFor(*set->game);
sort_ascending = gs.sort_cards_ascending;
......@@ -216,18 +217,16 @@ void CardListBase::rebuild() {
++i;
}
refreshList();
// select a card if possible
selectItemPos(0, true);
}
ChoiceStyleP CardListBase::findColorStyle() {
FOR_EACH(s, set->stylesheet->card_style) {
ChoiceStyleP cs = dynamic_pointer_cast<ChoiceStyle>(s);
if (cs && cs->colors_card_list) {
return cs;
ChoiceFieldP CardListBase::findColorField() {
FOR_EACH(s, set->game->card_fields) {
ChoiceFieldP cf = dynamic_pointer_cast<ChoiceField>(s);
if (cf && !cf->choice_colors_cardlist.empty()) {
return cf;
}
}
return ChoiceStyleP();
return ChoiceFieldP();
}
// ----------------------------------------------------------------------------- : CardListBase : Columns
......@@ -270,10 +269,10 @@ int CardListBase::OnGetItemImage(long pos) const {
}
wxListItemAttr* CardListBase::OnGetItemAttr(long pos) const {
if (!color_style) return nullptr;
ChoiceValueP val = static_pointer_cast<ChoiceValue>( getCard(pos)->data[color_style->fieldP]);
if (!color_field) return nullptr;
ChoiceValueP val = static_pointer_cast<ChoiceValue>( getCard(pos)->data[color_field]);
assert(val);
item_attr.SetTextColour(color_style->choice_colors[val->value()]); // if it doesn't exist we get black
item_attr.SetTextColour(color_field->choice_colors_cardlist[val->value()]); // if it doesn't exist we get black
return &item_attr;
}
......
......@@ -13,7 +13,7 @@
#include <gui/control/item_list.hpp>
#include <data/set.hpp>
DECLARE_POINTER_TYPE(ChoiceStyle);
DECLARE_POINTER_TYPE(ChoiceField);
DECLARE_POINTER_TYPE(Field);
// ----------------------------------------------------------------------------- : Events
......@@ -102,14 +102,13 @@ class CardListBase : public ItemList, public SetView {
// --------------------------------------------------- : Data
private:
// display stuff
ChoiceStyleP color_style; ///< Style (and field) to use for text color (optional)
ChoiceFieldP color_field; ///< Field to use for text color (optional)
vector<FieldP> column_fields; ///< The field to use for each column (by column index)
mutable wxListItemAttr item_attr; // for OnGetItemAttr
/// Find the field that determines the color, if any.
/** Note: Uses only fields from the set's default style */
ChoiceStyleP findColorStyle();
ChoiceFieldP findColorField();
/// Store the column sizes in the settings
void storeColumns();
......
......@@ -21,6 +21,12 @@ void FilteredCardList::setFilter(const CardListFilterP& filter) {
rebuild();
}
void FilteredCardList::onChangeSet() {
// clear filter before changing set, the filter might not make sense for a different set
filter = CardListFilterP();
CardListBase::onChangeSet();
}
void FilteredCardList::getItems(vector<VoidP>& out) const {
if (filter) {
FOR_EACH(c, set->cards) {
......
......@@ -37,7 +37,9 @@ class FilteredCardList : public CardListBase {
protected:
/// Get only the subset of the cards
virtual void getItems(vector<VoidP>& out) const;
virtual void onChangeSet();
private:
CardListFilterP filter; ///< Filter with which this.cards is made
};
......
This diff is collapsed.
......@@ -39,22 +39,33 @@ class GraphGroup {
UInt size; ///< Number of elements in this group
};
/// Automatic coloring mode
enum AutoColor
{ AUTO_COLOR_NO
, AUTO_COLOR_EVEN
, AUTO_COLOR_WEIGHTED
};
/// An axis in a graph, consists of a list of groups
/** The sum of groups.sum = sum of all elements in the data */
class GraphAxis {
public:
GraphAxis(const String& name, bool auto_color = true, bool numeric = false)
GraphAxis(const String& name, AutoColor auto_color = AUTO_COLOR_EVEN, bool numeric = false, const map<String,Color>* colors = nullptr)
: name(name)
, auto_color(auto_color)
, numeric(numeric)
, max(0)
, total(0)
, colors(colors)
{}
String name; ///< Name/label of this axis
bool auto_color; ///< Automatically assign colors to the groups on this axis
AutoColor auto_color; ///< Automatically assign colors to the groups on this axis
vector<GraphGroup> groups; ///< Groups along this axis
bool numeric; ///< Numeric axis?
UInt max; ///< Maximum size of the groups
UInt total; ///< Sum of the size of all groups
const map<String,Color>* colors; ///< Colors for each choice (optional
};
/// A single data point of a graph
......@@ -87,13 +98,21 @@ class GraphData {
// ----------------------------------------------------------------------------- : Graph
enum DrawLayer
{ LAYER_BOTTOM = 0
, LAYER_SELECTION = 0
, LAYER_AXES
, LAYER_VALUES
, LAYER_COUNT
};
/// A type of graph
/** It is rendered into a sub-rectangle of the screen */
class Graph {
public:
virtual ~Graph() {}
/// Draw this graph, filling the internalRect() of the dc.
virtual void draw(RotatedDC& dc, const vector<int>& current) const = 0;
virtual void draw(RotatedDC& dc, const vector<int>& current, DrawLayer layer) const = 0;
/// Find the item at the given position, the rectangle gives the screen size
virtual bool findItem(const RealPoint& pos, const RealRect& rect, vector<int>& out) const { return false; }
/// Change the data
......@@ -110,13 +129,13 @@ class Graph {
class Graph1D : public Graph {
public:
inline Graph1D(size_t axis) : axis(axis) {}
virtual void draw(RotatedDC& dc, const vector<int>& current) const;
virtual void draw(RotatedDC& dc, const vector<int>& current, DrawLayer layer) const;
virtual bool findItem(const RealPoint& pos, const RealRect& rect, vector<int>& out) const;
protected:
size_t axis;
/// Find an item, return the position along the axis, or -1 if not found
virtual int findItem(const RealPoint& pos, const RealRect& rect) const = 0;
virtual void draw(RotatedDC& dc, int current) const = 0;
virtual int findItem(const RealPoint& pos, const RealRect& rect) const { return -1; }
virtual void draw(RotatedDC& dc, int current, DrawLayer layer) const = 0;
inline GraphAxis& axis_data() const { return *data->axes.at(axis); }
};
......@@ -124,7 +143,7 @@ class Graph1D : public Graph {
class BarGraph : public Graph1D {
public:
inline BarGraph(size_t axis) : Graph1D(axis) {}
virtual void draw(RotatedDC& dc, int current) const;
virtual void draw(RotatedDC& dc, int current, DrawLayer layer) const;
virtual int findItem(const RealPoint& pos, const RealRect& rect) const;
};
......@@ -136,7 +155,7 @@ class BarGraph : public Graph1D {
class PieGraph : public Graph1D {
public:
inline PieGraph(size_t axis) : Graph1D(axis) {}
virtual void draw(RotatedDC& dc, int current) const;
virtual void draw(RotatedDC& dc, int current, DrawLayer layer) const;
virtual int findItem(const RealPoint& pos, const RealRect& rect) const;
};
......@@ -144,7 +163,7 @@ class PieGraph : public Graph1D {
class GraphLegend : public Graph1D {
public:
inline GraphLegend(size_t axis) : Graph1D(axis) {}
virtual void draw(RotatedDC& dc, int current) const;
virtual void draw(RotatedDC& dc, int current, DrawLayer layer) const;
virtual int findItem(const RealPoint& pos, const RealRect& rect) const;
};
......@@ -155,9 +174,43 @@ class GraphLegend : public Graph1D {
// virtual void draw(RotatedDC& dc) const;
//};
//class GraphValueAxis {
// virtual void draw(RotatedDC& dc) const;
//};
/// Draws an a vertical axis for counts
class GraphValueAxis : public Graph1D {
public:
inline GraphValueAxis(size_t axis) : Graph1D(axis) {}
virtual void draw(RotatedDC& dc, int current, DrawLayer layer) const;
};
/// A graph with margins
class GraphWithMargins : public Graph {
public:
inline GraphWithMargins(const GraphP& graph,
double margin_left, double margin_top, double margin_right, double margin_bottom,
bool upside_down = false)
: graph(graph)
, margin_left(margin_left), margin_top(margin_top), margin_right(margin_right), margin_bottom(margin_bottom)
, upside_down(upside_down)
{}
virtual void draw(RotatedDC& dc, const vector<int>& current, DrawLayer layer) const;
virtual bool findItem(const RealPoint& pos, const RealRect& rect, vector<int>& out) const;
virtual void setData(const GraphDataP& d);
private:
double margin_left, margin_top, margin_right, margin_bottom;
bool upside_down; // put the coordinate system upside down, since graphs are usually bottom-to-top
const GraphP graph;
};
/// A display containing multiple graphs
class GraphContainer : public Graph {
public:
virtual void draw(RotatedDC& dc, const vector<int>& current, DrawLayer layer) const;
virtual bool findItem(const RealPoint& pos, const RealRect& rect, vector<int>& out) const;
virtual void setData(const GraphDataP& d);
void add(const GraphP& graph);
private:
vector<GraphP> items;
};
// ----------------------------------------------------------------------------- : Graph control
......@@ -167,6 +220,8 @@ class GraphControl : public wxControl {
/// Create a graph control
GraphControl(Window* parent, int id);
/// Set the type of graph used, from a number of predefined choices
void setLayout();
/// Update the data in the graph
void setData(const GraphDataPre& data);
/// Update the data in the graph
......
......@@ -39,6 +39,10 @@ void ItemList::selectNext() {
assert(selected_item_pos + 1 < (long)sorted_list.size());
selectItemPos(selected_item_pos + 1, true);
}
void ItemList::selectFirst() {
assert(0 < (long)sorted_list.size());
selectItemPos(0, true);
}
// ----------------------------------------------------------------------------- : ItemList : Selection (private)
......
......@@ -34,6 +34,8 @@ class ItemList : public wxListView {
void selectPrevious();
/// Move the selection to the next item (if possible)
void selectNext();
/// Move the selection to the first item (if possible)
void selectFirst();
// --------------------------------------------------- : Virtual interface
protected:
......
......@@ -340,3 +340,8 @@ void CardsPanel::selectCard(const CardP& card) {
notes->setValue(card ? &card->notes : nullptr);
Layout();
}
void CardsPanel::selectFirstCard() {
if (!set) return; // we want onChangeSet first
card_list->selectFirst();
}
......@@ -68,6 +68,7 @@ class CardsPanel : public SetWindowPanel {
// --------------------------------------------------- : Selection
virtual CardP selectedCard() const;
virtual void selectCard(const CardP& card);
virtual void selectFirstCard();
private:
// --------------------------------------------------- : Controls
......
......@@ -68,6 +68,7 @@ class SetWindowPanel : public wxPanel, public SetView {
// --------------------------------------------------- : Selection
virtual CardP selectedCard() const { return CardP(); } ///< Return the currently selected card, or CardP()
virtual void selectCard(const CardP& card) {} ///< Switch the view to another card
virtual void selectFirstCard() {} ///< Switch the view to the first card
};
// ----------------------------------------------------------------------------- : EOF
......
......@@ -14,6 +14,7 @@
#include <data/statistics.hpp>
#include <util/window_id.hpp>
#include <util/alignment.hpp>
#include <util/tagged_string.hpp>
#include <gfx/gfx.hpp>
#include <wx/splitter.h>
......@@ -52,6 +53,8 @@ class StatCategoryList : public GalleryList {
void StatCategoryList::show(const GameP& game) {
this->game = game;
update();
// select first item
selection = itemCount() > 0 ? 0 : NO_SELECTION;
}
size_t StatCategoryList::itemCount() const {
......@@ -74,13 +77,11 @@ void StatCategoryList::drawItem(DC& dc, int x, int y, size_t item, bool selected
// draw name
RealRect rect(RealPoint(x + 24, y), RealSize(item_size.x - 30, item_size.y));
String str = capitalize(cat.name);
// dc.SetFont(wxFont(9.5 * text_scaling, wxSWISS, wxNORMAL, wxNORMAL, false,_("Arial")));
dc.SetFont(*wxNORMAL_FONT);
int w, h;
dc.GetTextExtent(str, &w, &h);
RealSize size = RealSize(w,h);
RealPoint pos = align_in_rect(ALIGN_MIDDLE_LEFT, size, rect);
// draw_resampled_text(dc, RealRect(pos, size), 0, 0, 0, str);
dc.DrawText(str, (int)pos.x, (int)pos.y);
}
......@@ -110,30 +111,13 @@ StatsPanel::StatsPanel(Window* parent, int id)
void StatsPanel::onChangeSet() {
card_list->setSet(set);
categories->show(set->game);
filterCards();
onCategorySelect();
}
void StatsPanel::onCommand(int id) {
switch (id) {
case ID_FIELD_LIST: {
// change graph data
if (categories->hasSelection()) {
StatsCategory& cat = categories->getSelection();
GraphDataPre d;
FOR_EACH(dim, cat.dimensions) {
d.axes.push_back(new_shared3<GraphAxis>(dim->name, true, dim->numeric));
}
FOR_EACH(card, set->cards) {
Context& ctx = set->getContext(card);
GraphElementP e(new GraphElement);
FOR_EACH(dim, cat.dimensions) {
e->values.push_back(*dim->script.invoke(ctx));
}
d.elements.push_back(e);
}
graph->setData(d);
filterCards();
}
onCategorySelect();
break;
}
}
......@@ -158,6 +142,41 @@ class StatsFilter : public CardListFilter {
Set& set;
};
void StatsPanel::onCategorySelect() {
// change graph data
if (categories->hasSelection()) {
StatsCategory& cat = categories->getSelection();
GraphDataPre d;
FOR_EACH(dim, cat.dimensions) {
d.axes.push_back(new_shared4<GraphAxis>(
dim->name,
dim->colors.empty() ? AUTO_COLOR_EVEN : AUTO_COLOR_NO,
dim->numeric,
&dim->colors
)
);
}
FOR_EACH(card, set->cards) {
Context& ctx = set->getContext(card);
GraphElementP e(new GraphElement);
bool show = true;
FOR_EACH(dim, cat.dimensions) {
String value = untag(dim->script.invoke(ctx)->toString());
e->values.push_back(value);
if (value.empty() && !dim->show_empty) {
// don't show this element
show = false;
break;
}
}
if (show) {
d.elements.push_back(e);
}
}
graph->setData(d);
filterCards();
}
}
void StatsPanel::onGraphSelect(wxCommandEvent&) {
filterCards();
}
......
......@@ -40,6 +40,7 @@ class StatsPanel : public SetWindowPanel {
GraphControl* graph;
FilteredCardList* card_list;
void onCategorySelect();
void onGraphSelect(wxCommandEvent&);
void filterCards();
};
......
......@@ -77,7 +77,7 @@ void StylePanel::selectCard(const CardP& card) {
// ----------------------------------------------------------------------------- : Events
void StylePanel::onStyleSelect(wxCommandEvent&) {
if (list->hasSelection()) {
if (list->hasSelection() && card) {
StyleSheetP stylesheet = list->getSelection<StyleSheet>();
if (stylesheet == set->stylesheet) {
// select no special style when selecting the same style as the set default
......
......@@ -131,15 +131,12 @@ SetWindow::SetWindow(Window* parent, const SetP& set)
SetSizer(s);
// panels
// NOTE: place the CardsPanel last in the panels list,
// this way the card list is the last to be told of a set change
// this way everyone else already uses the new set when it sends a CardSelectEvent
addPanel(menuWindow, tabBar, new CardsPanel (this, wxID_ANY), 4, _("cards tab"));
addPanel(menuWindow, tabBar, new SetInfoPanel (this, wxID_ANY), 0, _("set info tab"));
addPanel(menuWindow, tabBar, new StylePanel (this, wxID_ANY), 1, _("style tab"));
addPanel(menuWindow, tabBar, new KeywordsPanel(this, wxID_ANY), 2, _("keywords tab"));
addPanel(menuWindow, tabBar, new StatsPanel (this, wxID_ANY), 3, _("stats tab"));
// addPanel(*s, *menuWindow, *tabBar, new DraftPanel (&this, wxID_ANY), 4, _("F10"))
addPanel(menuWindow, tabBar, new CardsPanel (this, wxID_ANY), 0, _("cards tab"));
addPanel(menuWindow, tabBar, new SetInfoPanel (this, wxID_ANY), 1, _("set info tab"));
addPanel(menuWindow, tabBar, new StylePanel (this, wxID_ANY), 2, _("style tab"));
addPanel(menuWindow, tabBar, new KeywordsPanel(this, wxID_ANY), 3, _("keywords tab"));
addPanel(menuWindow, tabBar, new StatsPanel (this, wxID_ANY), 4, _("stats tab"));
// addPanel(*s, *menuWindow, *tabBar, new DraftPanel (&this, wxID_ANY), 5, _("F10"))
selectPanel(ID_WINDOW_CARDS); // select cards panel
// loose ends
......@@ -241,6 +238,10 @@ void SetWindow::onChangeSet() {
FOR_EACH(p, panels) {
p->setSet(set);
}
// only after setSet select a card
FOR_EACH(p, panels) {
p->selectFirstCard();
}
fixMinWindowSize();
}
......
......@@ -93,6 +93,13 @@ void DataViewer::setCard(const CardP& card, bool refresh) {
onChangeSize();
}
void DataViewer::onChangeSet() {
viewers.clear();
onInit();
onChange();
onChangeSize();
}
// ----------------------------------------------------------------------------- : Viewers
struct CompareViewer {
......
......@@ -67,6 +67,9 @@ class DataViewer : public SetView {
/** \param refresh: Always refresh, even if this card is already shown */
void setCard(const CardP& card, bool refresh = false);
/// Clear data
virtual void onChangeSet();
// --------------------------------------------------- : The viewers
protected:
/// Set the styles for the data to be shown, recreating the viewers
......
......@@ -330,7 +330,7 @@ SCRIPT_FUNCTION(replace) {
class ScriptFilterRule : public ScriptValue {
public:
virtual ScriptType type() const { return SCRIPT_FUNCTION; }
virtual String typeName() const { return _("replace_rule"); }
virtual String typeName() const { return _("filter_rule"); }
virtual ScriptValueP eval(Context& ctx) const {
SCRIPT_PARAM(String, input);
String ret;
......
......@@ -172,6 +172,31 @@ void RotatedDC::DrawRoundedRectangle(const RealRect& r, double radius) {
dc.DrawRoundedRectangle(r_ext.x, r_ext.y, r_ext.width, r_ext.height, trS(radius));
}
/// Convert radians to degrees
double rad_to_deg(double rad) { return rad * (180.0 / M_PI); }
/// Convert degrees to radians
double deg_to_rad(double deg) { return deg * (M_PI / 180.0); }
void RotatedDC::DrawEllipticArc(const RealPoint& center, const RealSize& size, double start, double end) {
wxPoint c_ext = tr(center - size/2);
wxSize s_ext = trNoNeg(size);
dc.DrawEllipticArc(c_ext.x, c_ext.y, s_ext.x, s_ext.y, rad_to_deg(start) + angle, rad_to_deg(end) + angle);
}
void RotatedDC::DrawEllipticSpoke(const RealPoint& center, const RealSize& size, double angle) {
wxPoint c_ext = tr(center - size/2);
wxSize s_ext = trNoNeg(size);
double rot_angle = angle + deg_to_rad(this->angle);
double sin_angle = sin(rot_angle), cos_angle = cos(rot_angle);
// position of center and of point on the boundary can vary because of rounding errors,
// this code matches DrawEllipticArc (at least on windows xp).
dc.DrawLine(
c_ext.x + int( 0.5 * (s_ext.x + cos_angle) ), // center
c_ext.y + int( 0.5 * (s_ext.y - sin_angle) ),
c_ext.x + int( 0.5 + 0.5 * (s_ext.x-1) * (1 + cos_angle) ), // boundary
c_ext.y + int( 0.5 + 0.5 * (s_ext.y-1) * (1 - sin_angle) )
);
}
// ----------------------------------------------------------------------------- : Forwarded properties
void RotatedDC::SetPen(const wxPen& pen) { dc.SetPen(pen); }
......
......@@ -146,6 +146,10 @@ class RotatedDC : public Rotation {
void DrawLine (const RealPoint& p1, const RealPoint& p2);
void DrawRectangle(const RealRect& r);
void DrawRoundedRectangle(const RealRect& r, double radius);
/// Draw an arc of an ellipse, angles are in radians
void DrawEllipticArc(const RealPoint& center, const RealSize& size, double start, double end);
/// Draw spokes of an ellipse
void DrawEllipticSpoke(const RealPoint& center, const RealSize& size, double start);
// Fill the dc with the color of the current brush
void Fill();
......
......@@ -57,11 +57,11 @@ enum MenuID {
// Window menu (MainWindow)
, ID_WINDOW_NEW = 201
, ID_WINDOW_MIN = 202
, ID_WINDOW_CARDS = ID_WINDOW_MIN + 4 // see SetWindow::SetWindow
, ID_WINDOW_SET = ID_WINDOW_MIN + 0
, ID_WINDOW_STYLE = ID_WINDOW_MIN + 1
, ID_WINDOW_KEYWORDS = ID_WINDOW_MIN + 2
, ID_WINDOW_STATS = ID_WINDOW_MIN + 3
, ID_WINDOW_CARDS = ID_WINDOW_MIN + 0
, ID_WINDOW_SET = ID_WINDOW_MIN + 1
, ID_WINDOW_STYLE = ID_WINDOW_MIN + 2
, ID_WINDOW_KEYWORDS = ID_WINDOW_MIN + 3
, ID_WINDOW_STATS = ID_WINDOW_MIN + 4
, ID_WINDOW_MAX = 220
// Help menu (MainWindow)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment