mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-11 13:17:00 -04:00
Choice images recomputed less often;
Implemented GraphType for choosing different layouts on the stats panel; Added option to define order of graph groups; Added busy cursor when loading recent file; Parentheses in FOR_EACH macro git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@351 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -164,6 +164,7 @@ ChoiceStyle::ChoiceStyle(const ChoiceFieldP& field)
|
|||||||
: Style(field)
|
: Style(field)
|
||||||
, popup_style(POPUP_DROPDOWN)
|
, popup_style(POPUP_DROPDOWN)
|
||||||
, render_style(RENDER_TEXT)
|
, render_style(RENDER_TEXT)
|
||||||
|
, choice_images_initialized(false)
|
||||||
, combine(COMBINE_NORMAL)
|
, combine(COMBINE_NORMAL)
|
||||||
, alignment(ALIGN_STRETCH)
|
, alignment(ALIGN_STRETCH)
|
||||||
, angle(0)
|
, angle(0)
|
||||||
@@ -179,10 +180,14 @@ bool ChoiceStyle::update(Context& ctx) {
|
|||||||
// Don't update the choice images, leave that to invalidate()
|
// Don't update the choice images, leave that to invalidate()
|
||||||
bool change = Style ::update(ctx)
|
bool change = Style ::update(ctx)
|
||||||
| mask_filename.update(ctx);
|
| mask_filename.update(ctx);
|
||||||
FOR_EACH(ci, choice_images) {
|
if (!choice_images_initialized) {
|
||||||
if (ci.second.update(ctx)) {
|
// we only want to do this once because it is rather slow, other updates are handled by dependencies
|
||||||
change = true;
|
choice_images_initialized = true;
|
||||||
// TODO : remove this thumbnail
|
FOR_EACH(ci, choice_images) {
|
||||||
|
if (ci.second.update(ctx)) {
|
||||||
|
change = true;
|
||||||
|
// TODO : remove this thumbnail
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ class ChoiceStyle : public Style {
|
|||||||
ChoiceRenderStyle render_style; ///< Style of rendering
|
ChoiceRenderStyle render_style; ///< Style of rendering
|
||||||
Font font; ///< Font for drawing text (when RENDER_TEXT)
|
Font font; ///< Font for drawing text (when RENDER_TEXT)
|
||||||
map<String,ScriptableImage> choice_images; ///< Images for the various choices (when RENDER_IMAGE)
|
map<String,ScriptableImage> choice_images; ///< Images for the various choices (when RENDER_IMAGE)
|
||||||
|
bool choice_images_initialized;
|
||||||
Scriptable<String> mask_filename; ///< Filename of an additional mask over the images
|
Scriptable<String> mask_filename; ///< Filename of an additional mask over the images
|
||||||
ImageCombine combine; ///< Combining mode for drawing the images
|
ImageCombine combine; ///< Combining mode for drawing the images
|
||||||
Alignment alignment; ///< Alignment of images
|
Alignment alignment; ///< Alignment of images
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) 2001 - 2007 Twan van Laarhoven |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#ifndef HEADER_DATA_GRAPH_TYPE
|
||||||
|
#define HEADER_DATA_GRAPH_TYPE
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <util/prec.hpp>
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : GraphType
|
||||||
|
|
||||||
|
/// Types of graphs
|
||||||
|
enum GraphType
|
||||||
|
{ GRAPH_TYPE_BAR
|
||||||
|
, GRAPH_TYPE_PIE
|
||||||
|
, GRAPH_TYPE_STACK
|
||||||
|
, GRAPH_TYPE_SCATTER
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : EOF
|
||||||
|
#endif
|
||||||
+15
-8
@@ -29,10 +29,14 @@ StatsDimension::StatsDimension(const Field& field)
|
|||||||
, numeric (false)
|
, numeric (false)
|
||||||
, show_empty (false)
|
, show_empty (false)
|
||||||
{
|
{
|
||||||
// choice colors?
|
// choice field?
|
||||||
const ChoiceField* choice_field = dynamic_cast<const ChoiceField*>(&field);
|
const ChoiceField* choice_field = dynamic_cast<const ChoiceField*>(&field);
|
||||||
if (choice_field) {
|
if (choice_field) {
|
||||||
colors = choice_field->choice_colors;
|
colors = choice_field->choice_colors;
|
||||||
|
int count = choice_field->choices->lastId();
|
||||||
|
for (int i = 0 ; i < count ; ++i) {
|
||||||
|
groups.push_back(choice_field->choices->choiceName(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// initialize script, card.{field_name}
|
// initialize script, card.{field_name}
|
||||||
Script& s = script.getScript();
|
Script& s = script.getScript();
|
||||||
@@ -50,6 +54,7 @@ IMPLEMENT_REFLECTION_NO_GET_MEMBER(StatsDimension) {
|
|||||||
REFLECT(numeric);
|
REFLECT(numeric);
|
||||||
REFLECT(show_empty);
|
REFLECT(show_empty);
|
||||||
REFLECT(colors);
|
REFLECT(colors);
|
||||||
|
REFLECT(groups);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,13 +74,6 @@ StatsCategory::StatsCategory(const StatsDimensionP& dim)
|
|||||||
, type(GRAPH_TYPE_BAR)
|
, type(GRAPH_TYPE_BAR)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION_ENUM(GraphType) {
|
|
||||||
VALUE_N("bar", GRAPH_TYPE_BAR);
|
|
||||||
VALUE_N("stack", GRAPH_TYPE_STACK);
|
|
||||||
VALUE_N("pie", GRAPH_TYPE_PIE);
|
|
||||||
VALUE_N("scatter", GRAPH_TYPE_SCATTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION_NO_GET_MEMBER(StatsCategory) {
|
IMPLEMENT_REFLECTION_NO_GET_MEMBER(StatsCategory) {
|
||||||
if (!automatic) {
|
if (!automatic) {
|
||||||
REFLECT(name);
|
REFLECT(name);
|
||||||
@@ -103,3 +101,12 @@ void StatsCategory::find_dimensions(const vector<StatsDimensionP>& available) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : GraphType (from graph_type.hpp)
|
||||||
|
|
||||||
|
IMPLEMENT_REFLECTION_ENUM(GraphType) {
|
||||||
|
VALUE_N("bar", GRAPH_TYPE_BAR);
|
||||||
|
VALUE_N("pie", GRAPH_TYPE_PIE);
|
||||||
|
VALUE_N("stack", GRAPH_TYPE_STACK);
|
||||||
|
VALUE_N("scatter", GRAPH_TYPE_SCATTER);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <util/reflect.hpp>
|
#include <util/reflect.hpp>
|
||||||
|
#include <data/graph_type.hpp>
|
||||||
#include <script/scriptable.hpp>
|
#include <script/scriptable.hpp>
|
||||||
|
|
||||||
class Field;
|
class Field;
|
||||||
@@ -34,20 +35,13 @@ class StatsDimension : public IntrusivePtrBase<StatsDimension> {
|
|||||||
bool numeric; ///< Are the values numeric? If so, they require special sorting
|
bool numeric; ///< Are the values numeric? If so, they require special sorting
|
||||||
bool show_empty; ///< Should "" be shown?
|
bool show_empty; ///< Should "" be shown?
|
||||||
map<String,Color> colors; ///< Colors for the categories
|
map<String,Color> colors; ///< Colors for the categories
|
||||||
|
vector<String> groups; ///< Order of the items
|
||||||
|
|
||||||
DECLARE_REFLECTION();
|
DECLARE_REFLECTION();
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Statistics category
|
// ----------------------------------------------------------------------------- : Statistics category
|
||||||
|
|
||||||
/// Types of graphs
|
|
||||||
enum GraphType
|
|
||||||
{ GRAPH_TYPE_BAR
|
|
||||||
, GRAPH_TYPE_STACK
|
|
||||||
, GRAPH_TYPE_PIE
|
|
||||||
, GRAPH_TYPE_SCATTER
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A category for statistics
|
/// A category for statistics
|
||||||
/** Can be generated automatically based on a dimension */
|
/** Can be generated automatically based on a dimension */
|
||||||
class StatsCategory : public IntrusivePtrBase<StatsCategory> {
|
class StatsCategory : public IntrusivePtrBase<StatsCategory> {
|
||||||
|
|||||||
+74
-24
@@ -17,6 +17,7 @@ DECLARE_TYPEOF_COLLECTION(GraphGroup);
|
|||||||
DECLARE_TYPEOF_COLLECTION(GraphP);
|
DECLARE_TYPEOF_COLLECTION(GraphP);
|
||||||
DECLARE_TYPEOF_COLLECTION(int);
|
DECLARE_TYPEOF_COLLECTION(int);
|
||||||
DECLARE_TYPEOF_COLLECTION(vector<int>);
|
DECLARE_TYPEOF_COLLECTION(vector<int>);
|
||||||
|
DECLARE_TYPEOF_COLLECTION(String);
|
||||||
DECLARE_TYPEOF(map<String COMMA UInt>);
|
DECLARE_TYPEOF(map<String COMMA UInt>);
|
||||||
|
|
||||||
template <typename T> inline T sgn(T v) { return v < 0 ? -1 : 1; }
|
template <typename T> inline T sgn(T v) { return v < 0 ? -1 : 1; }
|
||||||
@@ -48,7 +49,7 @@ GraphData::GraphData(const GraphDataPre& d)
|
|||||||
FOR_EACH_CONST(e, d.elements) {
|
FOR_EACH_CONST(e, d.elements) {
|
||||||
counts[e->values[i]] += 1;
|
counts[e->values[i]] += 1;
|
||||||
}
|
}
|
||||||
// TODO: allow some ordering in the groups, and allow colors to be passed
|
// TODO: allow some ordering in the groups
|
||||||
if (a->numeric) {
|
if (a->numeric) {
|
||||||
// TODO: start at something other than 0?
|
// TODO: start at something other than 0?
|
||||||
// TODO: support fractions?
|
// TODO: support fractions?
|
||||||
@@ -75,6 +76,14 @@ GraphData::GraphData(const GraphDataPre& d)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (a->order) {
|
||||||
|
// specific group order
|
||||||
|
FOR_EACH_CONST(gn, *a->order) {
|
||||||
|
UInt count = counts[gn];
|
||||||
|
a->groups.push_back(GraphGroup(gn, count));
|
||||||
|
a->max = max(a->max, count);
|
||||||
|
a->total += count;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
FOR_EACH(c, counts) {
|
FOR_EACH(c, counts) {
|
||||||
a->groups.push_back(GraphGroup(c.first, c.second));
|
a->groups.push_back(GraphGroup(c.first, c.second));
|
||||||
@@ -175,19 +184,16 @@ RealRect bar_graph_bar(const RealRect& rect, int group, int group_count, int sta
|
|||||||
double width = width_space / 5 * 4;
|
double width = width_space / 5 * 4;
|
||||||
double space = width_space / 5;
|
double space = width_space / 5;
|
||||||
double step_height = rect.height / max; // multiplier for bar height
|
double step_height = rect.height / max; // multiplier for bar height
|
||||||
double top = rect.bottom() + 1 - start * step_height;
|
int top = rect.bottom() - start * step_height;
|
||||||
double bottom = rect.bottom() - end * step_height;
|
int bottom = rect.bottom() - end * step_height;
|
||||||
RealRect result(
|
if (bottom < top) swap(top,bottom);
|
||||||
|
bottom += 1;
|
||||||
|
return RealRect(
|
||||||
rect.x + width_space * group + space / 2,
|
rect.x + width_space * group + space / 2,
|
||||||
top,
|
top,
|
||||||
width,
|
width,
|
||||||
(int)bottom - top
|
bottom - top
|
||||||
);
|
);
|
||||||
if (result.height < 0) {
|
|
||||||
result.height = -result.height;
|
|
||||||
result.y -= result.height;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
/// Which column of the bar graph with count bars is coordinate x in?
|
/// Which column of the bar graph with count bars is coordinate x in?
|
||||||
int find_bar_graph_column(double width, double x, int count) {
|
int find_bar_graph_column(double width, double x, int count) {
|
||||||
@@ -251,6 +257,28 @@ void BarGraph2D::draw(RotatedDC& dc, const vector<int>& current, DrawLayer layer
|
|||||||
// Bar sizes
|
// Bar sizes
|
||||||
if (layer == LAYER_SELECTION) {
|
if (layer == LAYER_SELECTION) {
|
||||||
// Highlight current column
|
// Highlight current column
|
||||||
|
Color bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||||
|
int cur1 = this->axis1 < current.size() ? current[this->axis1] : -1;
|
||||||
|
int cur2 = this->axis2 < current.size() ? current[this->axis2] : -1;
|
||||||
|
if (cur1 >= 0) {
|
||||||
|
// draw that bar
|
||||||
|
int start = 0;
|
||||||
|
int j = 0;
|
||||||
|
FOR_EACH_CONST(g2, axis2.groups) {
|
||||||
|
int end = start + values[j + axis2.groups.size() * cur1];
|
||||||
|
if (j == cur2 || cur2 < 0) {
|
||||||
|
RealRect bar = bar_graph_bar(rect, cur1, count, start, end, axis1.max);
|
||||||
|
dc.SetBrush(lerp(bg, g2.color, 0.25));
|
||||||
|
dc.DrawRectangle(bar.move(-5,0,10,0));
|
||||||
|
dc.SetBrush(lerp(bg, g2.color, 0.5));
|
||||||
|
dc.DrawRectangle(bar.move(-2,0,4,0));
|
||||||
|
}
|
||||||
|
start = end;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
} else if (cur2 >= 0) {
|
||||||
|
// entire row
|
||||||
|
}
|
||||||
// TODO
|
// TODO
|
||||||
} else if (layer == LAYER_VALUES) {
|
} else if (layer == LAYER_VALUES) {
|
||||||
// Draw bars
|
// Draw bars
|
||||||
@@ -276,6 +304,7 @@ bool BarGraph2D::findItem(const RealPoint& pos, const RealRect& rect, vector<int
|
|||||||
GraphAxis& axis1 = axis1_data(); // the major axis
|
GraphAxis& axis1 = axis1_data(); // the major axis
|
||||||
int count = (int)axis1.groups.size();
|
int count = (int)axis1.groups.size();
|
||||||
int col = find_bar_graph_column(rect.width, pos.x - rect.x, count);
|
int col = find_bar_graph_column(rect.width, pos.x - rect.x, count);
|
||||||
|
if (col < 0) return false;
|
||||||
// row
|
// row
|
||||||
int max_value = (int)axis1.max;
|
int max_value = (int)axis1.max;
|
||||||
int value = (rect.bottom() - pos.y) / rect.height * max_value;
|
int value = (rect.bottom() - pos.y) / rect.height * max_value;
|
||||||
@@ -503,18 +532,39 @@ void GraphContainer::add(const GraphP& graph) {
|
|||||||
GraphControl::GraphControl(Window* parent, int id)
|
GraphControl::GraphControl(Window* parent, int id)
|
||||||
: wxControl(parent, id)
|
: wxControl(parent, id)
|
||||||
{
|
{
|
||||||
//*
|
setLayout(GRAPH_TYPE_BAR);
|
||||||
intrusive_ptr<GraphContainer> combined(new GraphContainer());
|
}
|
||||||
combined->add(new_intrusive1<GraphValueAxis>(0));
|
|
||||||
combined->add(new_intrusive2<GraphLabelAxis>(0, HORIZONTAL));
|
void GraphControl::setLayout(GraphType type) {
|
||||||
//combined->add(new_intrusive1<BarGraph>(0));
|
if (type == layout) return;
|
||||||
combined->add(new_intrusive2<BarGraph2D>(0,1));
|
GraphDataP data = graph ? graph->getData() : GraphDataP();
|
||||||
graph = new_intrusive6<GraphWithMargins>(combined, 23,8,7,20, false);
|
switch (type) {
|
||||||
/*/
|
case GRAPH_TYPE_BAR: {
|
||||||
intrusive_ptr<GraphContainer> combined(new GraphContainer());
|
intrusive_ptr<GraphContainer> combined(new GraphContainer());
|
||||||
combined->add(new_intrusive1<PieGraph>(0));
|
combined->add(new_intrusive1<GraphValueAxis>(0));
|
||||||
graph = new_intrusive6<GraphWithMargins>(combined, 20,20,20,20, false);
|
combined->add(new_intrusive2<GraphLabelAxis>(0, HORIZONTAL));
|
||||||
//*/
|
combined->add(new_intrusive1<BarGraph>(0));
|
||||||
|
graph = new_intrusive5<GraphWithMargins>(combined, 23,8,7,20);
|
||||||
|
break;
|
||||||
|
} case GRAPH_TYPE_PIE: {
|
||||||
|
intrusive_ptr<GraphContainer> combined(new GraphContainer());
|
||||||
|
combined->add(new_intrusive1<PieGraph>(0));
|
||||||
|
graph = new_intrusive5<GraphWithMargins>(combined, 20,20,20,20);
|
||||||
|
break;
|
||||||
|
} case GRAPH_TYPE_STACK: {
|
||||||
|
intrusive_ptr<GraphContainer> combined(new GraphContainer());
|
||||||
|
combined->add(new_intrusive1<GraphValueAxis>(0));
|
||||||
|
combined->add(new_intrusive2<GraphLabelAxis>(0, HORIZONTAL));
|
||||||
|
combined->add(new_intrusive2<BarGraph2D>(0,1));
|
||||||
|
graph = new_intrusive5<GraphWithMargins>(combined, 23,8,7,20);
|
||||||
|
break;
|
||||||
|
} case GRAPH_TYPE_SCATTER: {
|
||||||
|
// TODO
|
||||||
|
} default:
|
||||||
|
graph = GraphP();
|
||||||
|
}
|
||||||
|
if (data && graph) graph->setData(data);
|
||||||
|
layout = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphControl::setData(const GraphDataPre& data) {
|
void GraphControl::setData(const GraphDataPre& data) {
|
||||||
@@ -560,8 +610,8 @@ bool GraphControl::hasSelection(size_t axis) const {
|
|||||||
return axis < current_item.size() && current_item[axis] >= 0;
|
return axis < current_item.size() && current_item[axis] >= 0;
|
||||||
}
|
}
|
||||||
String GraphControl::getSelection(size_t axis) const {
|
String GraphControl::getSelection(size_t axis) const {
|
||||||
if (!graph || axis >= current_item.size() || axis >= graph->getData().axes.size()) return wxEmptyString;
|
if (!graph || axis >= current_item.size() || axis >= graph->getData()->axes.size()) return wxEmptyString;
|
||||||
GraphAxis& a = *graph->getData().axes[axis];
|
GraphAxis& a = *graph->getData()->axes[axis];
|
||||||
int i = current_item[axis];
|
int i = current_item[axis];
|
||||||
if (i == -1 || (size_t)i >= a.groups.size()) return wxEmptyString;
|
if (i == -1 || (size_t)i >= a.groups.size()) return wxEmptyString;
|
||||||
return a.groups[current_item[axis]].name;
|
return a.groups[current_item[axis]].name;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <util/alignment.hpp>
|
#include <util/alignment.hpp>
|
||||||
#include <util/rotation.hpp>
|
#include <util/rotation.hpp>
|
||||||
|
#include <data/graph_type.hpp>
|
||||||
|
|
||||||
DECLARE_POINTER_TYPE(GraphAxis);
|
DECLARE_POINTER_TYPE(GraphAxis);
|
||||||
DECLARE_POINTER_TYPE(GraphElement);
|
DECLARE_POINTER_TYPE(GraphElement);
|
||||||
@@ -51,13 +52,14 @@ enum AutoColor
|
|||||||
/** The sum of groups.sum = sum of all elements in the data */
|
/** The sum of groups.sum = sum of all elements in the data */
|
||||||
class GraphAxis : public IntrusivePtrBase<GraphAxis> {
|
class GraphAxis : public IntrusivePtrBase<GraphAxis> {
|
||||||
public:
|
public:
|
||||||
GraphAxis(const String& name, AutoColor auto_color = AUTO_COLOR_EVEN, bool numeric = false, const map<String,Color>* colors = nullptr)
|
GraphAxis(const String& name, AutoColor auto_color = AUTO_COLOR_EVEN, bool numeric = false, const map<String,Color>* colors = nullptr, const vector<String>* order = nullptr)
|
||||||
: name(name)
|
: name(name)
|
||||||
, auto_color(auto_color)
|
, auto_color(auto_color)
|
||||||
, numeric(numeric)
|
, numeric(numeric)
|
||||||
, max(0)
|
, max(0)
|
||||||
, total(0)
|
, total(0)
|
||||||
, colors(colors)
|
, colors(colors)
|
||||||
|
, order(order)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
String name; ///< Name/label of this axis
|
String name; ///< Name/label of this axis
|
||||||
@@ -66,7 +68,8 @@ class GraphAxis : public IntrusivePtrBase<GraphAxis> {
|
|||||||
bool numeric; ///< Numeric axis?
|
bool numeric; ///< Numeric axis?
|
||||||
UInt max; ///< Maximum size of the groups
|
UInt max; ///< Maximum size of the groups
|
||||||
UInt total; ///< Sum of the size of all groups
|
UInt total; ///< Sum of the size of all groups
|
||||||
const map<String,Color>* colors; ///< Colors for each choice (optional
|
const map<String,Color>* colors; ///< Colors for each choice (optional)
|
||||||
|
const vector<String>* order; ///< Order of the items (optional)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A single data point of a graph
|
/// A single data point of a graph
|
||||||
@@ -121,7 +124,7 @@ class Graph : public IntrusivePtrVirtualBase {
|
|||||||
/// Change the data
|
/// Change the data
|
||||||
virtual void setData(const GraphDataP& d) { data = d; }
|
virtual void setData(const GraphDataP& d) { data = d; }
|
||||||
/// Get the data
|
/// Get the data
|
||||||
inline const GraphData& getData() const { return *data; }
|
inline const GraphDataP& getData() const { return data; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Data of the graph
|
/// Data of the graph
|
||||||
@@ -251,7 +254,7 @@ class GraphControl : public wxControl {
|
|||||||
GraphControl(Window* parent, int id);
|
GraphControl(Window* parent, int id);
|
||||||
|
|
||||||
/// Set the type of graph used, from a number of predefined choices
|
/// Set the type of graph used, from a number of predefined choices
|
||||||
void setLayout();
|
void setLayout(GraphType type);
|
||||||
/// Update the data in the graph
|
/// Update the data in the graph
|
||||||
void setData(const GraphDataPre& data);
|
void setData(const GraphDataPre& data);
|
||||||
/// Update the data in the graph
|
/// Update the data in the graph
|
||||||
@@ -265,6 +268,7 @@ class GraphControl : public wxControl {
|
|||||||
private:
|
private:
|
||||||
/// Graph object
|
/// Graph object
|
||||||
GraphP graph;
|
GraphP graph;
|
||||||
|
GraphType layout; /// < The current layout
|
||||||
/// The selected item per axis, or an empty vector if there is no selection
|
/// The selected item per axis, or an empty vector if there is no selection
|
||||||
/** If the value for an axis is -1, then all groups on that axis are selected */
|
/** If the value for an axis is -1, then all groups on that axis are selected */
|
||||||
vector<int> current_item;
|
vector<int> current_item;
|
||||||
|
|||||||
@@ -150,11 +150,12 @@ void StatsPanel::onCategorySelect() {
|
|||||||
cat.find_dimensions(set->game->statistics_dimensions);
|
cat.find_dimensions(set->game->statistics_dimensions);
|
||||||
// create axes
|
// create axes
|
||||||
FOR_EACH(dim, cat.dimensions) {
|
FOR_EACH(dim, cat.dimensions) {
|
||||||
d.axes.push_back(new_intrusive4<GraphAxis>(
|
d.axes.push_back(new_intrusive5<GraphAxis>(
|
||||||
dim->name,
|
dim->name,
|
||||||
dim->colors.empty() ? AUTO_COLOR_EVEN : AUTO_COLOR_NO,
|
dim->colors.empty() ? AUTO_COLOR_EVEN : AUTO_COLOR_NO,
|
||||||
dim->numeric,
|
dim->numeric,
|
||||||
&dim->colors
|
&dim->colors,
|
||||||
|
dim->groups.empty() ? nullptr : &dim->groups
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -176,7 +177,7 @@ void StatsPanel::onCategorySelect() {
|
|||||||
d.elements.push_back(e);
|
d.elements.push_back(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO graph->setLayout(cat.type)
|
graph->setLayout(cat.type);
|
||||||
graph->setData(d);
|
graph->setData(d);
|
||||||
filterCards();
|
filterCards();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -489,6 +489,7 @@ void SetWindow::onFileReload(wxCommandEvent&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetWindow::onFileRecent(wxCommandEvent& ev) {
|
void SetWindow::onFileRecent(wxCommandEvent& ev) {
|
||||||
|
wxBusyCursor busy;
|
||||||
setSet(import_set(settings.recent_sets.at(ev.GetId() - ID_FILE_RECENT)));
|
setSet(import_set(settings.recent_sets.at(ev.GetId() - ID_FILE_RECENT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -1798,6 +1798,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\data\font.hpp">
|
RelativePath=".\data\font.hpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\data\graph_type.hpp">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\data\installer.cpp">
|
RelativePath=".\data\installer.cpp">
|
||||||
</File>
|
</File>
|
||||||
@@ -3209,10 +3212,10 @@
|
|||||||
RelativePath="..\conversion-todo.txt">
|
RelativePath="..\conversion-todo.txt">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\data\en.mse-locale\locale">
|
RelativePath="..\data\nl.mse-locale\locale">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\data\nl.mse-locale\locale">
|
RelativePath="..\data\en.mse-locale\locale">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\main.cpp">
|
RelativePath=".\main.cpp">
|
||||||
|
|||||||
@@ -104,8 +104,8 @@
|
|||||||
/** Usage: FOR_EACH_IT_T(Type,it,collect) { body-of-loop }
|
/** Usage: FOR_EACH_IT_T(Type,it,collect) { body-of-loop }
|
||||||
*/
|
*/
|
||||||
#define FOR_EACH_IT_T(Type,Iterator,Collection) \
|
#define FOR_EACH_IT_T(Type,Iterator,Collection) \
|
||||||
for(Type Iterator = Collection.begin() ; \
|
for(Type Iterator = (Collection).begin() ; \
|
||||||
Iterator != Collection.end() ; \
|
Iterator != (Collection).end() ; \
|
||||||
++Iterator)
|
++Iterator)
|
||||||
|
|
||||||
/// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
|
/// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
|
||||||
@@ -127,8 +127,8 @@
|
|||||||
*/
|
*/
|
||||||
#define FOR_EACH_REVERSE_IT(Iterator,Collection) \
|
#define FOR_EACH_REVERSE_IT(Iterator,Collection) \
|
||||||
for(TYPEOF_RIT(Collection) \
|
for(TYPEOF_RIT(Collection) \
|
||||||
Iterator = Collection.rbegin() ; \
|
Iterator = (Collection).rbegin() ; \
|
||||||
Iterator != Collection.rend() ; \
|
Iterator != (Collection).rend() ; \
|
||||||
++Iterator)
|
++Iterator)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Looping macros
|
// ----------------------------------------------------------------------------- : Looping macros
|
||||||
@@ -141,8 +141,8 @@
|
|||||||
* To terminate this loop we need an extra bool, which we set to false after the first iteration.
|
* To terminate this loop we need an extra bool, which we set to false after the first iteration.
|
||||||
*/
|
*/
|
||||||
#define FOR_EACH_T(TypeIt,TypeElem,Elem,Collection, begin, end) \
|
#define FOR_EACH_T(TypeIt,TypeElem,Elem,Collection, begin, end) \
|
||||||
for(std::pair<TypeIt,bool> Elem##_IT(Collection.begin(), true) ; \
|
for(std::pair<TypeIt,bool> Elem##_IT((Collection).begin(), true) ; \
|
||||||
Elem##_IT.second && Elem##_IT.first != Collection.end() ; \
|
Elem##_IT.second && Elem##_IT.first != (Collection).end() ; \
|
||||||
++Elem##_IT.first, Elem##_IT.second = !Elem##_IT.second) \
|
++Elem##_IT.first, Elem##_IT.second = !Elem##_IT.second) \
|
||||||
for(TypeElem Elem = *Elem##_IT.first ; \
|
for(TypeElem Elem = *Elem##_IT.first ; \
|
||||||
Elem##_IT.second ; \
|
Elem##_IT.second ; \
|
||||||
@@ -183,9 +183,9 @@
|
|||||||
*/
|
*/
|
||||||
#define FOR_EACH_2_T(TypeIt1,TypeElem1,Elem1,Coll1,TypeIt2,TypeElem2,Elem2,Coll2) \
|
#define FOR_EACH_2_T(TypeIt1,TypeElem1,Elem1,Coll1,TypeIt2,TypeElem2,Elem2,Coll2) \
|
||||||
for(std::pair<std::pair<TypeIt1,TypeIt2>, bool> \
|
for(std::pair<std::pair<TypeIt1,TypeIt2>, bool> \
|
||||||
Elem1##_IT(make_pair(Coll1.begin(), Coll2.begin()), true) ; \
|
Elem1##_IT(make_pair((Coll1).begin(), (Coll2).begin()), true) ; \
|
||||||
Elem1##_IT.first.first != Coll1.end() && \
|
Elem1##_IT.first.first != (Coll1).end() && \
|
||||||
Elem1##_IT.first.second != Coll2.end() ; \
|
Elem1##_IT.first.second != (Coll2).end() ; \
|
||||||
++Elem1##_IT.first.first, ++Elem1##_IT.first.second, \
|
++Elem1##_IT.first.first, ++Elem1##_IT.first.second, \
|
||||||
Elem1##_IT.second = true) \
|
Elem1##_IT.second = true) \
|
||||||
for(TypeElem1 Elem1 = *Elem1##_IT.first.first ; \
|
for(TypeElem1 Elem1 = *Elem1##_IT.first.first ; \
|
||||||
|
|||||||
Reference in New Issue
Block a user