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:
twanvl
2007-05-13 15:22:26 +00:00
parent cc036b94f3
commit 8d5fc6949f
11 changed files with 154 additions and 63 deletions
+74 -24
View File
@@ -17,6 +17,7 @@ DECLARE_TYPEOF_COLLECTION(GraphGroup);
DECLARE_TYPEOF_COLLECTION(GraphP);
DECLARE_TYPEOF_COLLECTION(int);
DECLARE_TYPEOF_COLLECTION(vector<int>);
DECLARE_TYPEOF_COLLECTION(String);
DECLARE_TYPEOF(map<String COMMA UInt>);
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) {
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) {
// TODO: start at something other than 0?
// TODO: support fractions?
@@ -75,6 +76,14 @@ GraphData::GraphData(const GraphDataPre& d)
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 {
FOR_EACH(c, counts) {
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 space = width_space / 5;
double step_height = rect.height / max; // multiplier for bar height
double top = rect.bottom() + 1 - start * step_height;
double bottom = rect.bottom() - end * step_height;
RealRect result(
int top = rect.bottom() - start * step_height;
int bottom = rect.bottom() - end * step_height;
if (bottom < top) swap(top,bottom);
bottom += 1;
return RealRect(
rect.x + width_space * group + space / 2,
top,
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?
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
if (layer == LAYER_SELECTION) {
// 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
} else if (layer == LAYER_VALUES) {
// Draw bars
@@ -276,6 +304,7 @@ bool BarGraph2D::findItem(const RealPoint& pos, const RealRect& rect, vector<int
GraphAxis& axis1 = axis1_data(); // the major axis
int count = (int)axis1.groups.size();
int col = find_bar_graph_column(rect.width, pos.x - rect.x, count);
if (col < 0) return false;
// row
int max_value = (int)axis1.max;
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)
: wxControl(parent, id)
{
//*
intrusive_ptr<GraphContainer> combined(new GraphContainer());
combined->add(new_intrusive1<GraphValueAxis>(0));
combined->add(new_intrusive2<GraphLabelAxis>(0, HORIZONTAL));
//combined->add(new_intrusive1<BarGraph>(0));
combined->add(new_intrusive2<BarGraph2D>(0,1));
graph = new_intrusive6<GraphWithMargins>(combined, 23,8,7,20, false);
/*/
intrusive_ptr<GraphContainer> combined(new GraphContainer());
combined->add(new_intrusive1<PieGraph>(0));
graph = new_intrusive6<GraphWithMargins>(combined, 20,20,20,20, false);
//*/
setLayout(GRAPH_TYPE_BAR);
}
void GraphControl::setLayout(GraphType type) {
if (type == layout) return;
GraphDataP data = graph ? graph->getData() : GraphDataP();
switch (type) {
case GRAPH_TYPE_BAR: {
intrusive_ptr<GraphContainer> combined(new GraphContainer());
combined->add(new_intrusive1<GraphValueAxis>(0));
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) {
@@ -560,8 +610,8 @@ bool GraphControl::hasSelection(size_t axis) const {
return axis < current_item.size() && current_item[axis] >= 0;
}
String GraphControl::getSelection(size_t axis) const {
if (!graph || axis >= current_item.size() || axis >= graph->getData().axes.size()) return wxEmptyString;
GraphAxis& a = *graph->getData().axes[axis];
if (!graph || axis >= current_item.size() || axis >= graph->getData()->axes.size()) return wxEmptyString;
GraphAxis& a = *graph->getData()->axes[axis];
int i = current_item[axis];
if (i == -1 || (size_t)i >= a.groups.size()) return wxEmptyString;
return a.groups[current_item[axis]].name;
+8 -4
View File
@@ -12,6 +12,7 @@
#include <util/prec.hpp>
#include <util/alignment.hpp>
#include <util/rotation.hpp>
#include <data/graph_type.hpp>
DECLARE_POINTER_TYPE(GraphAxis);
DECLARE_POINTER_TYPE(GraphElement);
@@ -51,13 +52,14 @@ enum AutoColor
/** The sum of groups.sum = sum of all elements in the data */
class GraphAxis : public IntrusivePtrBase<GraphAxis> {
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)
, auto_color(auto_color)
, numeric(numeric)
, max(0)
, total(0)
, colors(colors)
, order(order)
{}
String name; ///< Name/label of this axis
@@ -66,7 +68,8 @@ class GraphAxis : public IntrusivePtrBase<GraphAxis> {
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
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
@@ -121,7 +124,7 @@ class Graph : public IntrusivePtrVirtualBase {
/// Change the data
virtual void setData(const GraphDataP& d) { data = d; }
/// Get the data
inline const GraphData& getData() const { return *data; }
inline const GraphDataP& getData() const { return data; }
protected:
/// Data of the graph
@@ -251,7 +254,7 @@ class GraphControl : public wxControl {
GraphControl(Window* parent, int id);
/// Set the type of graph used, from a number of predefined choices
void setLayout();
void setLayout(GraphType type);
/// Update the data in the graph
void setData(const GraphDataPre& data);
/// Update the data in the graph
@@ -265,6 +268,7 @@ class GraphControl : public wxControl {
private:
/// Graph object
GraphP graph;
GraphType layout; /// < The current layout
/// 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 */
vector<int> current_item;
+4 -3
View File
@@ -150,11 +150,12 @@ void StatsPanel::onCategorySelect() {
cat.find_dimensions(set->game->statistics_dimensions);
// create axes
FOR_EACH(dim, cat.dimensions) {
d.axes.push_back(new_intrusive4<GraphAxis>(
d.axes.push_back(new_intrusive5<GraphAxis>(
dim->name,
dim->colors.empty() ? AUTO_COLOR_EVEN : AUTO_COLOR_NO,
dim->numeric,
&dim->colors
&dim->colors,
dim->groups.empty() ? nullptr : &dim->groups
)
);
}
@@ -176,7 +177,7 @@ void StatsPanel::onCategorySelect() {
d.elements.push_back(e);
}
}
// TODO graph->setLayout(cat.type)
graph->setLayout(cat.type);
graph->setData(d);
filterCards();
}
+1
View File
@@ -489,6 +489,7 @@ void SetWindow::onFileReload(wxCommandEvent&) {
}
void SetWindow::onFileRecent(wxCommandEvent& ev) {
wxBusyCursor busy;
setSet(import_set(settings.recent_sets.at(ev.GetId() - ID_FILE_RECENT)));
}