From bc75acee92a234e0b9ee7525f578553088ffc575 Mon Sep 17 00:00:00 2001 From: Ted Turocy Date: Fri, 9 Feb 2024 11:12:56 +0000 Subject: [PATCH] Place all of src under clang-format checks in pre-commit, add clang-format check to CI. --- .github/workflows/lint.yml | 12 + .pre-commit-config.yaml | 16 +- src/gambit.h | 3 +- src/games/agg/agg.cc | 12 +- src/games/behavmixed.h | 98 +- src/games/behavmixed.imp | 357 +- src/games/behavpure.cc | 76 +- src/games/behavpure.h | 27 +- src/games/behavspt.cc | 218 +- src/games/behavspt.h | 43 +- src/games/file.cc | 228 +- src/games/game.cc | 228 +- src/games/game.h | 69 +- src/games/gameagg.cc | 146 +- src/games/gameagg.h | 69 +- src/games/gamebagg.cc | 194 +- src/games/gamebagg.h | 65 +- src/games/gameexpl.cc | 29 +- src/games/gameexpl.h | 8 +- src/games/gameobject.h | 115 +- src/games/gametable.cc | 161 +- src/games/gametable.h | 43 +- src/games/gametree.cc | 410 +- src/games/gametree.h | 59 +- src/games/nash.cc | 251 +- src/games/nash.h | 131 +- src/games/number.h | 11 +- src/games/stratmixed.h | 144 +- src/games/stratpure.cc | 48 +- src/games/stratpure.h | 39 +- src/games/stratspt.cc | 196 +- src/games/stratspt.h | 58 +- src/games/writer.cc | 132 +- src/games/writer.h | 8 +- src/labenski/include/wx/plotctrl/fourier.h | 37 +- src/labenski/include/wx/plotctrl/fparser.h | 138 +- src/labenski/include/wx/plotctrl/lm_lsqr.h | 214 +- src/labenski/include/wx/plotctrl/plotctrl.h | 2154 ++-- src/labenski/include/wx/plotctrl/plotcurv.h | 239 +- src/labenski/include/wx/plotctrl/plotdata.h | 704 +- src/labenski/include/wx/plotctrl/plotdefs.h | 14 +- src/labenski/include/wx/plotctrl/plotdraw.h | 192 +- src/labenski/include/wx/plotctrl/plotfunc.h | 129 +- src/labenski/include/wx/plotctrl/plotmark.h | 297 +- src/labenski/include/wx/plotctrl/plotprnt.h | 81 +- src/labenski/include/wx/sheet/pairarr.h | 373 +- src/labenski/include/wx/sheet/sheet.h | 3016 ++--- src/labenski/include/wx/sheet/sheetatr.h | 305 +- src/labenski/include/wx/sheet/sheetdef.h | 454 +- src/labenski/include/wx/sheet/sheetedg.h | 103 +- src/labenski/include/wx/sheet/sheetedt.h | 590 +- src/labenski/include/wx/sheet/sheetren.h | 469 +- src/labenski/include/wx/sheet/sheetsel.h | 890 +- src/labenski/include/wx/sheet/sheetspt.h | 418 +- src/labenski/include/wx/sheet/sheettbl.h | 644 +- src/labenski/include/wx/wxthings/block.h | 810 +- src/labenski/include/wx/wxthings/bmpcombo.h | 272 +- src/labenski/include/wx/wxthings/dropdown.h | 168 +- src/labenski/include/wx/wxthings/genergdi.h | 514 +- src/labenski/include/wx/wxthings/geometry.h | 1023 +- src/labenski/include/wx/wxthings/medsort.h | 667 +- src/labenski/include/wx/wxthings/optvalue.h | 323 +- src/labenski/include/wx/wxthings/range.h | 649 +- src/labenski/include/wx/wxthings/spinctld.h | 275 +- src/labenski/include/wx/wxthings/thingdef.h | 6 +- src/labenski/include/wx/wxthings/toggle.h | 290 +- src/labenski/src/block.cpp | 1560 +-- src/labenski/src/bmpcombo.cpp | 785 +- src/labenski/src/dropdown.cpp | 476 +- src/labenski/src/fourier.c | 471 +- src/labenski/src/fparser.cpp | 5530 ++++----- src/labenski/src/fparser.hh | 222 +- src/labenski/src/genergdi.cpp | 751 +- src/labenski/src/geometry.cpp | 135 +- src/labenski/src/lm_lsqr.cpp | 3276 +++--- src/labenski/src/optvalue.cpp | 763 +- src/labenski/src/plotctrl.cpp | 6156 +++++----- src/labenski/src/plotcurv.cpp | 269 +- src/labenski/src/plotdata.cpp | 4504 ++++---- src/labenski/src/plotdraw.cpp | 1761 +-- src/labenski/src/plotfunc.cpp | 180 +- src/labenski/src/plotmark.cpp | 145 +- src/labenski/src/plotprnt.cpp | 282 +- src/labenski/src/range.cpp | 950 +- src/labenski/src/sheet.cpp | 10675 +++++++++--------- src/labenski/src/sheetatr.cpp | 1099 +- src/labenski/src/sheetedg.cpp | 439 +- src/labenski/src/sheetedt.cpp | 1893 ++-- src/labenski/src/sheetren.cpp | 1387 ++- src/labenski/src/sheetsel.cpp | 1949 ++-- src/labenski/src/sheetspt.cpp | 1048 +- src/labenski/src/sheettbl.cpp | 1534 +-- src/labenski/src/spinctld.cpp | 901 +- src/labenski/src/toggle.cpp | 902 +- src/pygambit/nash.h | 14 +- src/pygambit/util.h | 27 +- src/solvers/enumpoly/quiksolv.imp | 1 - src/solvers/lrs/lrslib.c | 7839 +++++++------ src/solvers/lrs/lrsmp.c | 1399 ++- src/solvers/lrs/lrsnashlib.c | 835 +- 100 files changed, 41328 insertions(+), 38992 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7a911ecf2..80490efbe 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,6 +5,18 @@ on: pull_request: jobs: + clang-format: + name: clang-format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run clang-format style check for C/C++ + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: '17' + check-path: 'src' + include-regex: '^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|(imp))$' + clang-tidy: runs-on: ubuntu-latest if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 00f633b45..6c78b4416 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,17 +19,9 @@ repos: hooks: - id: cython-lint - id: double-quote-cython-strings -- repo: https://github.com/pocc/pre-commit-hooks - rev: v1.3.5 +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v17.0.6 hooks: - id: clang-format - files: src\/(gambit|core|gui|solvers|tools) - args: ["-i"] - # - id: clang-tidy - # args: ["--", "-I src", "-I", "src/labenski/include"] - # - id: oclint - # - id: uncrustify -# - id: cppcheck -# args: ["--suppressions-list=.cppcheck", "-Isrc", "-Isrc/labenski/include"] - # - id: cpplint - # - id: include-what-you-use + files: ^src\/.*\.(c|cc|cpp|h|imp)$ + types_or: [c++, c] diff --git a/src/gambit.h b/src/gambit.h index 194b21cdf..214aec972 100644 --- a/src/gambit.h +++ b/src/gambit.h @@ -53,8 +53,7 @@ inline double abs(double x) { return std::fabs(x); } inline double sqr(double x) { return x * x; } -template -bool contains(const std::map& map, const Key& key) +template bool contains(const std::map &map, const Key &key) // TODO: remove when we move to C++20 which already includes a "contains" method { return map.find(key) != map.end(); diff --git a/src/games/agg/agg.cc b/src/games/agg/agg.cc index c765cd443..459a98e87 100644 --- a/src/games/agg/agg.cc +++ b/src/games/agg/agg.cc @@ -38,12 +38,12 @@ AGG::AGG(int numPlayers, std::vector &_actions, int numANodes, int _numPNod vector &projTypes, vector> &projS, vector>> &proj, vector> &projF, vector>> &Po, vector &P, vector &_payoffs) - : numPlayers(numPlayers), totalActions(0), maxActions(0), - numActionNodes(numANodes), numPNodes(_numPNodes), - actionSets(_actionSets), neighbors(neighb), projectionTypes(projTypes), payoffs(_payoffs), - projection(proj), projectedStrat(projS), fullProjectedStrat(projS), projFunctions(projF), - Porder(Po), Pr(P), isPure(numANodes, true), node2Action(numANodes, vector(numPlayers)), - cache(numPlayers + 1), player2Class(numPlayers), kSymStrategyOffset(1, 0) + : numPlayers(numPlayers), totalActions(0), maxActions(0), numActionNodes(numANodes), + numPNodes(_numPNodes), actionSets(_actionSets), neighbors(neighb), projectionTypes(projTypes), + payoffs(_payoffs), projection(proj), projectedStrat(projS), fullProjectedStrat(projS), + projFunctions(projF), Porder(Po), Pr(P), isPure(numANodes, true), + node2Action(numANodes, vector(numPlayers)), cache(numPlayers + 1), + player2Class(numPlayers), kSymStrategyOffset(1, 0) { // actions diff --git a/src/games/behavmixed.h b/src/games/behavmixed.h index 2f66261d4..dcb2d1c4b 100644 --- a/src/games/behavmixed.h +++ b/src/games/behavmixed.h @@ -38,15 +38,15 @@ template class MixedBehaviorProfile { unsigned int m_gameversion; // structures for storing cached data: nodes - mutable std::map map_realizProbs, map_beliefs; - mutable std::map> map_nodeValues; + mutable std::map map_realizProbs, map_beliefs; + mutable std::map> map_nodeValues; // structures for storing cached data: information sets - mutable std::map map_infosetValues; + mutable std::map map_infosetValues; // structures for storing cached data: actions - mutable std::map map_actionValues; // aka conditional payoffs - mutable std::map map_regret; + mutable std::map map_actionValues; // aka conditional payoffs + mutable std::map map_regret; /// @name Auxiliary functions for computation of interesting values //@{ @@ -59,9 +59,9 @@ template class MixedBehaviorProfile { /// @name Converting mixed strategies to behavior //@{ - void BehaviorStrat(GamePlayer &, GameNode &, std::map &, std::map &); + void BehaviorStrat(GamePlayer &, GameNode &, std::map &, std::map &); void RealizationProbs(const MixedStrategyProfile &, GamePlayer &, const Array &, - GameTreeNodeRep *, std::map &, std::map &); + GameTreeNodeRep *, std::map &, std::map &); //@} /// Check underlying game has not changed; raise exception if it has @@ -83,49 +83,62 @@ template class MixedBehaviorProfile { MixedBehaviorProfile &operator=(const MixedBehaviorProfile &); MixedBehaviorProfile &operator=(const Vector &p) - { InvalidateCache(); m_probs = p; return *this;} + { + InvalidateCache(); + m_probs = p; + return *this; + } MixedBehaviorProfile &operator=(const T &x) - { InvalidateCache(); m_probs = x; return *this; } + { + InvalidateCache(); + m_probs = x; + return *this; + } //@} /// @name Operator overloading //@{ bool operator==(const MixedBehaviorProfile &) const; - bool operator!=(const MixedBehaviorProfile &x) const - { return !(*this == x); } + bool operator!=(const MixedBehaviorProfile &x) const { return !(*this == x); } - bool operator==(const DVector &x) const - { return m_probs == x; } - bool operator!=(const DVector &x) const - { return m_probs != x; } + bool operator==(const DVector &x) const { return m_probs == x; } + bool operator!=(const DVector &x) const { return m_probs != x; } const T &operator[](const GameAction &p_action) const - { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), - p_action->GetInfoset()->GetNumber(), - m_support.GetIndex(p_action)); } + { + return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), + p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); + } T &operator[](const GameAction &p_action) - { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), - p_action->GetInfoset()->GetNumber(), - m_support.GetIndex(p_action)); } + { + return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), + p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); + } const T &operator()(const GameAction &p_action) const - { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), - p_action->GetInfoset()->GetNumber(), - m_support.GetIndex(p_action)); } + { + return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), + p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); + } T &operator()(const GameAction &p_action) - { return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), - p_action->GetInfoset()->GetNumber(), - m_support.GetIndex(p_action)); } + { + return (*this)(p_action->GetInfoset()->GetPlayer()->GetNumber(), + p_action->GetInfoset()->GetNumber(), m_support.GetIndex(p_action)); + } - const T &operator()(int a, int b, int c) const - { return m_probs(a, b, c); } + const T &operator()(int a, int b, int c) const { return m_probs(a, b, c); } T &operator()(int a, int b, int c) - { InvalidateCache(); return m_probs(a, b, c); } - const T &operator[](int a) const - { return m_probs[a]; } + { + InvalidateCache(); + return m_probs(a, b, c); + } + const T &operator[](int a) const { return m_probs[a]; } T &operator[](int a) - { InvalidateCache(); return m_probs[a]; } + { + InvalidateCache(); + return m_probs[a]; + } operator const Vector &() const { return m_probs; } //@} @@ -138,14 +151,14 @@ template class MixedBehaviorProfile { /// We also clear /// map_nodeValues, map_actionValues /// as otherwise we would need to reset them to 0 while populating them - void InvalidateCache() const { + void InvalidateCache() const + { map_realizProbs.clear(); map_nodeValues.clear(); map_actionValues.clear(); } /// Reset certain cached values - /// Set the profile to the centroid void SetCentroid(); /// Set the behavior at any undefined information set to the centroid @@ -167,8 +180,7 @@ template class MixedBehaviorProfile { Game GetGame() const { return m_support.GetGame(); } const BehaviorSupportProfile &GetSupport() const { return m_support; } /// Returns whether the profile has been invalidated by a subsequent revision to the game - bool IsInvalidated() const - { return m_gameversion != m_support.GetGame()->GetVersion(); } + bool IsInvalidated() const { return m_gameversion != m_support.GetGame()->GetVersion(); } bool IsDefinedAt(GameInfoset p_infoset) const; //@} @@ -176,9 +188,7 @@ template class MixedBehaviorProfile { /// @name Computation of interesting quantities //@{ T GetPayoff(int p_player) const; - T GetPayoff(const GamePlayer &p_player) const { - return GetPayoff(p_player->GetNumber()); - } + T GetPayoff(const GamePlayer &p_player) const { return GetPayoff(p_player->GetNumber()); } T GetLiapValue() const; const T &GetRealizProb(const GameNode &node) const; @@ -216,12 +226,10 @@ template class MixedBehaviorProfile { /// GetRegret(const GameAction &) const T GetMaxRegret() const; - T DiffActionValue(const GameAction &action, - const GameAction &oppAction) const; - T DiffRealizProb(const GameNode &node, - const GameAction &oppAction) const; + T DiffActionValue(const GameAction &action, const GameAction &oppAction) const; + T DiffRealizProb(const GameNode &node, const GameAction &oppAction) const; T DiffNodeValue(const GameNode &node, const GamePlayer &player, - const GameAction &oppAction) const; + const GameAction &oppAction) const; MixedStrategyProfile ToMixedProfile() const; diff --git a/src/games/behavmixed.imp b/src/games/behavmixed.imp index c49208c3a..cfc959a17 100644 --- a/src/games/behavmixed.imp +++ b/src/games/behavmixed.imp @@ -34,8 +34,7 @@ namespace Gambit { template MixedBehaviorProfile::MixedBehaviorProfile(const Game &p_game) - : m_probs(p_game->NumActions()), - m_support(BehaviorSupportProfile(p_game)), + : m_probs(p_game->NumActions()), m_support(BehaviorSupportProfile(p_game)), m_gameversion(p_game->GetVersion()) { SetCentroid(); @@ -43,8 +42,7 @@ MixedBehaviorProfile::MixedBehaviorProfile(const Game &p_game) template MixedBehaviorProfile::MixedBehaviorProfile(const BehaviorSupportProfile &p_support) - : m_probs(p_support.NumActions()), - m_support(p_support), + : m_probs(p_support.NumActions()), m_support(p_support), m_gameversion(p_support.GetGame()->GetVersion()) { SetCentroid(); @@ -52,13 +50,13 @@ MixedBehaviorProfile::MixedBehaviorProfile(const BehaviorSupportProfile &p_su template void MixedBehaviorProfile::BehaviorStrat(GamePlayer &player, GameNode &p_node, - std::map &map_nvals, - std::map &map_bvals) + std::map &map_nvals, + std::map &map_bvals) { - for (auto child: p_node->GetChildren()) { + for (auto child : p_node->GetChildren()) { if (p_node->GetPlayer() == player) { - if (map_nvals[p_node] > T(0) && map_nvals[child] > T(0)) { - (*this)[child->GetPriorAction()]= map_nvals[child] / map_nvals[p_node]; + if (map_nvals[p_node] > T(0) && map_nvals[child] > T(0)) { + (*this)[child->GetPriorAction()] = map_nvals[child] / map_nvals[p_node]; } } BehaviorStrat(player, child, map_nvals, map_bvals); @@ -67,31 +65,32 @@ void MixedBehaviorProfile::BehaviorStrat(GamePlayer &player, GameNode &p_node template void MixedBehaviorProfile::RealizationProbs(const MixedStrategyProfile &mp, - GamePlayer &player, - const Array &actions, - GameTreeNodeRep *node, - std::map &map_nvals, - std::map &map_bvals) + GamePlayer &player, const Array &actions, + GameTreeNodeRep *node, + std::map &map_nvals, + std::map &map_bvals) { T prob; - for (int i = 1; i <= node->children.Length(); i++) { - if (node->GetPlayer() && !node->GetPlayer()->IsChance()) { - if (node->GetPlayer() == player) { - if (actions[node->GetInfoset()->GetNumber()] == i) - prob = T(1); - else - prob = T(0); - } + for (int i = 1; i <= node->children.Length(); i++) { + if (node->GetPlayer() && !node->GetPlayer()->IsChance()) { + if (node->GetPlayer() == player) { + if (actions[node->GetInfoset()->GetNumber()] == i) { + prob = T(1); + } + else { + prob = T(0); + } + } else if (GetSupport().Contains(node->GetInfoset()->GetAction(i))) { - int num_actions = GetSupport().NumActions(node->GetInfoset()); - prob = T(1) / T(num_actions); + int num_actions = GetSupport().NumActions(node->GetInfoset()); + prob = T(1) / T(num_actions); } else { - prob = T(0); + prob = T(0); } } - else { // n.GetPlayer() == 0 + else { // n.GetPlayer() == 0 prob = T(node->infoset->GetActionProb(i)); } @@ -106,19 +105,19 @@ void MixedBehaviorProfile::RealizationProbs(const MixedStrategyProfile &mp template MixedBehaviorProfile::MixedBehaviorProfile(const MixedStrategyProfile &p_profile) - : m_probs(p_profile.GetGame()->NumActions()), - m_support(p_profile.GetGame()), + : m_probs(p_profile.GetGame()->NumActions()), m_support(p_profile.GetGame()), m_gameversion(p_profile.GetGame()->GetVersion()) { static_cast &>(m_probs) = T(0); - GameTreeNodeRep *root = dynamic_cast(m_support.GetGame()->GetRoot().operator->()); + GameTreeNodeRep *root = + dynamic_cast(m_support.GetGame()->GetRoot().operator->()); const StrategySupportProfile &support = p_profile.GetSupport(); GameRep *game = m_support.GetGame(); for (auto player : game->GetPlayers()) { - std::map map_nvals, map_bvals; + std::map map_nvals, map_bvals; for (auto strategy : support.GetStrategies(player)) { if (p_profile[strategy] > T(0)) { const Array &actions = strategy->m_behav; @@ -126,14 +125,15 @@ MixedBehaviorProfile::MixedBehaviorProfile(const MixedStrategyProfile &p_p RealizationProbs(p_profile, player, actions, root, map_nvals, map_bvals); } } - map_nvals[root] = T(1); // set the root nval + map_nvals[root] = T(1); // set the root nval auto root = m_support.GetGame()->GetRoot(); BehaviorStrat(player, root, map_nvals, map_bvals); } } template -MixedBehaviorProfile &MixedBehaviorProfile::operator=(const MixedBehaviorProfile &p_profile) +MixedBehaviorProfile & +MixedBehaviorProfile::operator=(const MixedBehaviorProfile &p_profile) { if (this != &p_profile && m_support == p_profile.m_support) { InvalidateCache(); @@ -151,8 +151,7 @@ MixedBehaviorProfile &MixedBehaviorProfile::operator=(const MixedBehaviorP template bool MixedBehaviorProfile::operator==(const MixedBehaviorProfile &p_profile) const { - return (m_support == p_profile.m_support && - (DVector &) *this == (DVector &) p_profile); + return (m_support == p_profile.m_support && (DVector &)*this == (DVector &)p_profile); } //======================================================================== @@ -162,57 +161,59 @@ bool MixedBehaviorProfile::operator==(const MixedBehaviorProfile &p_profil template void MixedBehaviorProfile::SetCentroid() { CheckVersion(); - for (auto infoset: m_support.GetGame()->GetInfosets()) { - if (infoset->NumActions() > 0) { - T center = (T(1) / T(infoset->NumActions())); - for (auto act: infoset->GetActions()) { - (*this)(act) = center; - } + for (auto infoset : m_support.GetGame()->GetInfosets()) { + if (infoset->NumActions() > 0) { + T center = (T(1) / T(infoset->NumActions())); + for (auto act : infoset->GetActions()) { + (*this)(act) = center; } } + } } -template -void MixedBehaviorProfile::UndefinedToCentroid() +template void MixedBehaviorProfile::UndefinedToCentroid() { CheckVersion(); Game efg = m_support.GetGame(); - for (auto infoset: efg->GetInfosets()) { - if (GetInfosetProb(infoset) > T(0)) { - continue; - } - auto actions = infoset->GetActions(); - T total = std::accumulate (actions.begin(), actions.end(), T(0), - [this] (T total, GameAction act) {return total + GetActionProb(act);}); - if (total == T(0)) { - for (auto act: infoset->GetActions()) { - (*this)(act) = T(1) / T(infoset->NumActions()); - } + for (auto infoset : efg->GetInfosets()) { + if (GetInfosetProb(infoset) > T(0)) { + continue; + } + auto actions = infoset->GetActions(); + T total = + std::accumulate(actions.begin(), actions.end(), T(0), + [this](T total, GameAction act) { return total + GetActionProb(act); }); + if (total == T(0)) { + for (auto act : infoset->GetActions()) { + (*this)(act) = T(1) / T(infoset->NumActions()); } } + } } -template -MixedBehaviorProfile MixedBehaviorProfile::Normalize() const +template MixedBehaviorProfile MixedBehaviorProfile::Normalize() const { CheckVersion(); auto norm = MixedBehaviorProfile(*this); - for (auto infoset: m_support.GetGame()->GetInfosets()) { - if (GetInfosetProb(infoset) == T(0)) { - continue; - } - auto actions = infoset->GetActions(); - T total = std::accumulate (actions.begin(), actions.end(), T(0), - [this] (T total, GameAction act) {return total + GetActionProb(act);}); - if (total == T(0)) continue; - for (auto act: infoset->GetActions()) { - norm(act) /= total; - } + for (auto infoset : m_support.GetGame()->GetInfosets()) { + if (GetInfosetProb(infoset) == T(0)) { + continue; + } + auto actions = infoset->GetActions(); + T total = + std::accumulate(actions.begin(), actions.end(), T(0), + [this](T total, GameAction act) { return total + GetActionProb(act); }); + if (total == T(0)) { + continue; + } + for (auto act : infoset->GetActions()) { + norm(act) /= total; + } } return norm; } -template<> void MixedBehaviorProfile::Randomize() +template <> void MixedBehaviorProfile::Randomize() { CheckVersion(); Game game = m_support.GetGame(); @@ -220,21 +221,20 @@ template<> void MixedBehaviorProfile::Randomize() // To generate a uniform distribution on the simplex correctly, // take i.i.d. samples from an exponential distribution, and // renormalize at the end (this is a special case of the Dirichlet distribution). - for (auto infoset: game->GetInfosets()) { - for (auto act: infoset->GetActions()) { - (*this)(act) = -std::log(((double) std::rand()) / - ((double) RAND_MAX)); - } + for (auto infoset : game->GetInfosets()) { + for (auto act : infoset->GetActions()) { + (*this)(act) = -std::log(((double)std::rand()) / ((double)RAND_MAX)); + } } MixedBehaviorProfile norm(Normalize()); - for (auto infoset: game->GetInfosets()) { - for (auto act: infoset->GetActions()) { - (*this)(act) = norm(act); - } + for (auto infoset : game->GetInfosets()) { + for (auto act : infoset->GetActions()) { + (*this)(act) = norm(act); + } } } -template<> void MixedBehaviorProfile::Randomize() +template <> void MixedBehaviorProfile::Randomize() { // This operation is not well-defined when using Rational numbers; // use the version specifying the denominator grid instead. @@ -253,31 +253,26 @@ template void MixedBehaviorProfile::Randomize(int p_denom) GameInfoset infoset = player->GetInfoset(iset); std::vector cutoffs; for (int act = 1; act < infoset->NumActions(); act++) { - // When we support C++11, we will be able to implement uniformity better - cutoffs.push_back(std::rand() % (p_denom+1)); + // When we support C++11, we will be able to implement uniformity better + cutoffs.push_back(std::rand() % (p_denom + 1)); } std::sort(cutoffs.begin(), cutoffs.end()); cutoffs.push_back(p_denom); T sum = T(0); for (int act = 1; act < infoset->NumActions(); act++) { - (*this)(pl, iset, act) = T(cutoffs[act] - cutoffs[act-1]) / T(p_denom); - sum += (*this)(pl, iset, act); + (*this)(pl, iset, act) = T(cutoffs[act] - cutoffs[act - 1]) / T(p_denom); + sum += (*this)(pl, iset, act); } (*this)(pl, iset, infoset->NumActions()) = T(1) - sum; } } } - - - - //======================================================================== // MixedBehaviorProfile: Interesting quantities //======================================================================== -template -T MixedBehaviorProfile::GetLiapValue() const +template T MixedBehaviorProfile::GetLiapValue() const { CheckVersion(); ComputeSolutionData(); @@ -286,78 +281,71 @@ T MixedBehaviorProfile::GetLiapValue() const for (auto player : m_support.GetGame()->GetPlayers()) { for (auto infoset : player->GetInfosets()) { for (auto action : infoset->GetActions()) { - value += sqr( - std::max(GetPayoff(action) - GetPayoff(infoset), T(0))); + value += sqr(std::max(GetPayoff(action) - GetPayoff(infoset), T(0))); } } } return value; } -template -const T &MixedBehaviorProfile::GetRealizProb(const GameNode &node) const +template const T &MixedBehaviorProfile::GetRealizProb(const GameNode &node) const { CheckVersion(); ComputeSolutionData(); return map_realizProbs[node]; } -template -T MixedBehaviorProfile::GetInfosetProb(const GameInfoset &iset) const +template T MixedBehaviorProfile::GetInfosetProb(const GameInfoset &iset) const { CheckVersion(); ComputeSolutionData(); T prob = T(0); - for (auto iset: iset->GetMembers()) { + for (auto iset : iset->GetMembers()) { prob += map_realizProbs[iset]; } return prob; } -template -const T &MixedBehaviorProfile::GetBeliefProb(const GameNode &node) const +template const T &MixedBehaviorProfile::GetBeliefProb(const GameNode &node) const { CheckVersion(); ComputeSolutionData(); return map_beliefs[node]; } -template -Vector MixedBehaviorProfile::GetPayoff(const GameNode &node) const +template Vector MixedBehaviorProfile::GetPayoff(const GameNode &node) const { CheckVersion(); ComputeSolutionData(); Vector ret(node->GetGame()->NumPlayers()); auto players = node->GetGame()->GetPlayers(); - std::transform (players.begin(), players.end(), ret.begin(), - [this, node] (GamePlayer player) {return map_nodeValues[node][player];}); + std::transform(players.begin(), players.end(), ret.begin(), + [this, node](GamePlayer player) { return map_nodeValues[node][player]; }); return ret; } - template -const T &MixedBehaviorProfile::GetPayoff(const GamePlayer &p_player, const GameNode &p_node) const +const T &MixedBehaviorProfile::GetPayoff(const GamePlayer &p_player, + const GameNode &p_node) const { CheckVersion(); ComputeSolutionData(); return map_nodeValues[p_node][p_player]; } - -template -const T &MixedBehaviorProfile::GetPayoff(const GameInfoset &iset) const +template const T &MixedBehaviorProfile::GetPayoff(const GameInfoset &iset) const { CheckVersion(); ComputeSolutionData(); return map_infosetValues[iset]; } -template -T MixedBehaviorProfile::GetActionProb(const GameAction &action) const +template T MixedBehaviorProfile::GetActionProb(const GameAction &action) const { CheckVersion(); if (action->GetInfoset()->GetPlayer()->IsChance()) { - GameTreeInfosetRep *infoset = dynamic_cast(action->GetInfoset().operator->()); + GameTreeInfosetRep *infoset = + dynamic_cast(action->GetInfoset().operator->()); return static_cast(infoset->GetActionProb(action->GetNumber())); } else if (!m_support.Contains(action)) { @@ -365,34 +353,30 @@ T MixedBehaviorProfile::GetActionProb(const GameAction &action) const } else { return (*this)(action->GetInfoset()->GetPlayer()->GetNumber(), - action->GetInfoset()->GetNumber(), - m_support.GetIndex(action)); + action->GetInfoset()->GetNumber(), m_support.GetIndex(action)); } } -template -const T &MixedBehaviorProfile::GetPayoff(const GameAction &act) const +template const T &MixedBehaviorProfile::GetPayoff(const GameAction &act) const { CheckVersion(); ComputeSolutionData(); return map_actionValues[act]; } -template -const T &MixedBehaviorProfile::GetRegret(const GameAction &act) const +template const T &MixedBehaviorProfile::GetRegret(const GameAction &act) const { CheckVersion(); ComputeSolutionData(); return map_regret[act]; } -template -T MixedBehaviorProfile::GetRegret(const GameInfoset &p_infoset) const +template T MixedBehaviorProfile::GetRegret(const GameInfoset &p_infoset) const { auto actions = p_infoset->GetActions(); T br_payoff = std::accumulate( - std::next(actions.begin()), actions.end(), GetPayoff(*actions.begin()), - [this](const T &x, const GameAction &action) { return std::max(x, GetPayoff(action)); }); + std::next(actions.begin()), actions.end(), GetPayoff(*actions.begin()), + [this](const T &x, const GameAction &action) { return std::max(x, GetPayoff(action)); }); return br_payoff - GetPayoff(p_infoset); } @@ -400,14 +384,13 @@ template T MixedBehaviorProfile::GetMaxRegret() const { auto infosets = m_support.GetGame()->GetInfosets(); return std::accumulate( - infosets.begin(), infosets.end(), T(0), - [this](const T &x, const GameInfoset &infoset) { return std::max(x, GetRegret(infoset)); }); + infosets.begin(), infosets.end(), T(0), + [this](const T &x, const GameInfoset &infoset) { return std::max(x, GetRegret(infoset)); }); } - template -void MixedBehaviorProfile::GetPayoff(const GameNode &node, - const T &prob, const GamePlayer &player, T &value) const +void MixedBehaviorProfile::GetPayoff(const GameNode &node, const T &prob, + const GamePlayer &player, T &value) const { if (node->GetOutcome()) { value += prob * static_cast(node->GetOutcome()->GetPayoff(player)); @@ -416,12 +399,13 @@ void MixedBehaviorProfile::GetPayoff(const GameNode &node, if (!node->IsTerminal()) { if (node->GetPlayer()->IsChance()) { // chance player - for (auto child: node->GetChildren()) { - GetPayoff(child, - prob * static_cast(GetActionProb(child->GetPriorAction())), player, value); + for (auto child : node->GetChildren()) { + GetPayoff(child, prob * static_cast(GetActionProb(child->GetPriorAction())), player, + value); } - } else { - for (auto child: node->GetChildren()) { + } + else { + for (auto child : node->GetChildren()) { GetPayoff(child, prob * GetActionProb(child->GetPriorAction()), player, value); } } @@ -438,7 +422,6 @@ template T MixedBehaviorProfile::GetPayoff(int pl) const return value; } - // // The following routines compute the derivatives of quantities as // the probability of the action 'p_oppAction' is changed. @@ -450,7 +433,7 @@ template T MixedBehaviorProfile::GetPayoff(int pl) const template T MixedBehaviorProfile::DiffActionValue(const GameAction &p_action, - const GameAction &p_oppAction) const + const GameAction &p_oppAction) const { CheckVersion(); ComputeSolutionData(); @@ -458,13 +441,13 @@ T MixedBehaviorProfile::DiffActionValue(const GameAction &p_action, GameInfoset infoset = p_action->GetInfoset(); GamePlayer player = p_action->GetInfoset()->GetPlayer(); - for (auto member: infoset->GetMembers()) { + for (auto member : infoset->GetMembers()) { GameNode child = member->GetChild(p_action); deriv += DiffRealizProb(member, p_oppAction) * (map_nodeValues[child][player] - map_actionValues[p_action]); deriv += map_realizProbs[member] * - DiffNodeValue(member->GetChild(p_action->GetNumber()), player, p_oppAction); + DiffNodeValue(member->GetChild(p_action->GetNumber()), player, p_oppAction); } return deriv / GetInfosetProb(p_action->GetInfoset()); @@ -472,7 +455,7 @@ T MixedBehaviorProfile::DiffActionValue(const GameAction &p_action, template T MixedBehaviorProfile::DiffRealizProb(const GameNode &p_node, - const GameAction &p_oppAction) const + const GameAction &p_oppAction) const { CheckVersion(); ComputeSolutionData(); @@ -494,9 +477,8 @@ T MixedBehaviorProfile::DiffRealizProb(const GameNode &p_node, } template -T MixedBehaviorProfile::DiffNodeValue(const GameNode &p_node, - const GamePlayer &p_player, - const GameAction &p_oppAction) const +T MixedBehaviorProfile::DiffNodeValue(const GameNode &p_node, const GamePlayer &p_player, + const GameAction &p_oppAction) const { CheckVersion(); ComputeSolutionData(); @@ -513,8 +495,8 @@ T MixedBehaviorProfile::DiffNodeValue(const GameNode &p_node, else { T deriv = T(0); for (auto action : infoset->GetActions()) { - deriv += (DiffNodeValue(p_node->GetChild(action), p_player, p_oppAction) * - GetActionProb(action)); + deriv += (DiffNodeValue(p_node->GetChild(action), p_player, p_oppAction) * + GetActionProb(action)); } return deriv; } @@ -530,88 +512,90 @@ T MixedBehaviorProfile::DiffNodeValue(const GameNode &p_node, // MixedBehaviorProfile: Cached profile information //======================================================================== - // compute realization probabilities for nodes and isets. template void MixedBehaviorProfile::ComputePass1_realizProbs(const GameNode &node) const { - map_realizProbs[node] = (node->GetParent()) ? - map_realizProbs[node->GetParent()] * GetActionProb(node->GetPriorAction()) : T(1); + map_realizProbs[node] = (node->GetParent()) ? map_realizProbs[node->GetParent()] * + GetActionProb(node->GetPriorAction()) + : T(1); - for (auto childNode: node->GetChildren()) { - ComputePass1_realizProbs(childNode); + for (auto childNode : node->GetChildren()) { + ComputePass1_realizProbs(childNode); } } template -void MixedBehaviorProfile::ComputePass2_beliefs_nodeValues_actionValues(const GameNode &node) const +void MixedBehaviorProfile::ComputePass2_beliefs_nodeValues_actionValues( + const GameNode &node) const { if (node->GetOutcome()) { GameOutcome outcome = node->GetOutcome(); - for (auto player: m_support.GetGame()->GetPlayers()) { + for (auto player : m_support.GetGame()->GetPlayers()) { map_nodeValues[node][player] += static_cast(outcome->GetPayoff(player)); } } - if (node->IsTerminal()) - return; + if (node->IsTerminal()) { + return; + } GameInfoset iset = node->GetInfoset(); auto nodes = iset->GetMembers(); - T infosetProb = std::accumulate (nodes.begin(), nodes.end(), T(0), - [this] (T total, GameNode node) {return total + map_realizProbs[node];}); + T infosetProb = + std::accumulate(nodes.begin(), nodes.end(), T(0), + [this](T total, GameNode node) { return total + map_realizProbs[node]; }); if (infosetProb != T(0)) { - map_beliefs[node] = map_realizProbs[node] / infosetProb; + map_beliefs[node] = map_realizProbs[node] / infosetProb; } // push down payoffs from outcomes attached to non-terminal nodes - for (auto child: node->GetChildren()) { - map_nodeValues[child] = map_nodeValues[node]; + for (auto child : node->GetChildren()) { + map_nodeValues[child] = map_nodeValues[node]; } - for (auto player: m_support.GetGame()->GetPlayers()) { - map_nodeValues[node][player] = T(0); + for (auto player : m_support.GetGame()->GetPlayers()) { + map_nodeValues[node][player] = T(0); } - for (auto child: node->GetChildren()) { - ComputePass2_beliefs_nodeValues_actionValues(child); + for (auto child : node->GetChildren()) { + ComputePass2_beliefs_nodeValues_actionValues(child); - GameAction act = child->GetPriorAction(); + GameAction act = child->GetPriorAction(); - for (auto player: m_support.GetGame()->GetPlayers()) { - map_nodeValues[node][player] += GetActionProb(act) * map_nodeValues[child][player]; - } + for (auto player : m_support.GetGame()->GetPlayers()) { + map_nodeValues[node][player] += GetActionProb(act) * map_nodeValues[child][player]; + } - if (!iset->IsChanceInfoset()) { - map_actionValues[act] += (infosetProb != T(0)) ? - map_beliefs[node] * map_nodeValues[child][iset->GetPlayer()]: T(0); - } + if (!iset->IsChanceInfoset()) { + map_actionValues[act] += (infosetProb != T(0)) + ? map_beliefs[node] * map_nodeValues[child][iset->GetPlayer()] + : T(0); + } } } -template -void MixedBehaviorProfile::ComputePass3_infosetValues_regret() const +template void MixedBehaviorProfile::ComputePass3_infosetValues_regret() const { // Populate - for (auto infoset: m_support.GetGame()->GetInfosets()) { - map_infosetValues[infoset] = T(0); - for (auto action : infoset->GetActions()) { - map_infosetValues[infoset] += GetActionProb(action) * map_actionValues[action]; - } - auto actions = infoset->GetActions(); - T brpayoff = map_actionValues[actions.front()]; - for (auto action : infoset->GetActions()) { - brpayoff = std::max(brpayoff, map_actionValues[action]); - } - for (auto action : infoset->GetActions()) { - map_regret[action] = brpayoff - map_actionValues[action]; - } + for (auto infoset : m_support.GetGame()->GetInfosets()) { + map_infosetValues[infoset] = T(0); + for (auto action : infoset->GetActions()) { + map_infosetValues[infoset] += GetActionProb(action) * map_actionValues[action]; } + auto actions = infoset->GetActions(); + T brpayoff = map_actionValues[actions.front()]; + for (auto action : infoset->GetActions()) { + brpayoff = std::max(brpayoff, map_actionValues[action]); + } + for (auto action : infoset->GetActions()) { + map_regret[action] = brpayoff - map_actionValues[action]; + } + } } -template -void MixedBehaviorProfile::ComputeSolutionData() const +template void MixedBehaviorProfile::ComputeSolutionData() const { auto rootNode = m_support.GetGame()->GetRoot(); if (contains(map_realizProbs, rootNode)) { @@ -623,11 +607,10 @@ void MixedBehaviorProfile::ComputeSolutionData() const ComputePass3_infosetValues_regret(); } -template -bool MixedBehaviorProfile::IsDefinedAt(GameInfoset p_infoset) const +template bool MixedBehaviorProfile::IsDefinedAt(GameInfoset p_infoset) const { CheckVersion(); - for (auto act: p_infoset->GetActions()) { + for (auto act : p_infoset->GetActions()) { if (GetActionProb(act) > T(0)) { return true; } @@ -635,12 +618,10 @@ bool MixedBehaviorProfile::IsDefinedAt(GameInfoset p_infoset) const return false; } -template -MixedStrategyProfile MixedBehaviorProfile::ToMixedProfile() const +template MixedStrategyProfile MixedBehaviorProfile::ToMixedProfile() const { CheckVersion(); return MixedStrategyProfile(*this); } - -} // end namespace Gambit +} // end namespace Gambit diff --git a/src/games/behavpure.cc b/src/games/behavpure.cc index c4841846e..4362657a7 100644 --- a/src/games/behavpure.cc +++ b/src/games/behavpure.cc @@ -32,10 +32,9 @@ namespace Gambit { // PureBehaviorProfile: Lifecycle //------------------------------------------------------------------------ -PureBehaviorProfile::PureBehaviorProfile(Game p_efg) - : m_efg(p_efg), m_profile(m_efg->NumPlayers()) +PureBehaviorProfile::PureBehaviorProfile(Game p_efg) : m_efg(p_efg), m_profile(m_efg->NumPlayers()) { - for (int pl = 1; pl <= m_efg->NumPlayers(); pl++) { + for (int pl = 1; pl <= m_efg->NumPlayers(); pl++) { GamePlayerRep *player = m_efg->GetPlayer(pl); m_profile[pl] = Array(player->NumInfosets()); for (int iset = 1; iset <= player->NumInfosets(); iset++) { @@ -55,13 +54,11 @@ GameAction PureBehaviorProfile::GetAction(const GameInfoset &infoset) const void PureBehaviorProfile::SetAction(const GameAction &action) { - m_profile[action->GetInfoset()->GetPlayer()->GetNumber()] - [action->GetInfoset()->GetNumber()] = action; + m_profile[action->GetInfoset()->GetPlayer()->GetNumber()][action->GetInfoset()->GetNumber()] = + action; } -template -T PureBehaviorProfile::GetPayoff(const GameNode &p_node, - int pl) const +template T PureBehaviorProfile::GetPayoff(const GameNode &p_node, int pl) const { T payoff(0); @@ -79,8 +76,7 @@ T PureBehaviorProfile::GetPayoff(const GameNode &p_node, else { int player = p_node->GetPlayer()->GetNumber(); int iset = p_node->GetInfoset()->GetNumber(); - payoff += GetPayoff(p_node->GetChild(m_profile[player][iset]->GetNumber()), - pl); + payoff += GetPayoff(p_node->GetChild(m_profile[player][iset]->GetNumber()), pl); } } @@ -91,8 +87,7 @@ T PureBehaviorProfile::GetPayoff(const GameNode &p_node, template double PureBehaviorProfile::GetPayoff(const GameNode &, int pl) const; template Rational PureBehaviorProfile::GetPayoff(const GameNode &, int pl) const; -template -T PureBehaviorProfile::GetPayoff(const GameAction &p_action) const +template T PureBehaviorProfile::GetPayoff(const GameAction &p_action) const { PureBehaviorProfile copy(*this); copy.SetAction(p_action); @@ -109,7 +104,7 @@ bool PureBehaviorProfile::IsAgentNash() const auto current = GetPayoff(player); for (auto infoset : player->GetInfosets()) { for (auto action : infoset->GetActions()) { - if (GetPayoff(action) > current) { + if (GetPayoff(action) > current) { return false; } } @@ -118,8 +113,7 @@ bool PureBehaviorProfile::IsAgentNash() const return true; } -MixedBehaviorProfile -PureBehaviorProfile::ToMixedBehaviorProfile() const +MixedBehaviorProfile PureBehaviorProfile::ToMixedBehaviorProfile() const { MixedBehaviorProfile temp(m_efg); temp = Rational(0); @@ -135,13 +129,9 @@ PureBehaviorProfile::ToMixedBehaviorProfile() const // class BehaviorProfileIterator //======================================================================== - BehaviorProfileIterator::BehaviorProfileIterator(const Game &p_game) - : m_atEnd(false), m_support(p_game), - m_currentBehav(p_game->NumInfosets()), - m_profile(p_game), - m_frozenPlayer(0), m_frozenInfoset(0), - m_numActiveInfosets(p_game->NumPlayers()) + : m_atEnd(false), m_support(p_game), m_currentBehav(p_game->NumInfosets()), m_profile(p_game), + m_frozenPlayer(0), m_frozenInfoset(0), m_numActiveInfosets(p_game->NumPlayers()) { for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { GamePlayer player = p_game->GetPlayer(pl); @@ -156,9 +146,8 @@ BehaviorProfileIterator::BehaviorProfileIterator(const Game &p_game) } BehaviorProfileIterator::BehaviorProfileIterator(const BehaviorSupportProfile &p_support, - const GameAction &p_action) - : m_atEnd(false), m_support(p_support), - m_currentBehav(p_support.GetGame()->NumInfosets()), + const GameAction &p_action) + : m_atEnd(false), m_support(p_support), m_currentBehav(p_support.GetGame()->NumInfosets()), m_profile(p_support.GetGame()), m_frozenPlayer(p_action->GetInfoset()->GetPlayer()->GetNumber()), m_frozenInfoset(p_action->GetInfoset()->GetNumber()), @@ -182,13 +171,13 @@ BehaviorProfileIterator::BehaviorProfileIterator(const BehaviorSupportProfile &p void BehaviorProfileIterator::First() { - for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { + for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= m_support.GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { if (pl != m_frozenPlayer && iset != m_frozenInfoset) { - m_currentBehav(pl, iset) = 1; - if (m_isActive[pl][iset]) { - m_profile.SetAction(m_support.GetAction(pl, iset, 1)); - } + m_currentBehav(pl, iset) = 1; + if (m_isActive[pl][iset]) { + m_profile.SetAction(m_support.GetAction(pl, iset, 1)); + } } } } @@ -197,8 +186,9 @@ void BehaviorProfileIterator::First() void BehaviorProfileIterator::operator++() { int pl = m_support.GetGame()->NumPlayers(); - while (pl > 0 && m_numActiveInfosets[pl] == 0) + while (pl > 0 && m_numActiveInfosets[pl] == 0) { --pl; + } if (pl == 0) { m_atEnd = true; return; @@ -207,28 +197,26 @@ void BehaviorProfileIterator::operator++() int iset = m_support.GetGame()->GetPlayer(pl)->NumInfosets(); while (true) { - if (m_isActive[pl][iset] && - (pl != m_frozenPlayer || iset != m_frozenInfoset)) { - if (m_currentBehav(pl, iset) < m_support.NumActions(pl, iset)) { - m_profile.SetAction(m_support.GetAction(pl, iset, - ++m_currentBehav(pl, iset))); - return; + if (m_isActive[pl][iset] && (pl != m_frozenPlayer || iset != m_frozenInfoset)) { + if (m_currentBehav(pl, iset) < m_support.NumActions(pl, iset)) { + m_profile.SetAction(m_support.GetAction(pl, iset, ++m_currentBehav(pl, iset))); + return; } else { - m_currentBehav(pl, iset) = 1; - m_profile.SetAction(m_support.GetAction(pl, iset, 1)); + m_currentBehav(pl, iset) = 1; + m_profile.SetAction(m_support.GetAction(pl, iset, 1)); } } iset--; - if (iset == 0) { - do { - --pl; - } while (pl > 0 && m_numActiveInfosets[pl] == 0); + if (iset == 0) { + do { + --pl; + } while (pl > 0 && m_numActiveInfosets[pl] == 0); if (pl == 0) { - m_atEnd = true; - return; + m_atEnd = true; + return; } iset = m_support.GetGame()->GetPlayer(pl)->NumInfosets(); } diff --git a/src/games/behavpure.h b/src/games/behavpure.h index 560494580..ddeee0b65 100644 --- a/src/games/behavpure.h +++ b/src/games/behavpure.h @@ -33,7 +33,7 @@ namespace Gambit { class PureBehaviorProfile { private: Game m_efg; - Array > m_profile; + Array> m_profile; public: /// @name Lifecycle @@ -53,7 +53,9 @@ class PureBehaviorProfile { template T GetPayoff(int pl) const; /// Get the payoff to the player that results from the profile template T GetPayoff(const GamePlayer &p_player) const - { return GetPayoff(p_player->GetNumber()); } + { + return GetPayoff(p_player->GetNumber()); + } /// Get the payoff to player pl conditional on reaching a node template T GetPayoff(const GameNode &, int pl) const; /// Get the payoff to playing the action, conditional on the profile @@ -67,15 +69,20 @@ class PureBehaviorProfile { //@} }; -template<> inline double PureBehaviorProfile::GetPayoff(int pl) const -{ return GetPayoff(m_efg->GetRoot(), pl); } +template <> inline double PureBehaviorProfile::GetPayoff(int pl) const +{ + return GetPayoff(m_efg->GetRoot(), pl); +} -template<> inline Rational PureBehaviorProfile::GetPayoff(int pl) const -{ return GetPayoff(m_efg->GetRoot(), pl); } - -template<> inline std::string PureBehaviorProfile::GetPayoff(int pl) const -{ return lexical_cast(GetPayoff(m_efg->GetRoot(), pl)); } +template <> inline Rational PureBehaviorProfile::GetPayoff(int pl) const +{ + return GetPayoff(m_efg->GetRoot(), pl); +} +template <> inline std::string PureBehaviorProfile::GetPayoff(int pl) const +{ + return lexical_cast(GetPayoff(m_efg->GetRoot(), pl)); +} // // Currently, the contingency iterator only allows one information @@ -90,7 +97,7 @@ class BehaviorProfileIterator { PVector m_currentBehav; PureBehaviorProfile m_profile; int m_frozenPlayer, m_frozenInfoset; - Array > m_isActive; + Array> m_isActive; Array m_numActiveInfosets; /// Reset the iterator to the first contingency (this is called by ctors) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index a82179ebd..0030f74d3 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -28,17 +28,16 @@ namespace Gambit { // BehaviorSupportProfile: Lifecycle //======================================================================== -BehaviorSupportProfile::BehaviorSupportProfile(const Game &p_efg) - : m_efg(p_efg) +BehaviorSupportProfile::BehaviorSupportProfile(const Game &p_efg) : m_efg(p_efg) { for (int pl = 1; pl <= p_efg->NumPlayers(); pl++) { - m_actions.push_back(Array >()); + m_actions.push_back(Array>()); GamePlayer player = p_efg->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { GameInfoset infoset = player->GetInfoset(iset); m_actions[pl].push_back(Array()); for (int act = 1; act <= infoset->NumActions(); act++) { - m_actions[pl][iset].push_back(infoset->GetAction(act)); + m_actions[pl][iset].push_back(infoset->GetAction(act)); } } } @@ -84,8 +83,8 @@ PVector BehaviorSupportProfile::NumActions() const size_t BehaviorSupportProfile::BehaviorProfileLength() const { size_t answer = 0; - for (const auto& player : m_actions) { - for (const auto& infoset : player) { + for (const auto &player : m_actions) { + for (const auto &infoset : player) { answer += infoset.size(); } } @@ -94,7 +93,9 @@ size_t BehaviorSupportProfile::BehaviorProfileLength() const int BehaviorSupportProfile::GetIndex(const GameAction &a) const { - if (a->GetInfoset()->GetGame() != m_efg) throw MismatchException(); + if (a->GetInfoset()->GetGame() != m_efg) { + throw MismatchException(); + } int pl = a->GetInfoset()->GetPlayer()->GetNumber(); if (pl == 0) { @@ -108,7 +109,7 @@ int BehaviorSupportProfile::GetIndex(const GameAction &a) const bool BehaviorSupportProfile::RemoveAction(const GameAction &s) { - for (const auto& node : GetMembers(s->GetInfoset())) { + for (const auto &node : GetMembers(s->GetInfoset())) { DeactivateSubtree(node->GetChild(s)); } @@ -131,7 +132,7 @@ bool BehaviorSupportProfile::RemoveAction(const GameAction &s) bool BehaviorSupportProfile::RemoveAction(const GameAction &s, List &list) { - for (const auto& node : GetMembers(s->GetInfoset())) { + for (const auto &node : GetMembers(s->GetInfoset())) { DeactivateSubtree(node->GetChild(s->GetNumber()), list); } // the following returns false if s was not in the support @@ -165,11 +166,10 @@ void BehaviorSupportProfile::AddAction(const GameAction &s) } } -std::list -BehaviorSupportProfile::GetInfosets(const GamePlayer &p_player) const +std::list BehaviorSupportProfile::GetInfosets(const GamePlayer &p_player) const { std::list answer; - for (const auto& infoset : p_player->GetInfosets()) { + for (const auto &infoset : p_player->GetInfosets()) { if (m_infosetReachable.at(infoset)) { answer.push_back(infoset); } @@ -179,10 +179,8 @@ BehaviorSupportProfile::GetInfosets(const GamePlayer &p_player) const namespace { /// Sets p_reachable(pl,iset) to 1 if infoset (pl,iset) reachable after p_node -void -ReachableInfosets(const BehaviorSupportProfile &p_support, - const GameNode &p_node, - PVector &p_reached) +void ReachableInfosets(const BehaviorSupportProfile &p_support, const GameNode &p_node, + PVector &p_reached) { if (p_node->IsTerminal()) { return; @@ -191,25 +189,25 @@ ReachableInfosets(const BehaviorSupportProfile &p_support, GameInfoset infoset = p_node->GetInfoset(); if (!infoset->GetPlayer()->IsChance()) { p_reached(infoset->GetPlayer()->GetNumber(), infoset->GetNumber()) = 1; - for (const auto &action: p_support.GetActions(infoset)) { + for (const auto &action : p_support.GetActions(infoset)) { ReachableInfosets(p_support, p_node->GetChild(action), p_reached); } } else { - for (const auto &child: p_node->GetChildren()) { + for (const auto &child : p_node->GetChildren()) { ReachableInfosets(p_support, child, p_reached); } } } -} // end anonymous namespace +} // end anonymous namespace // This class iterates // over contingencies that are relevant once a particular node // has been reached. -class BehavConditionalIterator { +class BehavConditionalIterator { private: - bool m_atEnd {false}; + bool m_atEnd{false}; BehaviorSupportProfile m_support; PVector m_currentBehav; PureBehaviorProfile m_profile; @@ -238,13 +236,10 @@ class BehavConditionalIterator { //@} }; - BehavConditionalIterator::BehavConditionalIterator(const BehaviorSupportProfile &p_support, - const PVector &p_active) - : m_support(p_support), - m_currentBehav(m_support.GetGame()->NumInfosets()), - m_profile(m_support.GetGame()), - m_isActive(p_active), + const PVector &p_active) + : m_support(p_support), m_currentBehav(m_support.GetGame()->NumInfosets()), + m_profile(m_support.GetGame()), m_isActive(p_active), m_numActiveInfosets(m_support.GetGame()->NumPlayers()) { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { @@ -252,7 +247,7 @@ BehavConditionalIterator::BehavConditionalIterator(const BehaviorSupportProfile GamePlayer player = m_support.GetGame()->GetPlayer(pl); for (int iset = 1; iset <= player->NumInfosets(); iset++) { if (m_isActive(pl, iset)) { - m_numActiveInfosets[pl]++; + m_numActiveInfosets[pl]++; } } } @@ -261,11 +256,11 @@ BehavConditionalIterator::BehavConditionalIterator(const BehaviorSupportProfile void BehavConditionalIterator::First() { - for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { + for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { for (int iset = 1; iset <= m_support.GetGame()->GetPlayer(pl)->NumInfosets(); iset++) { m_currentBehav(pl, iset) = 1; if (m_isActive(pl, iset)) { - m_profile.SetAction(m_support.GetAction(pl, iset, 1)); + m_profile.SetAction(m_support.GetAction(pl, iset, 1)); } } } @@ -274,8 +269,9 @@ void BehavConditionalIterator::First() void BehavConditionalIterator::operator++() { int pl = m_support.GetGame()->NumPlayers(); - while (pl > 0 && m_numActiveInfosets[pl] == 0) + while (pl > 0 && m_numActiveInfosets[pl] == 0) { --pl; + } if (pl == 0) { m_atEnd = true; return; @@ -285,34 +281,33 @@ void BehavConditionalIterator::operator++() while (true) { if (m_isActive(pl, iset)) { - if (m_currentBehav(pl, iset) < m_support.NumActions(pl, iset)) { - m_profile.SetAction(m_support.GetAction(pl, iset, - ++m_currentBehav(pl, iset))); - return; + if (m_currentBehav(pl, iset) < m_support.NumActions(pl, iset)) { + m_profile.SetAction(m_support.GetAction(pl, iset, ++m_currentBehav(pl, iset))); + return; } else { - m_currentBehav(pl, iset) = 1; - m_profile.SetAction(m_support.GetAction(pl, iset, 1)); + m_currentBehav(pl, iset) = 1; + m_profile.SetAction(m_support.GetAction(pl, iset, 1)); } } iset--; - if (iset == 0) { - do { - --pl; - } while (pl > 0 && m_numActiveInfosets[pl] == 0); + if (iset == 0) { + do { + --pl; + } while (pl > 0 && m_numActiveInfosets[pl] == 0); if (pl == 0) { - m_atEnd = true; - return; + m_atEnd = true; + return; } iset = m_support.GetGame()->GetPlayer(pl)->NumInfosets(); } } } -bool BehaviorSupportProfile::Dominates(const GameAction &a, const GameAction &b, - bool p_strict, bool p_conditional) const +bool BehaviorSupportProfile::Dominates(const GameAction &a, const GameAction &b, bool p_strict, + bool p_conditional) const { GameInfoset infoset = a->GetInfoset(); if (infoset != b->GetInfoset()) { @@ -329,17 +324,17 @@ bool BehaviorSupportProfile::Dominates(const GameAction &a, const GameAction &b, auto bp = (*iter).GetPayoff(b); if (p_strict) { - if (ap <= bp) { - return false; - } + if (ap <= bp) { + return false; + } } else { - if (ap < bp) { - return false; - } - else if (ap > bp) { - equal = false; - } + if (ap < bp) { + return false; + } + else if (ap > bp) { + equal = false; + } } } } @@ -349,19 +344,18 @@ bool BehaviorSupportProfile::Dominates(const GameAction &a, const GameAction &b, if (nodelist.empty()) { // This may not be a good idea; I suggest checking for this // prior to entry - for (const auto& member : infoset->GetMembers()) { + for (const auto &member : infoset->GetMembers()) { nodelist.push_back(member); } } - for (const auto& node : nodelist) { + for (const auto &node : nodelist) { PVector reachable(GetGame()->NumInfosets()); reachable = 0; ReachableInfosets(*this, node->GetChild(a), reachable); ReachableInfosets(*this, node->GetChild(b), reachable); - for (BehavConditionalIterator iter(*this, reachable); - !iter.AtEnd(); iter++) { + for (BehavConditionalIterator iter(*this, reachable); !iter.AtEnd(); iter++) { auto ap = iter->GetPayoff(node->GetChild(a), pl); auto bp = iter->GetPayoff(node->GetChild(b), pl); @@ -390,33 +384,29 @@ bool BehaviorSupportProfile::Dominates(const GameAction &a, const GameAction &b, } } -bool SomeElementDominates(const BehaviorSupportProfile &S, - const Array &array, - const GameAction &a, - const bool strong, - const bool conditional) +bool SomeElementDominates(const BehaviorSupportProfile &S, const Array &array, + const GameAction &a, const bool strong, const bool conditional) { - for (int i = 1; i <= array.Length(); i++) - if (array[i] != a) - if (S.Dominates(array[i],a,strong,conditional)) { - return true; + for (int i = 1; i <= array.Length(); i++) { + if (array[i] != a) { + if (S.Dominates(array[i], a, strong, conditional)) { + return true; } + } + } return false; } -bool BehaviorSupportProfile::IsDominated(const GameAction &a, - bool strong, bool conditional) const +bool BehaviorSupportProfile::IsDominated(const GameAction &a, bool strong, bool conditional) const { int pl = a->GetInfoset()->GetPlayer()->GetNumber(); int iset = a->GetInfoset()->GetNumber(); Array array(m_actions[pl][iset]); - return SomeElementDominates(*this,array,a,strong,conditional); + return SomeElementDominates(*this, array, a, strong, conditional); } -bool InfosetHasDominatedElement(const BehaviorSupportProfile &S, - const GameInfoset &p_infoset, - bool strong, - bool conditional) +bool InfosetHasDominatedElement(const BehaviorSupportProfile &S, const GameInfoset &p_infoset, + bool strong, bool conditional) { int pl = p_infoset->GetPlayer()->GetNumber(); int iset = p_infoset->GetNumber(); @@ -424,42 +414,51 @@ bool InfosetHasDominatedElement(const BehaviorSupportProfile &S, for (int act = 1; act <= S.NumActions(pl, iset); act++) { actions.push_back(S.GetAction(pl, iset, act)); } - for (int i = 1; i <= actions.Length(); i++) - if (SomeElementDominates(S,actions,actions[i], - strong,conditional)) + for (int i = 1; i <= actions.Length(); i++) { + if (SomeElementDominates(S, actions, actions[i], strong, conditional)) { return true; + } + } return false; } -bool ElimDominatedInInfoset(const BehaviorSupportProfile &S, BehaviorSupportProfile &T, - int pl, int iset, - bool strong, bool conditional) +bool ElimDominatedInInfoset(const BehaviorSupportProfile &S, BehaviorSupportProfile &T, int pl, + int iset, bool strong, bool conditional) { Array actions; for (int act = 1; act <= S.NumActions(pl, iset); act++) { actions.push_back(S.GetAction(pl, iset, act)); } Array is_dominated(actions.Length()); - for (int k = 1; k <= actions.Length(); k++) + for (int k = 1; k <= actions.Length(); k++) { is_dominated[k] = false; + } - for (int i = 1; i <= actions.Length(); i++) - for (int j = 1; j <= actions.Length(); j++) - if (i != j && !is_dominated[i] && !is_dominated[j]) - if (S.Dominates(actions[i], actions[j], strong, conditional)) { - is_dominated[j] = true; - } + for (int i = 1; i <= actions.Length(); i++) { + for (int j = 1; j <= actions.Length(); j++) { + if (i != j && !is_dominated[i] && !is_dominated[j]) { + if (S.Dominates(actions[i], actions[j], strong, conditional)) { + is_dominated[j] = true; + } + } + } + } bool action_was_eliminated = false; int k = 1; while (k <= actions.Length() && !action_was_eliminated) { - if (is_dominated[k]) action_was_eliminated = true; - else k++; + if (is_dominated[k]) { + action_was_eliminated = true; + } + else { + k++; + } } while (k <= actions.Length()) { - if (is_dominated[k]) + if (is_dominated[k]) { T.RemoveAction(actions[k]); + } k++; } @@ -467,38 +466,34 @@ bool ElimDominatedInInfoset(const BehaviorSupportProfile &S, BehaviorSupportProf } bool ElimDominatedForPlayer(const BehaviorSupportProfile &S, BehaviorSupportProfile &T, - const int pl, int &cumiset, - const bool strong, - const bool conditional) + const int pl, int &cumiset, const bool strong, const bool conditional) { bool action_was_eliminated = false; - for (int iset = 1; iset <= S.GetGame()->GetPlayer(pl)->NumInfosets(); - iset++, cumiset++) { - if (ElimDominatedInInfoset(S, T, pl, iset, strong, conditional)) + for (int iset = 1; iset <= S.GetGame()->GetPlayer(pl)->NumInfosets(); iset++, cumiset++) { + if (ElimDominatedInInfoset(S, T, pl, iset, strong, conditional)) { action_was_eliminated = true; + } } return action_was_eliminated; } BehaviorSupportProfile BehaviorSupportProfile::Undominated(bool strong, bool conditional, - const Array &players, - std::ostream &) const + const Array &players, + std::ostream &) const { BehaviorSupportProfile T(*this); int cumiset = 0; - for (int i = 1; i <= players.Length(); i++) { + for (int i = 1; i <= players.Length(); i++) { int pl = players[i]; - ElimDominatedForPlayer(*this, T, pl, cumiset, - strong, conditional); + ElimDominatedForPlayer(*this, T, pl, cumiset, strong, conditional); } return T; } - // Utilities bool BehaviorSupportProfile::HasActiveMembers(int pl, int iset) const { @@ -522,7 +517,7 @@ void BehaviorSupportProfile::ActivateSubtree(const GameNode &n) } else { const Array &actions( - m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); + m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); for (int i = 1; i <= actions.Length(); i++) { ActivateSubtree(n->GetChild(actions[i]->GetNumber())); } @@ -532,7 +527,7 @@ void BehaviorSupportProfile::ActivateSubtree(const GameNode &n) void BehaviorSupportProfile::DeactivateSubtree(const GameNode &n) { - if (!n->IsTerminal()) { // THIS ALL LOOKS FISHY + if (!n->IsTerminal()) { // THIS ALL LOOKS FISHY m_nonterminalReachable[n] = false; if (!HasActiveMembers(n->GetInfoset()->GetPlayer()->GetNumber(), n->GetInfoset()->GetNumber())) { @@ -540,7 +535,7 @@ void BehaviorSupportProfile::DeactivateSubtree(const GameNode &n) } if (!n->GetPlayer()->IsChance()) { Array actions( - m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); + m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); for (int i = 1; i <= actions.Length(); i++) { DeactivateSubtree(n->GetChild(actions[i]->GetNumber())); } @@ -553,28 +548,27 @@ void BehaviorSupportProfile::DeactivateSubtree(const GameNode &n) } } -void -BehaviorSupportProfile::DeactivateSubtree(const GameNode &n, List &list) +void BehaviorSupportProfile::DeactivateSubtree(const GameNode &n, List &list) { if (!n->IsTerminal()) { m_nonterminalReachable[n] = false; if (!HasActiveMembers(n->GetInfoset()->GetPlayer()->GetNumber(), - n->GetInfoset()->GetNumber())) { + n->GetInfoset()->GetNumber())) { list.push_back(n->GetInfoset()); m_infosetReachable[n->GetInfoset()] = false; } - Array actions(m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); + Array actions( + m_actions[n->GetInfoset()->GetPlayer()->GetNumber()][n->GetInfoset()->GetNumber()]); for (int i = 1; i <= actions.Length(); i++) { DeactivateSubtree(n->GetChild(actions[i]->GetNumber()), list); } } } -std::list -BehaviorSupportProfile::GetMembers(const GameInfoset &p_infoset) const +std::list BehaviorSupportProfile::GetMembers(const GameInfoset &p_infoset) const { std::list answer; - for (const auto& member : p_infoset->GetMembers()) { + for (const auto &member : p_infoset->GetMembers()) { if (m_nonterminalReachable.at(member)) { answer.push_back(member); } diff --git a/src/games/behavspt.h b/src/games/behavspt.h index de060a598..8442ad4b4 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -39,7 +39,7 @@ namespace Gambit { class BehaviorSupportProfile { protected: Game m_efg; - Array > > m_actions; + Array>> m_actions; std::map m_infosetReachable; std::map m_nonterminalReachable; @@ -62,8 +62,7 @@ class BehaviorSupportProfile { //@{ /// Test for the equality of two supports (same actions at all infosets) bool operator==(const BehaviorSupportProfile &) const; - bool operator!=(const BehaviorSupportProfile &p_support) const - { return !(*this == p_support); } + bool operator!=(const BehaviorSupportProfile &p_support) const { return !(*this == p_support); } /// @name General information //@{ @@ -72,9 +71,10 @@ class BehaviorSupportProfile { /// Returns the number of actions in the information set int NumActions(const GameInfoset &p_infoset) const - { return m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()].Length(); } - int NumActions(int pl, int iset) const - { return m_actions[pl][iset].Length(); } + { + return m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()].Length(); + } + int NumActions(int pl, int iset) const { return m_actions[pl][iset].Length(); } /// Returns the number of actions in the support for all information sets PVector NumActions() const; @@ -82,21 +82,23 @@ class BehaviorSupportProfile { size_t BehaviorProfileLength() const; /// Returns the action at the specified position in the support - GameAction GetAction(int pl, int iset, int act) const - { return m_actions[pl][iset][act]; } + GameAction GetAction(int pl, int iset, int act) const { return m_actions[pl][iset][act]; } /// Returns the set of actions in the support at the information set const Array &GetActions(const GameInfoset &p_infoset) const - { return m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()]; } + { + return m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()]; + } /// Does the information set have at least one active action? bool HasAction(const GameInfoset &p_infoset) const - { return !m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()].empty(); } + { + return !m_actions[p_infoset->GetPlayer()->GetNumber()][p_infoset->GetNumber()].empty(); + } /// Returns the position of the action in the support. int GetIndex(const GameAction &) const; /// Returns whether the action is in the support. - bool Contains(const GameAction &p_action) const - { return (GetIndex(p_action) != 0); } + bool Contains(const GameAction &p_action) const { return (GetIndex(p_action) != 0); } //@} /// @name Editing the support @@ -113,8 +115,7 @@ class BehaviorSupportProfile { /// @name Reachability of nodes and information sets //@{ /// Can the information set be reached under this support? - bool IsReachable(const GameInfoset &p_infoset) const - { return m_infosetReachable.at(p_infoset); } + bool IsReachable(const GameInfoset &p_infoset) const { return m_infosetReachable.at(p_infoset); } /// Get the information sets for the player reachable under the support std::list GetInfosets(const GamePlayer &) const; /// Get the members of the information set reachable under the support @@ -124,18 +125,16 @@ class BehaviorSupportProfile { /// @name Identification of dominated actions //@{ /// Returns true if action a is dominated by action b - bool Dominates(const GameAction &a, const GameAction &b, - bool p_strict, bool p_conditional) const; + bool Dominates(const GameAction &a, const GameAction &b, bool p_strict, + bool p_conditional) const; /// Returns true if the action is dominated by some other action - bool IsDominated(const GameAction &a, - bool p_strict, bool p_conditional) const; + bool IsDominated(const GameAction &a, bool p_strict, bool p_conditional) const; /// Returns a copy of the support with dominated actions eliminated - BehaviorSupportProfile Undominated(bool p_strict, bool p_conditional, - const Array &players, - std::ostream &) const; + BehaviorSupportProfile Undominated(bool p_strict, bool p_conditional, const Array &players, + std::ostream &) const; //@} }; } // end namespace Gambit -#endif // LIBGAMBIT_BEHAVSPT_H +#endif // LIBGAMBIT_BEHAVSPT_H diff --git a/src/games/file.cc b/src/games/file.cc index fc1a76fff..2606cc32d 100644 --- a/src/games/file.cc +++ b/src/games/file.cc @@ -29,15 +29,20 @@ // for explicit access to turning off canonicalization #include "gametree.h" - namespace { // This anonymous namespace encapsulates the file-parsing code using namespace Gambit; using GameFileToken = enum { - TOKEN_NUMBER = 0, TOKEN_TEXT = 1, TOKEN_SYMBOL = 2, - TOKEN_LBRACE = 3, TOKEN_RBRACE = 4, TOKEN_COMMA = 5, TOKEN_EOF = 6, TOKEN_NONE = 7 + TOKEN_NUMBER = 0, + TOKEN_TEXT = 1, + TOKEN_SYMBOL = 2, + TOKEN_LBRACE = 3, + TOKEN_RBRACE = 4, + TOKEN_COMMA = 5, + TOKEN_EOF = 6, + TOKEN_NONE = 7 }; //! @@ -49,18 +54,17 @@ class GameParserState { private: std::istream &m_file; - int m_currentLine {1}; - int m_currentColumn {1}; - GameFileToken m_lastToken { TOKEN_NONE }; + int m_currentLine{1}; + int m_currentColumn{1}; + GameFileToken m_lastToken{TOKEN_NONE}; std::string m_lastText; - void ReadChar(char& c); + void ReadChar(char &c); void UnreadChar(); void IncreaseLine(); public: - explicit GameParserState(std::istream &p_file) : - m_file(p_file) { } + explicit GameParserState(std::istream &p_file) : m_file(p_file) {} GameFileToken GetNextToken(); GameFileToken GetCurrentToken() const { return m_lastToken; } @@ -70,7 +74,7 @@ class GameParserState { const std::string &GetLastText() const { return m_lastText; } }; -void GameParserState::ReadChar(char& c) +void GameParserState::ReadChar(char &c) { m_file.get(c); m_currentColumn++; @@ -82,7 +86,8 @@ void GameParserState::UnreadChar() m_currentColumn--; } -void GameParserState::IncreaseLine(){ +void GameParserState::IncreaseLine() +{ m_currentLine++; // Reset column m_currentColumn = 1; @@ -211,46 +216,49 @@ GameFileToken GameParserState::GetNextToken() m_lastText = ""; - do { + do { ReadChar(a); if (a == '\n') { IncreaseLine(); } } while (isspace(a)); - if (a == '\"') { + if (a == '\"') { bool lastslash = false; ReadChar(a); - while (a != '\"' || lastslash) { - if (m_file.eof() || !m_file.good()) { - throw InvalidFileException(CreateLineMsg("End of file encountered when reading string label")); - } + while (a != '\"' || lastslash) { + if (m_file.eof() || !m_file.good()) { + throw InvalidFileException( + CreateLineMsg("End of file encountered when reading string label")); + } if (lastslash && a == '"') { m_lastText += '"'; - } - else if (lastslash) { + } + else if (lastslash) { m_lastText += '\\'; m_lastText += a; } - else if (a != '\\') + else if (a != '\\') { m_lastText += a; + } lastslash = (a == '\\'); ReadChar(a); } } - else { - do { - m_lastText += a; + else { + do { + m_lastText += a; ReadChar(a); - if (m_file.eof() || !m_file.good()) { - throw InvalidFileException(CreateLineMsg("End of file encountered when reading string label")); - } + if (m_file.eof() || !m_file.good()) { + throw InvalidFileException( + CreateLineMsg("End of file encountered when reading string label")); + } if (a == '\n') { IncreaseLine(); } - } while (!isspace(a)); + } while (!isspace(a)); } return (m_lastToken = TOKEN_TEXT); @@ -275,17 +283,16 @@ class TableFilePlayer { public: std::string m_name; Array m_strategies; - TableFilePlayer *m_next {nullptr}; + TableFilePlayer *m_next{nullptr}; TableFilePlayer() = default; }; - class TableFileGame { public: std::string m_title, m_comment; - TableFilePlayer *m_firstPlayer {nullptr}, *m_lastPlayer {nullptr}; - int m_numPlayers {0}; + TableFilePlayer *m_firstPlayer{nullptr}, *m_lastPlayer{nullptr}; + int m_numPlayers{0}; TableFileGame() = default; ~TableFileGame(); @@ -382,8 +389,7 @@ std::string TableFileGame::GetStrategy(int p_player, int p_strategy) const void ReadPlayers(GameParserState &p_state, TableFileGame &p_data) { if (p_state.GetNextToken() != TOKEN_LBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '{' before players")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '{' before players")); } while (p_state.GetNextToken() == TOKEN_TEXT) { @@ -391,8 +397,7 @@ void ReadPlayers(GameParserState &p_state, TableFileGame &p_data) } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '}' after players")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '}' after players")); } p_state.GetNextToken(); @@ -401,8 +406,7 @@ void ReadPlayers(GameParserState &p_state, TableFileGame &p_data) void ReadStrategies(GameParserState &p_state, TableFileGame &p_data) { if (p_state.GetCurrentToken() != TOKEN_LBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '{' before strategies")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '{' before strategies")); } p_state.GetNextToken(); @@ -411,8 +415,8 @@ void ReadStrategies(GameParserState &p_state, TableFileGame &p_data) while (p_state.GetCurrentToken() == TOKEN_LBRACE) { if (!player) { - throw InvalidFileException(p_state.CreateLineMsg( - "Not enough players for number of strategy entries")); + throw InvalidFileException( + p_state.CreateLineMsg("Not enough players for number of strategy entries")); } while (p_state.GetNextToken() == TOKEN_TEXT) { @@ -420,8 +424,7 @@ void ReadStrategies(GameParserState &p_state, TableFileGame &p_data) } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '}' after player strategy")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '}' after player strategy")); } p_state.GetNextToken(); @@ -429,13 +432,11 @@ void ReadStrategies(GameParserState &p_state, TableFileGame &p_data) } if (player) { - throw InvalidFileException( - p_state.CreateLineMsg("Players with undefined strategies")); + throw InvalidFileException(p_state.CreateLineMsg("Players with undefined strategies")); } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '}' after strategies")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '}' after strategies")); } p_state.GetNextToken(); @@ -445,8 +446,8 @@ void ReadStrategies(GameParserState &p_state, TableFileGame &p_data) while (p_state.GetCurrentToken() == TOKEN_NUMBER) { if (!player) { - throw InvalidFileException(p_state.CreateLineMsg( - "Not enough players for number of strategy entries")); + throw InvalidFileException( + p_state.CreateLineMsg("Not enough players for number of strategy entries")); } for (int st = 1; st <= atoi(p_state.GetLastText().c_str()); st++) { @@ -458,39 +459,32 @@ void ReadStrategies(GameParserState &p_state, TableFileGame &p_data) } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '}' after strategies")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '}' after strategies")); } if (player) { - throw InvalidFileException( - p_state.CreateLineMsg("Players with strategies undefined")); + throw InvalidFileException(p_state.CreateLineMsg("Players with strategies undefined")); } p_state.GetNextToken(); } else { - throw InvalidFileException( - p_state.CreateLineMsg("Unrecognizable strategies format")); + throw InvalidFileException(p_state.CreateLineMsg("Unrecognizable strategies format")); } } void ParseNfgHeader(GameParserState &p_state, TableFileGame &p_data) { - if (p_state.GetNextToken() != TOKEN_NUMBER || - p_state.GetLastText() != "1") { - throw InvalidFileException( - p_state.CreateLineMsg("Accepting only NFG version 1")); + if (p_state.GetNextToken() != TOKEN_NUMBER || p_state.GetLastText() != "1") { + throw InvalidFileException(p_state.CreateLineMsg("Accepting only NFG version 1")); } if (p_state.GetNextToken() != TOKEN_SYMBOL || (p_state.GetLastText() != "D" && p_state.GetLastText() != "R")) { - throw InvalidFileException( - p_state.CreateLineMsg("Accepting only NFG D or R data type")); + throw InvalidFileException(p_state.CreateLineMsg("Accepting only NFG D or R data type")); } if (p_state.GetNextToken() != TOKEN_TEXT) { - throw InvalidFileException( - p_state.CreateLineMsg("Game title missing")); + throw InvalidFileException(p_state.CreateLineMsg("Game title missing")); } p_data.m_title = p_state.GetLastText(); @@ -504,7 +498,6 @@ void ParseNfgHeader(GameParserState &p_state, TableFileGame &p_data) } } - void ReadOutcomeList(GameParserState &p_parser, Game &p_nfg) { if (p_parser.GetNextToken() == TOKEN_RBRACE) { @@ -514,8 +507,7 @@ void ReadOutcomeList(GameParserState &p_parser, Game &p_nfg) } if (p_parser.GetCurrentToken() != TOKEN_LBRACE) { - throw InvalidFileException( - p_parser.CreateLineMsg("Expecting '{' before outcome")); + throw InvalidFileException(p_parser.CreateLineMsg("Expecting '{' before outcome")); } int nOutcomes = 0; @@ -525,8 +517,7 @@ void ReadOutcomeList(GameParserState &p_parser, Game &p_nfg) int pl = 1; if (p_parser.GetNextToken() != TOKEN_TEXT) { - throw InvalidFileException( - p_parser.CreateLineMsg("Expecting string for outcome")); + throw InvalidFileException(p_parser.CreateLineMsg("Expecting string for outcome")); } GameOutcome outcome; @@ -545,28 +536,25 @@ void ReadOutcomeList(GameParserState &p_parser, Game &p_nfg) while (p_parser.GetCurrentToken() == TOKEN_NUMBER) { outcome->SetPayoff(pl++, Number(p_parser.GetLastText())); if (p_parser.GetNextToken() == TOKEN_COMMA) { - p_parser.GetNextToken(); + p_parser.GetNextToken(); } } } catch (IndexException &) { // This would be triggered by too many payoffs - throw InvalidFileException( - p_parser.CreateLineMsg("Exceeded number of players in outcome")); + throw InvalidFileException(p_parser.CreateLineMsg("Exceeded number of players in outcome")); } - if (pl <= p_nfg->NumPlayers() || - p_parser.GetCurrentToken() != TOKEN_RBRACE) { + if (pl <= p_nfg->NumPlayers() || p_parser.GetCurrentToken() != TOKEN_RBRACE) { throw InvalidFileException( - p_parser.CreateLineMsg("Insufficient number of players in outcome")); + p_parser.CreateLineMsg("Insufficient number of players in outcome")); } p_parser.GetNextToken(); } if (p_parser.GetCurrentToken() != TOKEN_RBRACE) { - throw InvalidFileException( - p_parser.CreateLineMsg("Expecting '}' after outcome")); + throw InvalidFileException(p_parser.CreateLineMsg("Expecting '}' after outcome")); } p_parser.GetNextToken(); } @@ -580,12 +568,11 @@ void ParseOutcomeBody(GameParserState &p_parser, Game &p_nfg) while (p_parser.GetCurrentToken() != TOKEN_EOF) { if (p_parser.GetCurrentToken() != TOKEN_NUMBER) { - throw InvalidFileException( - p_parser.CreateLineMsg("Expecting outcome index")); + throw InvalidFileException(p_parser.CreateLineMsg("Expecting outcome index")); } int outcomeId = atoi(p_parser.GetLastText().c_str()); - if (outcomeId > 0) { + if (outcomeId > 0) { (*iter)->SetOutcome(p_nfg->GetOutcome(outcomeId)); } else { @@ -632,7 +619,7 @@ Game BuildNfg(GameParserState &p_parser, TableFileGame &p_data) for (int pl = 1; pl <= dim.Length(); pl++) { nfg->GetPlayer(pl)->SetLabel(p_data.GetPlayer(pl)); for (int st = 1; st <= dim[pl]; st++) { - nfg->GetPlayer(pl)->GetStrategy(st)->SetLabel(p_data.GetStrategy(pl,st)); + nfg->GetPlayer(pl)->GetStrategy(st)->SetLabel(p_data.GetStrategy(pl, st)); } } @@ -643,15 +630,12 @@ Game BuildNfg(GameParserState &p_parser, TableFileGame &p_data) ParsePayoffBody(p_parser, nfg); } else { - throw InvalidFileException( - p_parser.CreateLineMsg("Expecting outcome or payoff")); + throw InvalidFileException(p_parser.CreateLineMsg("Expecting outcome or payoff")); } return nfg; } - - //========================================================================= // Temporary representation classes //========================================================================= @@ -660,18 +644,16 @@ class TreeData { public: std::map m_outcomeMap; std::map m_chanceInfosetMap; - List > m_infosetMap; + List> m_infosetMap; - TreeData() = default; + TreeData() = default; ~TreeData() = default; }; -void ReadPlayers(GameParserState &p_state, - Game &p_game, TreeData &p_treeData) +void ReadPlayers(GameParserState &p_state, Game &p_game, TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_LBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '{' before players")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '{' before players")); } while (p_state.GetNextToken() == TOKEN_TEXT) { @@ -680,8 +662,7 @@ void ReadPlayers(GameParserState &p_state, } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '}' after players")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '}' after players")); } } @@ -693,13 +674,10 @@ void ReadPlayers(GameParserState &p_state, // pointing to the 'c', 'p', or 't' token starting the // next node declaration. // -void ParseOutcome(GameParserState &p_state, - Game &p_game, TreeData &p_treeData, - GameNode &p_node) +void ParseOutcome(GameParserState &p_state, Game &p_game, TreeData &p_treeData, GameNode &p_node) { if (p_state.GetCurrentToken() != TOKEN_NUMBER) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting index of outcome")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting index of outcome")); } int outcomeId = atoi(p_state.GetLastText().c_str()); @@ -720,8 +698,7 @@ void ParseOutcome(GameParserState &p_state, p_node->SetOutcome(outcome); if (p_state.GetNextToken() != TOKEN_LBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '{' before outcome")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '{' before outcome")); } p_state.GetNextToken(); @@ -730,8 +707,7 @@ void ParseOutcome(GameParserState &p_state, outcome->SetPayoff(pl, Number(p_state.GetLastText())); } else { - throw InvalidFileException( - p_state.CreateLineMsg("Payoffs should be numbers")); + throw InvalidFileException(p_state.CreateLineMsg("Payoffs should be numbers")); } // Commas are optional between payoffs @@ -741,8 +717,7 @@ void ParseOutcome(GameParserState &p_state, } if (p_state.GetCurrentToken() != TOKEN_RBRACE) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting '}' after outcome")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting '}' after outcome")); } p_state.GetNextToken(); } @@ -754,14 +729,12 @@ void ParseOutcome(GameParserState &p_state, p_node->SetOutcome(p_treeData.m_outcomeMap[outcomeId]); } else { - throw InvalidFileException( - p_state.CreateLineMsg("Outcome not defined")); + throw InvalidFileException(p_state.CreateLineMsg("Outcome not defined")); } } } -void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, - TreeData &p_treeData); +void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, TreeData &p_treeData); // // Precondition: parser state is expecting the node label @@ -769,8 +742,8 @@ void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, // Postcondition: parser state is pointing at the 'c', 'p', or 't' // beginning the next node entry // -void ParseChanceNode(GameParserState &p_state, - Game &p_game, GameNode &p_node, TreeData &p_treeData) +void ParseChanceNode(GameParserState &p_state, Game &p_game, GameNode &p_node, + TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(p_state.CreateLineMsg("Expecting label")); @@ -796,7 +769,7 @@ void ParseChanceNode(GameParserState &p_state, if (p_state.GetNextToken() != TOKEN_LBRACE) { throw InvalidFileException( - p_state.CreateLineMsg("Expecting '{' before information set data")); + p_state.CreateLineMsg("Expecting '{' before information set data")); } p_state.GetNextToken(); do { @@ -841,8 +814,7 @@ void ParseChanceNode(GameParserState &p_state, } else { // Referencing an undefined infoset is an error - throw InvalidFileException( - p_state.CreateLineMsg("Referencing an undefined infoset")); + throw InvalidFileException(p_state.CreateLineMsg("Referencing an undefined infoset")); } ParseOutcome(p_state, p_game, p_treeData, p_node); @@ -852,8 +824,8 @@ void ParseChanceNode(GameParserState &p_state, } } -void ParsePersonalNode(GameParserState &p_state, - Game p_game, GameNode p_node, TreeData &p_treeData) +void ParsePersonalNode(GameParserState &p_state, Game p_game, GameNode p_node, + TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(p_state.CreateLineMsg("Expecting label")); @@ -886,13 +858,12 @@ void ParsePersonalNode(GameParserState &p_state, if (p_state.GetNextToken() != TOKEN_LBRACE) { throw InvalidFileException( - p_state.CreateLineMsg("Expecting '{' before information set data")); + p_state.CreateLineMsg("Expecting '{' before information set data")); } p_state.GetNextToken(); do { if (p_state.GetCurrentToken() != TOKEN_TEXT) { - throw InvalidFileException( - p_state.CreateLineMsg("Expecting action")); + throw InvalidFileException(p_state.CreateLineMsg("Expecting action")); } actions.push_back(p_state.GetLastText()); @@ -905,7 +876,7 @@ void ParsePersonalNode(GameParserState &p_state, infosetMap[infosetId] = infoset; infoset->SetLabel(label); for (int act = 1; act <= actions.Length(); act++) { - infoset->GetAction(act)->SetLabel(actions[act]); + infoset->GetAction(act)->SetLabel(actions[act]); } } else { @@ -918,8 +889,7 @@ void ParsePersonalNode(GameParserState &p_state, } else { // Referencing an undefined infoset is an error - throw InvalidFileException( - p_state.CreateLineMsg("Referencing an undefined infoset")); + throw InvalidFileException(p_state.CreateLineMsg("Referencing an undefined infoset")); } ParseOutcome(p_state, p_game, p_treeData, p_node); @@ -929,8 +899,8 @@ void ParsePersonalNode(GameParserState &p_state, } } -void ParseTerminalNode(GameParserState &p_state, - Game p_game, GameNode p_node, TreeData &p_treeData) +void ParseTerminalNode(GameParserState &p_state, Game p_game, GameNode p_node, + TreeData &p_treeData) { if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(p_state.CreateLineMsg("Expecting label")); @@ -942,8 +912,7 @@ void ParseTerminalNode(GameParserState &p_state, ParseOutcome(p_state, p_game, p_treeData, p_node); } -void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, - TreeData &p_treeData) +void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, TreeData &p_treeData) { if (p_state.GetLastText() == "c") { ParseChanceNode(p_state, p_game, p_node, p_treeData); @@ -961,16 +930,13 @@ void ParseNode(GameParserState &p_state, Game p_game, GameNode p_node, void ParseEfg(GameParserState &p_state, Game p_game, TreeData &p_treeData) { - if (p_state.GetNextToken() != TOKEN_NUMBER || - p_state.GetLastText() != "2") { - throw InvalidFileException( - p_state.CreateLineMsg("Accepting only EFG version 2")); + if (p_state.GetNextToken() != TOKEN_NUMBER || p_state.GetLastText() != "2") { + throw InvalidFileException(p_state.CreateLineMsg("Accepting only EFG version 2")); } if (p_state.GetNextToken() != TOKEN_SYMBOL || (p_state.GetLastText() != "D" && p_state.GetLastText() != "R")) { - throw InvalidFileException( - p_state.CreateLineMsg("Accepting only EFG R or D data type")); + throw InvalidFileException(p_state.CreateLineMsg("Accepting only EFG R or D data type")); } if (p_state.GetNextToken() != TOKEN_TEXT) { throw InvalidFileException(p_state.CreateLineMsg("Game title missing")); @@ -990,7 +956,6 @@ void ParseEfg(GameParserState &p_state, Game p_game, TreeData &p_treeData) } // end of anonymous namespace - #include "core/tinyxml.h" namespace Gambit { @@ -1001,7 +966,7 @@ class GameXMLSavefile { public: explicit GameXMLSavefile(const std::string &p_xml); - ~GameXMLSavefile() = default; + ~GameXMLSavefile() = default; Game GetGame() const; }; @@ -1083,7 +1048,8 @@ Game ReadGame(std::istream &p_file) return GameBAGGRep::ReadBaggFile(buffer); } else { - throw InvalidFileException("Tokens 'EFG' or 'NFG' or '#AGG' or '#BAGG' expected at start of file"); + throw InvalidFileException( + "Tokens 'EFG' or 'NFG' or '#AGG' or '#BAGG' expected at start of file"); } } catch (std::exception &ex) { diff --git a/src/games/game.cc b/src/games/game.cc index 39557406d..e973ce53b 100644 --- a/src/games/game.cc +++ b/src/games/game.cc @@ -40,10 +40,9 @@ namespace Gambit { //======================================================================== GameOutcomeRep::GameOutcomeRep(GameRep *p_game, int p_number) - : m_game(p_game), m_number(p_number), - m_payoffs(m_game->NumPlayers()) -{ } - + : m_game(p_game), m_number(p_number), m_payoffs(m_game->NumPlayers()) +{ +} //======================================================================== // class GameStrategyRep @@ -51,15 +50,19 @@ GameOutcomeRep::GameOutcomeRep(GameRep *p_game, int p_number) void GameStrategyRep::DeleteStrategy() { - if (m_player->GetGame()->IsTree()) throw UndefinedException(); - if (m_player->NumStrategies() == 1) return; + if (m_player->GetGame()->IsTree()) { + throw UndefinedException(); + } + if (m_player->NumStrategies() == 1) { + return; + } m_player->GetGame()->IncrementVersion(); m_player->m_strategies.Remove(m_player->m_strategies.Find(this)); for (int st = 1; st <= m_player->m_strategies.Length(); st++) { m_player->m_strategies[st]->m_number = st; } - //m_player->m_game->RebuildTable(); + // m_player->m_game->RebuildTable(); this->Invalidate(); } @@ -90,20 +93,22 @@ Array GamePlayerRep::GetStrategies() const { m_game->BuildComputedValues(); Array ret(m_strategies.size()); - std::transform(m_strategies.cbegin(), m_strategies.cend(), - ret.begin(), [](GameStrategyRep *s) -> GameStrategy { return s; }); + std::transform(m_strategies.cbegin(), m_strategies.cend(), ret.begin(), + [](GameStrategyRep *s) -> GameStrategy { return s; }); return ret; } GameStrategy GamePlayerRep::NewStrategy() { - if (m_game->IsTree()) throw UndefinedException(); + if (m_game->IsTree()) { + throw UndefinedException(); + } m_game->IncrementVersion(); auto *strategy = new GameStrategyRep(this); m_strategies.push_back(strategy); strategy->m_number = m_strategies.size(); - strategy->m_offset = -1; // this flags this action as new + strategy->m_offset = -1; // this flags this action as new dynamic_cast(m_game)->RebuildTable(); return strategy; } @@ -112,11 +117,13 @@ void GamePlayerRep::MakeStrategy() { Array c(NumInfosets()); - for (int i = 1; i <= NumInfosets(); i++) { - if (m_infosets[i]->flag == 1) + for (int i = 1; i <= NumInfosets(); i++) { + if (m_infosets[i]->flag == 1) { c[i] = m_infosets[i]->whichbranch; - else + } + else { c[i] = 0; + } } auto *strategy = new GameStrategyRep(this); @@ -129,10 +136,10 @@ void GamePlayerRep::MakeStrategy() if (!strategy->m_behav.empty()) { for (int iset = 1; iset <= strategy->m_behav.Length(); iset++) { if (strategy->m_behav[iset] > 0) { - strategy->m_label += lexical_cast(strategy->m_behav[iset]); + strategy->m_label += lexical_cast(strategy->m_behav[iset]); } else { - strategy->m_label += "*"; + strategy->m_label += "*"; } } } @@ -146,47 +153,53 @@ void GamePlayerRep::MakeReducedStrats(GameTreeNodeRep *n, GameTreeNodeRep *nn) int i; GameTreeNodeRep *m, *mm; - if (!n->GetParent()) n->ptr = nullptr; - - if (n->NumChildren() > 0) { - if (n->infoset->m_player == this) { - if (n->infoset->flag == 0) { - // we haven't visited this infoset before - n->infoset->flag = 1; - for (i = 1; i <= n->NumChildren(); i++) { - GameTreeNodeRep *m = n->children[i]; - n->whichbranch = m; - n->infoset->whichbranch = i; - MakeReducedStrats(m, nn); - } - n->infoset->flag = 0; + if (!n->GetParent()) { + n->ptr = nullptr; + } + + if (n->NumChildren() > 0) { + if (n->infoset->m_player == this) { + if (n->infoset->flag == 0) { + // we haven't visited this infoset before + n->infoset->flag = 1; + for (i = 1; i <= n->NumChildren(); i++) { + GameTreeNodeRep *m = n->children[i]; + n->whichbranch = m; + n->infoset->whichbranch = i; + MakeReducedStrats(m, nn); + } + n->infoset->flag = 0; } - else { - // we have visited this infoset, take same action - MakeReducedStrats(n->children[n->infoset->whichbranch], nn); + else { + // we have visited this infoset, take same action + MakeReducedStrats(n->children[n->infoset->whichbranch], nn); } } - else { + else { n->ptr = nullptr; - if (nn != nullptr) - n->ptr = nn->m_parent; + if (nn != nullptr) { + n->ptr = nn->m_parent; + } n->whichbranch = n->children[1]; - if (n->infoset) - n->infoset->whichbranch = 0; + if (n->infoset) { + n->infoset->whichbranch = 0; + } MakeReducedStrats(n->children[1], n->children[1]); } } - else if (nn) { - for (; ; nn = nn->m_parent->ptr->whichbranch) { + else if (nn) { + for (;; nn = nn->m_parent->ptr->whichbranch) { if (!nn->GetNextSibling()) { - m = nullptr; + m = nullptr; } else { - m = dynamic_cast(nn->GetNextSibling().operator->()); + m = dynamic_cast(nn->GetNextSibling().operator->()); + } + if (m || nn->m_parent->ptr == nullptr) { + break; } - if (m || nn->m_parent->ptr == nullptr) break; } - if (m) { + if (m) { mm = m->m_parent->whichbranch; m->m_parent->whichbranch = m; MakeReducedStrats(m, m); @@ -201,16 +214,13 @@ void GamePlayerRep::MakeReducedStrats(GameTreeNodeRep *n, GameTreeNodeRep *nn) } } -GameInfoset GamePlayerRep::GetInfoset(int p_index) const -{ - return m_infosets[p_index]; -} +GameInfoset GamePlayerRep::GetInfoset(int p_index) const { return m_infosets[p_index]; } Array GamePlayerRep::GetInfosets() const { Array ret(m_infosets.size()); - std::transform(m_infosets.cbegin(), m_infosets.cend(), - ret.begin(), [](GameTreeInfosetRep *s) -> GameInfoset { return s; }); + std::transform(m_infosets.cbegin(), m_infosets.cend(), ret.begin(), + [](GameTreeInfosetRep *s) -> GameInfoset { return s; }); return ret; } @@ -219,8 +229,9 @@ int GamePlayerRep::NumSequences() const if (!m_game->IsTree()) { throw UndefinedException(); } - return std::accumulate(m_infosets.cbegin(), m_infosets.cend(), 1, - [](int ct, GameTreeInfosetRep *s) -> int { return ct + s->m_actions.size(); }); + return std::accumulate( + m_infosets.cbegin(), m_infosets.cend(), 1, + [](int ct, GameTreeInfosetRep *s) -> int { return ct + s->m_actions.size(); }); } //======================================================================== @@ -236,7 +247,6 @@ Array GameRep::GetPlayers() const return ret; } - Array GameRep::GetStrategies() const { Array ret(MixedProfileLength()); @@ -250,27 +260,27 @@ Array GameRep::GetStrategies() const return ret; } - //------------------------------------------------------------------------ // GameRep: Writing data files //------------------------------------------------------------------------ - namespace { std::string EscapeQuotes(const std::string &s) { std::string ret; - for (char c : s) { - if (c == '"') ret += '\\'; + for (char c : s) { + if (c == '"') { + ret += '\\'; + } ret += c; } return ret; } -} // end anonymous namespace +} // end anonymous namespace /// /// Write the game to a savefile in .nfg payoff format. @@ -319,8 +329,7 @@ void GameRep::WriteNfgFile(std::ostream &p_file) const template MixedStrategyProfileRep::MixedStrategyProfileRep(const StrategySupportProfile &p_support) - : m_probs(p_support.MixedProfileLength()), - m_support(p_support), + : m_probs(p_support.MixedProfileLength()), m_support(p_support), m_gameversion(p_support.GetGame()->GetVersion()) { SetCentroid(); @@ -329,23 +338,24 @@ MixedStrategyProfileRep::MixedStrategyProfileRep(const StrategySupportProfile template void MixedStrategyProfileRep::SetCentroid() { for (auto player : m_support.GetGame()->GetPlayers()) { - T center = ((T) 1) / ((T) m_support.NumStrategies(player->GetNumber())); + T center = ((T)1) / ((T)m_support.NumStrategies(player->GetNumber())); for (auto strategy : m_support.GetStrategies(player)) { (*this)[strategy] = center; } } } -template -MixedStrategyProfileRep *MixedStrategyProfileRep::Normalize() const +template MixedStrategyProfileRep *MixedStrategyProfileRep::Normalize() const { auto norm = Copy(); for (auto player : m_support.GetGame()->GetPlayers()) { - T sum = (T) 0; + T sum = (T)0; for (auto strategy : m_support.GetStrategies(player)) { sum += (*this)[strategy]; } - if (sum == (T) 0) continue; + if (sum == (T)0) { + continue; + } for (auto strategy : m_support.GetStrategies(player)) { (*norm)[strategy] /= sum; } @@ -353,7 +363,7 @@ MixedStrategyProfileRep *MixedStrategyProfileRep::Normalize() const return norm; } -template<> void MixedStrategyProfileRep::Randomize() +template <> void MixedStrategyProfileRep::Randomize() { Game nfg = m_support.GetGame(); m_probs = 0.0; @@ -363,7 +373,7 @@ template<> void MixedStrategyProfileRep::Randomize() // renormalize at the end (this is a special case of the Dirichlet distribution). for (auto player : nfg->GetPlayers()) { for (auto strategy : player->GetStrategies()) { - (*this)[strategy] = -std::log(((double) std::rand()) / ((double) RAND_MAX)); + (*this)[strategy] = -std::log(((double)std::rand()) / ((double)RAND_MAX)); } } auto normed = Normalize(); @@ -371,7 +381,7 @@ template<> void MixedStrategyProfileRep::Randomize() delete normed; } -template<> void MixedStrategyProfileRep::Randomize() +template <> void MixedStrategyProfileRep::Randomize() { // This operation is not well-defined when using Rational numbers; // use the version specifying the denominator grid instead. @@ -387,7 +397,7 @@ template void MixedStrategyProfileRep::Randomize(int p_denom) std::vector cutoffs; for (size_t st = 1; st < player->GetStrategies().size(); st++) { // When we support C++11, we will be able to implement uniformity better here. - cutoffs.push_back(std::rand() % (p_denom+1)); + cutoffs.push_back(std::rand() % (p_denom + 1)); } std::sort(cutoffs.begin(), cutoffs.end()); cutoffs.push_back(p_denom); @@ -400,40 +410,37 @@ template void MixedStrategyProfileRep::Randomize(int p_denom) } } -template -T MixedStrategyProfileRep::GetRegret(const GameStrategy &p_strategy) const +template T MixedStrategyProfileRep::GetRegret(const GameStrategy &p_strategy) const { GamePlayer player = p_strategy->GetPlayer(); T payoff = GetPayoffDeriv(player->GetNumber(), p_strategy); T brpayoff = payoff; for (auto strategy : player->GetStrategies()) { if (strategy != p_strategy) { - brpayoff = std::max(brpayoff, - GetPayoffDeriv(player->GetNumber(), strategy)); + brpayoff = std::max(brpayoff, GetPayoffDeriv(player->GetNumber(), strategy)); } } return brpayoff - payoff; } - -template -T MixedStrategyProfileRep::GetRegret(const GamePlayer &p_player) const +template T MixedStrategyProfileRep::GetRegret(const GamePlayer &p_player) const { auto strategies = p_player->GetStrategies(); - T br_payoff = std::accumulate( - std::next(strategies.begin()), strategies.end(), GetPayoff(*strategies.begin()), - [this](const T &x, const GameStrategy &strategy) { return std::max(x, GetPayoff(strategy)); }); + T br_payoff = std::accumulate(std::next(strategies.begin()), strategies.end(), + GetPayoff(*strategies.begin()), + [this](const T &x, const GameStrategy &strategy) { + return std::max(x, GetPayoff(strategy)); + }); return br_payoff - GetPayoff(p_player); } - -template -T MixedStrategyProfileRep::GetMaxRegret() const +template T MixedStrategyProfileRep::GetMaxRegret() const { auto players = m_support.GetGame()->GetPlayers(); - return std::accumulate( - players.begin(), players.end(), T(0), - [this](const T &x, const GamePlayer &player) { return std::max(x, this->GetRegret(player)); }); + return std::accumulate(players.begin(), players.end(), T(0), + [this](const T &x, const GamePlayer &player) { + return std::max(x, this->GetRegret(player)); + }); } //======================================================================== @@ -446,13 +453,14 @@ MixedStrategyProfile::MixedStrategyProfile(const MixedBehaviorProfile &p_p { Game game = p_profile.GetGame(); auto *efg = dynamic_cast(game.operator->()); - for (int pl = 1; pl <= m_rep->m_support.GetGame()->NumPlayers(); pl++) { - for (int st = 1; st <= m_rep->m_support.GetGame()->GetPlayer(pl)->NumStrategies(); st++) { - T prob = (T) 1; + for (int pl = 1; pl <= m_rep->m_support.GetGame()->NumPlayers(); pl++) { + for (int st = 1; st <= m_rep->m_support.GetGame()->GetPlayer(pl)->NumStrategies(); st++) { + T prob = (T)1; for (int iset = 1; iset <= efg->GetPlayer(pl)->NumInfosets(); iset++) { - if (efg->m_players[pl]->m_strategies[st]->m_behav[iset] > 0) + if (efg->m_players[pl]->m_strategies[st]->m_behav[iset] > 0) { prob *= p_profile(pl, iset, efg->m_players[pl]->m_strategies[st]->m_behav[iset]); + } } (*this)[m_rep->m_support.GetGame()->GetPlayer(pl)->GetStrategy(st)] = prob; } @@ -462,10 +470,12 @@ MixedStrategyProfile::MixedStrategyProfile(const MixedBehaviorProfile &p_p template MixedStrategyProfile::MixedStrategyProfile(const MixedStrategyProfile &p_profile) : m_rep(p_profile.m_rep->Copy()) -{ } +{ +} template -MixedStrategyProfile &MixedStrategyProfile::operator=(const MixedStrategyProfile &p_profile) +MixedStrategyProfile & +MixedStrategyProfile::operator=(const MixedStrategyProfile &p_profile) { if (this != &p_profile) { delete m_rep; @@ -474,19 +484,13 @@ MixedStrategyProfile &MixedStrategyProfile::operator=(const MixedStrategyP return *this; } -template -MixedStrategyProfile::~MixedStrategyProfile() -{ - delete m_rep; -} - +template MixedStrategyProfile::~MixedStrategyProfile() { delete m_rep; } //======================================================================== // MixedStrategyProfile: General data access //======================================================================== -template -Vector MixedStrategyProfile::operator[](const GamePlayer &p_player) const +template Vector MixedStrategyProfile::operator[](const GamePlayer &p_player) const { CheckVersion(); auto strategies = m_rep->m_support.GetStrategies(p_player); @@ -498,11 +502,10 @@ Vector MixedStrategyProfile::operator[](const GamePlayer &p_player) const return probs; } -template -MixedStrategyProfile MixedStrategyProfile::ToFullSupport() const +template MixedStrategyProfile MixedStrategyProfile::ToFullSupport() const { CheckVersion(); - MixedStrategyProfile full(m_rep->m_support.GetGame()->NewMixedStrategyProfile((T) 0)); + MixedStrategyProfile full(m_rep->m_support.GetGame()->NewMixedStrategyProfile((T)0)); for (int pl = 1; pl <= m_rep->m_support.GetGame()->NumPlayers(); pl++) { GamePlayer player = m_rep->m_support.GetGame()->GetPlayer(pl); @@ -526,35 +529,35 @@ MixedStrategyProfile MixedStrategyProfile::ToFullSupport() const template T MixedStrategyProfile::GetLiapValue() const { CheckVersion(); - static const T BIG1 = (T) 100; - static const T BIG2 = (T) 100; + static const T BIG1 = (T)100; + static const T BIG2 = (T)100; - T liapValue = (T) 0; + T liapValue = (T)0; for (auto player : m_rep->m_support.GetPlayers()) { // values of the player's strategies std::map values; - T avg = (T) 0, sum = (T) 0; + T avg = (T)0, sum = (T)0; for (auto strategy : m_rep->m_support.GetStrategies(player)) { const T &prob = (*this)[strategy]; values[strategy] = GetPayoff(strategy); avg += prob * values.at(strategy); sum += prob; - if (prob < (T) 0) { - liapValue += BIG1*prob*prob; // penalty for negative probabilities + if (prob < (T)0) { + liapValue += BIG1 * prob * prob; // penalty for negative probabilities } } for (auto v : values) { T regret = v.second - avg; - if (regret > (T) 0) { - liapValue += regret*regret; // penalty if not best response + if (regret > (T)0) { + liapValue += regret * regret; // penalty if not best response } } // penalty if sum does not equal to one - liapValue += BIG2*(sum - (T) 1.0)*(sum - (T) 1.0); + liapValue += BIG2 * (sum - (T)1.0) * (sum - (T)1.0); } return liapValue; @@ -566,5 +569,4 @@ template class MixedStrategyProfileRep; template class MixedStrategyProfile; template class MixedStrategyProfile; - -} // end namespace Gambit +} // end namespace Gambit diff --git a/src/games/game.h b/src/games/game.h index 37ef4f508..7f239ecd7 100644 --- a/src/games/game.h +++ b/src/games/game.h @@ -20,7 +20,6 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // - #ifndef LIBGAMBIT_GAME_H #define LIBGAMBIT_GAME_H @@ -71,8 +70,8 @@ template class MixedBehaviorProfile; /// Exception thrown when an operation that is undefined is attempted class UndefinedException : public Exception { public: - UndefinedException() : Exception("Undefined operation on game") { } - explicit UndefinedException(const std::string &s) : Exception(s) { } + UndefinedException() : Exception("Undefined operation on game") {} + explicit UndefinedException(const std::string &s) : Exception(s) {} ~UndefinedException() noexcept override = default; }; @@ -81,7 +80,9 @@ class MismatchException : public Exception { public: ~MismatchException() noexcept override = default; const char *what() const noexcept override - { return "Operation between objects in different games"; } + { + return "Operation between objects in different games"; + } }; /// Exception thrown when comparing different versions of a game @@ -89,14 +90,16 @@ class GameStructureChangedException : public Exception { public: ~GameStructureChangedException() noexcept override = default; const char *what() const noexcept override - { return "Game structure has changed since object was defined"; } + { + return "Game structure has changed since object was defined"; + } }; /// Exception thrown on a parse error when reading a game savefile class InvalidFileException : public Exception { public: - InvalidFileException() : Exception("File not in a recognized format") { } - explicit InvalidFileException(const std::string &s) : Exception(s) { } + InvalidFileException() : Exception("File not in a recognized format") {} + explicit InvalidFileException(const std::string &s) : Exception(s) {} ~InvalidFileException() noexcept override = default; }; @@ -106,7 +109,7 @@ class InvalidFileException : public Exception { /// This class represents an outcome in a game. An outcome /// specifies a vector of payoffs to players. -class GameOutcomeRep : public GameObject { +class GameOutcomeRep : public GameObject { friend class GameExplicitRep; friend class GameTreeRep; friend class GameTableRep; @@ -164,7 +167,6 @@ class GameActionRep : public GameObject { virtual bool Precedes(const GameNode &) const = 0; virtual void DeleteAction() = 0; - }; /// An information set in an extensive game @@ -217,7 +219,7 @@ class GameInfosetRep : public GameObject { /// strategies gives the index into the strategic game's table to /// find the outcome for that strategy profile, making payoff computation /// relatively efficient. -class GameStrategyRep : public GameObject { +class GameStrategyRep : public GameObject { friend class GameExplicitRep; friend class GameTreeRep; friend class GameTableRep; @@ -243,7 +245,9 @@ class GameStrategyRep : public GameObject { //@{ /// Creates a new strategy for the given player. explicit GameStrategyRep(GamePlayerRep *p_player) - : m_number(0), m_id(0), m_player(p_player), m_offset(0L) { } + : m_number(0), m_id(0), m_player(p_player), m_offset(0L) + { + } //@} public: @@ -293,8 +297,7 @@ class GamePlayerRep : public GameObject { Array m_infosets; Array m_strategies; - GamePlayerRep(GameRep *p_game, int p_id) - : m_game(p_game), m_number(p_id) { } + GamePlayerRep(GameRep *p_game, int p_id) : m_game(p_game), m_number(p_id) {} GamePlayerRep(GameRep *p_game, int p_id, int m_strats); ~GamePlayerRep() override; @@ -387,7 +390,6 @@ class GameNodeRep : public GameObject { virtual GameInfoset InsertMove(GameInfoset p_infoset) = 0; }; - /// This is the class for representing an arbitrary finite game. class GameRep : public BaseGameRep { friend class GameOutcomeRep; @@ -406,14 +408,14 @@ class GameRep : public BaseGameRep { std::string m_title, m_comment; unsigned int m_version; - GameRep() : m_version(0) { } + GameRep() : m_version(0) {} /// @name Managing the representation //@{ /// Mark that the content of the game has changed void IncrementVersion() { m_version++; } /// Build any computed values anew - virtual void BuildComputedValues() { } + virtual void BuildComputedValues() {} public: /// @name Lifecycle @@ -458,18 +460,21 @@ class GameRep : public BaseGameRep { virtual bool IsPerfectRecall(GameInfoset &, GameInfoset &) const = 0; /// Returns true if the game is perfect recall bool IsPerfectRecall() const - { GameInfoset s, t; return IsPerfectRecall(s, t); } + { + GameInfoset s, t; + return IsPerfectRecall(s, t); + } //@} /// @name Writing data files //@{ /// Write the game to a savefile in the specified format. - virtual void Write(std::ostream &p_stream, - const std::string &p_format="native") const - { throw UndefinedException(); } + virtual void Write(std::ostream &p_stream, const std::string &p_format = "native") const + { + throw UndefinedException(); + } /// Write the game in .efg format to the specified stream - virtual void WriteEfgFile(std::ostream &) const - { throw UndefinedException(); } + virtual void WriteEfgFile(std::ostream &) const { throw UndefinedException(); } /// Write the game to a file in .nfg payoff format. virtual void WriteNfgFile(std::ostream &p_stream) const; //@} @@ -497,8 +502,10 @@ class GameRep : public BaseGameRep { virtual PureStrategyProfile NewPureStrategyProfile() const = 0; virtual MixedStrategyProfile NewMixedStrategyProfile(double) const = 0; virtual MixedStrategyProfile NewMixedStrategyProfile(const Rational &) const = 0; - virtual MixedStrategyProfile NewMixedStrategyProfile(double, const StrategySupportProfile&) const = 0; - virtual MixedStrategyProfile NewMixedStrategyProfile(const Rational &, const StrategySupportProfile&) const = 0; + virtual MixedStrategyProfile + NewMixedStrategyProfile(double, const StrategySupportProfile &) const = 0; + virtual MixedStrategyProfile + NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &) const = 0; /// @name Players //@{ @@ -588,9 +595,15 @@ inline GamePlayer GameStrategyRep::GetPlayer() const { return m_player; } inline Game GamePlayerRep::GetGame() const { return m_game; } inline int GamePlayerRep::NumStrategies() const -{ m_game->BuildComputedValues(); return m_strategies.size(); } +{ + m_game->BuildComputedValues(); + return m_strategies.size(); +} inline GameStrategy GamePlayerRep::GetStrategy(int st) const -{ m_game->BuildComputedValues(); return m_strategies[st]; } +{ + m_game->BuildComputedValues(); + return m_strategies[st]; +} //======================================================================= @@ -601,6 +614,6 @@ Game NewTable(const Array &p_dim, bool p_sparseOutcomes = false); /// Reads a game in .efg or .nfg format from the input stream Game ReadGame(std::istream &); -} // end namespace gambit +} // namespace Gambit -#endif // LIBGAMBIT_GAME_H +#endif // LIBGAMBIT_GAME_H diff --git a/src/games/gameagg.cc b/src/games/gameagg.cc index 5c1cd44d5..089dcdc9c 100644 --- a/src/games/gameagg.cc +++ b/src/games/gameagg.cc @@ -33,15 +33,12 @@ namespace Gambit { class AGGPureStrategyProfileRep : public PureStrategyProfileRep { public: - explicit AGGPureStrategyProfileRep(const Game &p_game) - : PureStrategyProfileRep(p_game) { } - PureStrategyProfileRep *Copy() const override - { return new AGGPureStrategyProfileRep(*this); } + explicit AGGPureStrategyProfileRep(const Game &p_game) : PureStrategyProfileRep(p_game) {} + PureStrategyProfileRep *Copy() const override { return new AGGPureStrategyProfileRep(*this); } void SetStrategy(const GameStrategy &) override; GameOutcome GetOutcome() const override { throw UndefinedException(); } - void SetOutcome(GameOutcome p_outcome) override - { throw UndefinedException(); } + void SetOutcome(GameOutcome p_outcome) override { throw UndefinedException(); } Rational GetPayoff(int pl) const override; Rational GetStrategyValue(const GameStrategy &) const override; }; @@ -60,38 +57,38 @@ Rational AGGPureStrategyProfileRep::GetPayoff(int pl) const std::shared_ptr aggPtr = dynamic_cast(*m_nfg).aggPtr; std::vector s(aggPtr->getNumPlayers()); for (int i = 1; i <= aggPtr->getNumPlayers(); i++) { - s[i-1] = m_profile[i]->GetNumber() -1; + s[i - 1] = m_profile[i]->GetNumber() - 1; } - return Rational(aggPtr->getPurePayoff(pl-1, s)); + return Rational(aggPtr->getPurePayoff(pl - 1, s)); } -Rational -AGGPureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const +Rational AGGPureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const { int player = p_strategy->GetPlayer()->GetNumber(); std::shared_ptr aggPtr = dynamic_cast(*m_nfg).aggPtr; std::vector s(aggPtr->getNumPlayers()); for (int i = 1; i <= aggPtr->getNumPlayers(); i++) { - s[i-1] = m_profile[i]->GetNumber() - 1; + s[i - 1] = m_profile[i]->GetNumber() - 1; } - s[player-1] = p_strategy->GetNumber() - 1; - return Rational(aggPtr->getPurePayoff(player-1, s)); + s[player - 1] = p_strategy->GetNumber() - 1; + return Rational(aggPtr->getPurePayoff(player - 1, s)); } //======================================================================== // AGGMixedStrategyProfileRep //======================================================================== -template class AGGMixedStrategyProfileRep - : public MixedStrategyProfileRep { +template class AGGMixedStrategyProfileRep : public MixedStrategyProfileRep { public: explicit AGGMixedStrategyProfileRep(const StrategySupportProfile &p_support) : MixedStrategyProfileRep(p_support) - { } + { + } ~AGGMixedStrategyProfileRep() override = default; - MixedStrategyProfileRep *Copy() const override { + MixedStrategyProfileRep *Copy() const override + { return new AGGMixedStrategyProfileRep(*this); } T GetPayoff(int pl) const override; @@ -99,90 +96,90 @@ template class AGGMixedStrategyProfileRep T GetPayoffDeriv(int pl, const GameStrategy &, const GameStrategy &) const override; }; -template -T AGGMixedStrategyProfileRep::GetPayoff(int pl) const +template T AGGMixedStrategyProfileRep::GetPayoff(int pl) const { auto &g = dynamic_cast(*(this->m_support.GetGame())); - std::vector s (g.aggPtr->getNumActions()); - for (int i=0;igetNumPlayers();++i) { - for (int j=0;jgetNumActions(i);++j){ - GameStrategy strategy = this->m_support.GetGame()->GetPlayer(i+1)->GetStrategy(j+1); + std::vector s(g.aggPtr->getNumActions()); + for (int i = 0; i < g.aggPtr->getNumPlayers(); ++i) { + for (int j = 0; j < g.aggPtr->getNumActions(i); ++j) { + GameStrategy strategy = this->m_support.GetGame()->GetPlayer(i + 1)->GetStrategy(j + 1); int ind = this->m_support.m_profileIndex[strategy->GetId()]; - s[g.aggPtr->firstAction(i)+j]= (ind==-1)?(T)0:this->m_probs[ind]; + s[g.aggPtr->firstAction(i) + j] = (ind == -1) ? (T)0 : this->m_probs[ind]; } } - return (T) g.aggPtr->getMixedPayoff(pl-1, s); + return (T)g.aggPtr->getMixedPayoff(pl - 1, s); } template T AGGMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &ps) const { auto &g = dynamic_cast(*(this->m_support.GetGame())); - std::vector s (g.aggPtr->getNumActions()); - for (int i=0;igetNumPlayers();++i){ - if(i+1 == ps->GetPlayer()->GetNumber()){ - for (int j=0;jgetNumActions(i);++j){ - s[g.aggPtr->firstAction(i)+j] = (T) 0; + std::vector s(g.aggPtr->getNumActions()); + for (int i = 0; i < g.aggPtr->getNumPlayers(); ++i) { + if (i + 1 == ps->GetPlayer()->GetNumber()) { + for (int j = 0; j < g.aggPtr->getNumActions(i); ++j) { + s[g.aggPtr->firstAction(i) + j] = (T)0; } - s.at(g.aggPtr->firstAction(i)+ ps->GetNumber()-1) = (T) 1; + s.at(g.aggPtr->firstAction(i) + ps->GetNumber() - 1) = (T)1; } else { - for (int j=0;jgetNumActions(i);++j){ - GameStrategy strategy = this->m_support.GetGame()->GetPlayer(i+1)->GetStrategy(j+1); - const int &ind=this->m_support.m_profileIndex[strategy->GetId()]; - s[g.aggPtr->firstAction(i)+j]= (ind==-1)?(T)0:this->m_probs[ind]; + for (int j = 0; j < g.aggPtr->getNumActions(i); ++j) { + GameStrategy strategy = this->m_support.GetGame()->GetPlayer(i + 1)->GetStrategy(j + 1); + const int &ind = this->m_support.m_profileIndex[strategy->GetId()]; + s[g.aggPtr->firstAction(i) + j] = (ind == -1) ? (T)0 : this->m_probs[ind]; } } } - return (T) g.aggPtr->getMixedPayoff(pl-1, s); + return (T)g.aggPtr->getMixedPayoff(pl - 1, s); } template -T AGGMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &ps1, const GameStrategy &ps2) const +T AGGMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &ps1, + const GameStrategy &ps2) const { GamePlayerRep *player1 = ps1->GetPlayer(); GamePlayerRep *player2 = ps2->GetPlayer(); - if (player1 == player2) return (T) 0; + if (player1 == player2) { + return (T)0; + } auto &g = dynamic_cast(*(this->m_support.GetGame())); - std::vector s (g.aggPtr->getNumActions()); - for (int i=0;igetNumPlayers();++i){ - if(i+1 == player1->GetNumber()){ - for (int j=0;jgetNumActions(i);++j){ - s[g.aggPtr->firstAction(i)+j] = (T) 0; + std::vector s(g.aggPtr->getNumActions()); + for (int i = 0; i < g.aggPtr->getNumPlayers(); ++i) { + if (i + 1 == player1->GetNumber()) { + for (int j = 0; j < g.aggPtr->getNumActions(i); ++j) { + s[g.aggPtr->firstAction(i) + j] = (T)0; } - s.at(g.aggPtr->firstAction(i)+ ps1->GetNumber()-1) = (T) 1; + s.at(g.aggPtr->firstAction(i) + ps1->GetNumber() - 1) = (T)1; } - else if(i+1 == player2->GetNumber()){ - for (int j=0;jgetNumActions(i);++j){ - s[g.aggPtr->firstAction(i)+j] = (T) 0; + else if (i + 1 == player2->GetNumber()) { + for (int j = 0; j < g.aggPtr->getNumActions(i); ++j) { + s[g.aggPtr->firstAction(i) + j] = (T)0; } - s.at(g.aggPtr->firstAction(i)+ ps2->GetNumber()-1) = (T) 1; + s.at(g.aggPtr->firstAction(i) + ps2->GetNumber() - 1) = (T)1; } else { - for (int j=0;jgetNumActions(i);++j){ - GameStrategy strategy = this->m_support.GetGame()->GetPlayer(i+1)->GetStrategy(j+1); - const int &ind=this->m_support.m_profileIndex[strategy->GetId()]; - s[g.aggPtr->firstAction(i)+j]= (ind==-1)?(T)0:this->m_probs[ind]; + for (int j = 0; j < g.aggPtr->getNumActions(i); ++j) { + GameStrategy strategy = this->m_support.GetGame()->GetPlayer(i + 1)->GetStrategy(j + 1); + const int &ind = this->m_support.m_profileIndex[strategy->GetId()]; + s[g.aggPtr->firstAction(i) + j] = (ind == -1) ? (T)0 : this->m_probs[ind]; } } } - return (T) g.aggPtr->getMixedPayoff(pl-1, s); + return (T)g.aggPtr->getMixedPayoff(pl - 1, s); } template class AGGMixedStrategyProfileRep; template class AGGMixedStrategyProfileRep; - //------------------------------------------------------------------------ // GameAGGRep: Lifecycle //------------------------------------------------------------------------ -GameAGGRep::GameAGGRep(std::shared_ptr p_aggPtr) - : aggPtr(p_aggPtr) +GameAGGRep::GameAGGRep(std::shared_ptr p_aggPtr) : aggPtr(p_aggPtr) { for (int pl = 1; pl <= aggPtr->getNumPlayers(); pl++) { - m_players.push_back(new GamePlayerRep(this, pl, aggPtr->getNumActions(pl-1))); + m_players.push_back(new GamePlayerRep(this, pl, aggPtr->getNumActions(pl - 1))); m_players[pl]->m_label = lexical_cast(pl); for (int st = 1; st <= m_players[pl]->NumStrategies(); st++) { m_players[pl]->m_strategies[st]->SetLabel(lexical_cast(st)); @@ -190,7 +187,8 @@ GameAGGRep::GameAGGRep(std::shared_ptr p_aggPtr) } for (int pl = 1, id = 1; pl <= m_players.Length(); pl++) { for (int st = 1; st <= m_players[pl]->m_strategies.Length(); - m_players[pl]->m_strategies[st++]->m_id = id++); + m_players[pl]->m_strategies[st++]->m_id = id++) + ; } } @@ -239,23 +237,23 @@ PureStrategyProfile GameAGGRep::NewPureStrategyProfile() const MixedStrategyProfile GameAGGRep::NewMixedStrategyProfile(double) const { - return MixedStrategyProfile( - new AGGMixedStrategyProfileRep(StrategySupportProfile(const_cast(this))) - ); + return MixedStrategyProfile(new AGGMixedStrategyProfileRep( + StrategySupportProfile(const_cast(this)))); } MixedStrategyProfile GameAGGRep::NewMixedStrategyProfile(const Rational &) const { - return MixedStrategyProfile( - new AGGMixedStrategyProfileRep(StrategySupportProfile(const_cast(this))) - ); + return MixedStrategyProfile(new AGGMixedStrategyProfileRep( + StrategySupportProfile(const_cast(this)))); } -MixedStrategyProfile GameAGGRep::NewMixedStrategyProfile(double, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameAGGRep::NewMixedStrategyProfile(double, const StrategySupportProfile &spt) const { return MixedStrategyProfile(new AGGMixedStrategyProfileRep(spt)); } -MixedStrategyProfile GameAGGRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameAGGRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &spt) const { return MixedStrategyProfile(new AGGMixedStrategyProfileRep(spt)); } @@ -291,8 +289,7 @@ bool GameAGGRep::IsConstSum() const // GameAGGRep: Writing data files //------------------------------------------------------------------------ -void GameAGGRep::Write(std::ostream &p_stream, - const std::string &p_format /*="native"*/) const +void GameAGGRep::Write(std::ostream &p_stream, const std::string &p_format /*="native"*/) const { if (p_format == "native" || p_format == "agg") { WriteAggFile(p_stream); @@ -316,9 +313,8 @@ void GameAGGRep::WriteAggFile(std::ostream &s) const } s << std::endl; for (int i = 0; i < aggPtr->getNumPlayers(); i++) { - std::copy(aggPtr->getActionSet(i).begin(), - aggPtr->getActionSet(i).end(), - std::ostream_iterator(s," ")); + std::copy(aggPtr->getActionSet(i).begin(), aggPtr->getActionSet(i).end(), + std::ostream_iterator(s, " ")); s << std::endl; } aggPtr->printActionGraph(s); @@ -329,14 +325,12 @@ void GameAGGRep::WriteAggFile(std::ostream &s) const // payoffs for (int i = 0; i < aggPtr->getNumActionNodes(); i++) { - s << "1" << std::endl; //type of payoff output + s << "1" << std::endl; // type of payoff output aggPtr->printPayoffs(s, i); s << std::endl; } } -Game GameAGGRep::ReadAggFile(std::istream& in){ - return new GameAGGRep(agg::AGG::makeAGG(in)); -} +Game GameAGGRep::ReadAggFile(std::istream &in) { return new GameAGGRep(agg::AGG::makeAGG(in)); } -} // end namespace Gambit +} // end namespace Gambit diff --git a/src/games/gameagg.h b/src/games/gameagg.h index 0fd2399d2..69d7ac83b 100644 --- a/src/games/gameagg.h +++ b/src/games/gameagg.h @@ -44,7 +44,8 @@ class GameAGGRep : public GameRep { /// Create a game from a serialized file in AGG format static Game ReadAggFile(std::istream &); /// Destructor - ~GameAGGRep() override { + ~GameAGGRep() override + { for (auto player : m_players) { player->Invalidate(); } @@ -65,19 +66,19 @@ class GameAGGRep : public GameRep { /// Gets the i'th strategy in the game, numbered globally GameStrategy GetStrategy(int p_index) const override; /// Returns the total number of actions in the game - int BehavProfileLength() const override { throw UndefinedException(); } + int BehavProfileLength() const override { throw UndefinedException(); } /// Returns the total number of strategies in the game - int MixedProfileLength() const override - { return aggPtr->getNumActions(); } - int NumStrategyContingencies() const override - { throw UndefinedException(); } + int MixedProfileLength() const override { return aggPtr->getNumActions(); } + int NumStrategyContingencies() const override { throw UndefinedException(); } //@} PureStrategyProfile NewPureStrategyProfile() const override; MixedStrategyProfile NewMixedStrategyProfile(double) const override; MixedStrategyProfile NewMixedStrategyProfile(const Rational &) const override; - MixedStrategyProfile NewMixedStrategyProfile(double, const StrategySupportProfile &) const override; - MixedStrategyProfile NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &) const override; + MixedStrategyProfile + NewMixedStrategyProfile(double, const StrategySupportProfile &) const override; + MixedStrategyProfile + NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &) const override; /// @name Players //@{ @@ -86,80 +87,72 @@ class GameAGGRep : public GameRep { /// Returns the pl'th player in the game GamePlayer GetPlayer(int pl) const override { return m_players[pl]; } /// Returns the chance (nature) player - GamePlayer GetChance() const override { throw UndefinedException(); } + GamePlayer GetChance() const override { throw UndefinedException(); } /// Creates a new player in the game, with no moves - GamePlayer NewPlayer() override { throw UndefinedException(); } + GamePlayer NewPlayer() override { throw UndefinedException(); } //@} /// @name Information sets //@{ /// Returns the iset'th information set in the game (numbered globally) - GameInfoset GetInfoset(int iset) const override - { throw UndefinedException(); } + GameInfoset GetInfoset(int iset) const override { throw UndefinedException(); } /// Returns the set of information sets in the game - Array GetInfosets() const override - { throw UndefinedException(); } + Array GetInfosets() const override { throw UndefinedException(); } /// Returns an array with the number of information sets per personal player - Array NumInfosets() const override - { throw UndefinedException(); } + Array NumInfosets() const override { throw UndefinedException(); } /// Returns the act'th action in the game (numbered globally) - GameAction GetAction(int act) const override - { throw UndefinedException(); } + GameAction GetAction(int act) const override { throw UndefinedException(); } //@} - /// @name Outcomes //@{ /// Returns the number of outcomes defined in the game - int NumOutcomes() const override { throw UndefinedException(); } + int NumOutcomes() const override { throw UndefinedException(); } /// Returns the index'th outcome defined in the game - GameOutcome GetOutcome(int index) const override - { throw UndefinedException(); } + GameOutcome GetOutcome(int index) const override { throw UndefinedException(); } /// Creates a new outcome in the game - GameOutcome NewOutcome() override { throw UndefinedException(); } + GameOutcome NewOutcome() override { throw UndefinedException(); } /// Deletes the specified outcome from the game - void DeleteOutcome(const GameOutcome &) override - { throw UndefinedException(); } + void DeleteOutcome(const GameOutcome &) override { throw UndefinedException(); } //@} /// @name Nodes //@{ /// Returns the root node of the game - GameNode GetRoot() const override { throw UndefinedException(); } + GameNode GetRoot() const override { throw UndefinedException(); } /// Returns the number of nodes in the game - int NumNodes() const override { throw UndefinedException(); } + int NumNodes() const override { throw UndefinedException(); } //@} /// @name General data access //@{ bool IsTree() const override { return false; } bool IsAgg() const override { return true; } - bool IsPerfectRecall(GameInfoset &, GameInfoset &) const override - { return true; } + bool IsPerfectRecall(GameInfoset &, GameInfoset &) const override { return true; } bool IsConstSum() const override; /// Returns the smallest payoff in any outcome of the game - Rational GetMinPayoff(int) const override - { return Rational(aggPtr->getMinPayoff()); } + Rational GetMinPayoff(int) const override { return Rational(aggPtr->getMinPayoff()); } /// Returns the largest payoff in any outcome of the game - Rational GetMaxPayoff(int) const override - { return Rational(aggPtr->getMaxPayoff()); } + Rational GetMaxPayoff(int) const override { return Rational(aggPtr->getMaxPayoff()); } //@} /// @name Modification //@{ - Game SetChanceProbs(const GameInfoset &, const Array &) override { throw UndefinedException(); } + Game SetChanceProbs(const GameInfoset &, const Array &) override + { + throw UndefinedException(); + } //@} /// @name Writing data files //@{ /// Write the game to a savefile in the specified format. - void Write(std::ostream &p_stream, - const std::string &p_format="native") const override; + void Write(std::ostream &p_stream, const std::string &p_format = "native") const override; virtual void WriteAggFile(std::ostream &) const; //@} }; -} // namespace Gambit +} // namespace Gambit -#endif // GAMEAGG_H +#endif // GAMEAGG_H diff --git a/src/games/gamebagg.cc b/src/games/gamebagg.cc index 048aaae73..5bf096517 100644 --- a/src/games/gamebagg.cc +++ b/src/games/gamebagg.cc @@ -33,15 +33,11 @@ namespace Gambit { class BAGGPureStrategyProfileRep : public PureStrategyProfileRep { public: - explicit BAGGPureStrategyProfileRep(const Game &p_game) - : PureStrategyProfileRep(p_game) { } - PureStrategyProfileRep *Copy() const override - { return new BAGGPureStrategyProfileRep(*this); } + explicit BAGGPureStrategyProfileRep(const Game &p_game) : PureStrategyProfileRep(p_game) {} + PureStrategyProfileRep *Copy() const override { return new BAGGPureStrategyProfileRep(*this); } void SetStrategy(const GameStrategy &) override; - GameOutcome GetOutcome() const override - { throw UndefinedException(); } - void SetOutcome(GameOutcome p_outcome) override - { throw UndefinedException(); } + GameOutcome GetOutcome() const override { throw UndefinedException(); } + void SetOutcome(GameOutcome p_outcome) override { throw UndefinedException(); } Rational GetPayoff(int pl) const override; Rational GetStrategyValue(const GameStrategy &) const override; }; @@ -60,42 +56,42 @@ Rational BAGGPureStrategyProfileRep::GetPayoff(int pl) const std::shared_ptr baggPtr = dynamic_cast(*m_nfg).baggPtr; std::vector s(m_nfg->NumPlayers()); for (int i = 1; i <= m_nfg->NumPlayers(); i++) { - s[i-1] = m_profile[i]->GetNumber() - 1; + s[i - 1] = m_profile[i]->GetNumber() - 1; } int bp = dynamic_cast(*m_nfg).agent2baggPlayer[pl]; - int tp = pl - 1 - baggPtr->typeOffset[bp-1]; - return Rational(baggPtr->getPurePayoff(bp-1,tp,s)); + int tp = pl - 1 - baggPtr->typeOffset[bp - 1]; + return Rational(baggPtr->getPurePayoff(bp - 1, tp, s)); } -Rational -BAGGPureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const +Rational BAGGPureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const { int player = p_strategy->GetPlayer()->GetNumber(); std::shared_ptr baggPtr = dynamic_cast(*m_nfg).baggPtr; std::vector s(m_nfg->NumPlayers()); - for (int i= 1; i <= m_nfg->NumPlayers(); i++) { - s[i-1] = m_profile[i]->GetNumber() - 1; + for (int i = 1; i <= m_nfg->NumPlayers(); i++) { + s[i - 1] = m_profile[i]->GetNumber() - 1; } - s[player-1] = p_strategy->GetNumber() - 1; + s[player - 1] = p_strategy->GetNumber() - 1; int bp = dynamic_cast(*m_nfg).agent2baggPlayer[player]; - int tp = player - 1 - baggPtr->typeOffset[bp-1]; - return Rational(baggPtr->getPurePayoff(bp-1,tp,s)); + int tp = player - 1 - baggPtr->typeOffset[bp - 1]; + return Rational(baggPtr->getPurePayoff(bp - 1, tp, s)); } //======================================================================== // class BAGGMixedStrategyProfileRep //======================================================================== -template class BAGGMixedStrategyProfileRep - : public MixedStrategyProfileRep { +template class BAGGMixedStrategyProfileRep : public MixedStrategyProfileRep { public: explicit BAGGMixedStrategyProfileRep(const StrategySupportProfile &p_support) : MixedStrategyProfileRep(p_support) - { } + { + } ~BAGGMixedStrategyProfileRep() override = default; - MixedStrategyProfileRep *Copy() const override { + MixedStrategyProfileRep *Copy() const override + { return new BAGGMixedStrategyProfileRep(*this); } T GetPayoff(int pl) const override; @@ -103,103 +99,112 @@ template class BAGGMixedStrategyProfileRep T GetPayoffDeriv(int pl, const GameStrategy &, const GameStrategy &) const override; }; -template -T BAGGMixedStrategyProfileRep::GetPayoff(int pl) const +template T BAGGMixedStrategyProfileRep::GetPayoff(int pl) const { auto &g = dynamic_cast(*(this->m_support.GetGame())); - std::vector s (g.MixedProfileLength()); - Array ns=g.NumStrategies(); - int bplayer=-1,btype=-1; - for (int i=0,offs=0;igetNumPlayers();++i) - for (int tp=0;tpgetNumTypes(i);++tp) { - if (pl == g.baggPtr->typeOffset[i]+tp+1){ - bplayer=i; - btype=tp; + std::vector s(g.MixedProfileLength()); + Array ns = g.NumStrategies(); + int bplayer = -1, btype = -1; + for (int i = 0, offs = 0; i < g.baggPtr->getNumPlayers(); ++i) { + for (int tp = 0; tp < g.baggPtr->getNumTypes(i); ++tp) { + if (pl == g.baggPtr->typeOffset[i] + tp + 1) { + bplayer = i; + btype = tp; } - for (int j=0;jtypeOffset[i]+tp+1];++j,++offs){ - GameStrategy strategy = this->m_support.GetGame()->GetPlayer(g.baggPtr->typeOffset[i]+tp+1)->GetStrategy(j+1); - const int &ind=this->m_support.m_profileIndex[strategy->GetId()]; - s.at(offs)= (ind==-1)?(T)0:this->m_probs[ind]; + for (int j = 0; j < ns[g.baggPtr->typeOffset[i] + tp + 1]; ++j, ++offs) { + GameStrategy strategy = this->m_support.GetGame() + ->GetPlayer(g.baggPtr->typeOffset[i] + tp + 1) + ->GetStrategy(j + 1); + const int &ind = this->m_support.m_profileIndex[strategy->GetId()]; + s.at(offs) = (ind == -1) ? (T)0 : this->m_probs[ind]; } } - return (T) g.baggPtr->getMixedPayoff(bplayer,btype, s); + } + return (T)g.baggPtr->getMixedPayoff(bplayer, btype, s); } template T BAGGMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &ps) const { auto &g = dynamic_cast(*(this->m_support.GetGame())); - std::vector s (g.MixedProfileLength()); - int bplayer=-1,btype=-1; - for (int i=0;igetNumPlayers();++i){ - for(int tp=0; tpgetNumTypes(i);++tp){ - if(pl == g.baggPtr->typeOffset[i]+tp+1){ - bplayer=i; - btype=tp; + std::vector s(g.MixedProfileLength()); + int bplayer = -1, btype = -1; + for (int i = 0; i < g.baggPtr->getNumPlayers(); ++i) { + for (int tp = 0; tp < g.baggPtr->getNumTypes(i); ++tp) { + if (pl == g.baggPtr->typeOffset[i] + tp + 1) { + bplayer = i; + btype = tp; } - if(g.baggPtr->typeOffset[i]+tp+1 == ps->GetPlayer()->GetNumber()){ - for (unsigned int j=0;jtypeActionSets.at(i).at(tp).size();++j){ - s.at(g.baggPtr->firstAction(i,tp)+j) = 0; + if (g.baggPtr->typeOffset[i] + tp + 1 == ps->GetPlayer()->GetNumber()) { + for (unsigned int j = 0; j < g.baggPtr->typeActionSets.at(i).at(tp).size(); ++j) { + s.at(g.baggPtr->firstAction(i, tp) + j) = 0; } - s.at(g.baggPtr->firstAction(i,tp)+ ps->GetNumber()-1) = 1; + s.at(g.baggPtr->firstAction(i, tp) + ps->GetNumber() - 1) = 1; } else { - for (int j=0;jgetNumActions(i,tp);++j){ - GameStrategy strategy = this->m_support.GetGame()->GetPlayer(g.baggPtr->typeOffset[i]+tp+1)->GetStrategy(j+1); - const int &ind=this->m_support.m_profileIndex[strategy->GetId()]; - s.at(g.baggPtr->firstAction(i,tp)+j)= (ind==-1)?Rational(0):this->m_probs[ind]; + for (int j = 0; j < g.baggPtr->getNumActions(i, tp); ++j) { + GameStrategy strategy = this->m_support.GetGame() + ->GetPlayer(g.baggPtr->typeOffset[i] + tp + 1) + ->GetStrategy(j + 1); + const int &ind = this->m_support.m_profileIndex[strategy->GetId()]; + s.at(g.baggPtr->firstAction(i, tp) + j) = (ind == -1) ? Rational(0) : this->m_probs[ind]; } } } } - return (T) g.baggPtr->getMixedPayoff(bplayer,btype, s); + return (T)g.baggPtr->getMixedPayoff(bplayer, btype, s); } template -T BAGGMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &ps1, const GameStrategy &ps2) const +T BAGGMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &ps1, + const GameStrategy &ps2) const { GamePlayerRep *player1 = ps1->GetPlayer(); GamePlayerRep *player2 = ps2->GetPlayer(); - if (player1 == player2) return (T) 0; + if (player1 == player2) { + return (T)0; + } auto &g = dynamic_cast(*(this->m_support.GetGame())); - std::vector s (g.MixedProfileLength()); - int bplayer=-1,btype=-1; - for (int i=0;igetNumPlayers();++i){ - for(int tp=0;tpgetNumTypes(i);++tp){ - if(pl == g.baggPtr->typeOffset[i]+tp+1){ - bplayer=i; - btype=tp; + std::vector s(g.MixedProfileLength()); + int bplayer = -1, btype = -1; + for (int i = 0; i < g.baggPtr->getNumPlayers(); ++i) { + for (int tp = 0; tp < g.baggPtr->getNumTypes(i); ++tp) { + if (pl == g.baggPtr->typeOffset[i] + tp + 1) { + bplayer = i; + btype = tp; } - if(g.baggPtr->typeOffset[i]+tp+1 == player1->GetNumber()){ - for (unsigned int j=0;jtypeActionSets.at(i).at(tp).size();++j){ - s.at(g.baggPtr->firstAction(i,tp)+j) = 0; + if (g.baggPtr->typeOffset[i] + tp + 1 == player1->GetNumber()) { + for (unsigned int j = 0; j < g.baggPtr->typeActionSets.at(i).at(tp).size(); ++j) { + s.at(g.baggPtr->firstAction(i, tp) + j) = 0; } - s.at(g.baggPtr->firstAction(i,tp)+ ps1->GetNumber()-1) = 1; + s.at(g.baggPtr->firstAction(i, tp) + ps1->GetNumber() - 1) = 1; } - else if(g.baggPtr->typeOffset[i]+tp+1 == player2->GetNumber()){ - for (int j=0;jgetNumActions(i,tp);++j){ - s.at(g.baggPtr->firstAction(i,tp)+j) = 0; + else if (g.baggPtr->typeOffset[i] + tp + 1 == player2->GetNumber()) { + for (int j = 0; j < g.baggPtr->getNumActions(i, tp); ++j) { + s.at(g.baggPtr->firstAction(i, tp) + j) = 0; } - s.at(g.baggPtr->firstAction(i,tp)+ ps2->GetNumber()-1) = 1; + s.at(g.baggPtr->firstAction(i, tp) + ps2->GetNumber() - 1) = 1; } else { - for (unsigned int j=0;jtypeActionSets.at(i).at(tp).size();++j){ - GameStrategy strategy = this->m_support.GetGame()->GetPlayer(g.baggPtr->typeOffset[i]+tp+1)->GetStrategy(j+1); - const int &ind=this->m_support.m_profileIndex[strategy->GetId()]; - s.at(g.baggPtr->firstAction(i,tp)+j)= static_cast((ind==-1)?T(0):this->m_probs[ind]); + for (unsigned int j = 0; j < g.baggPtr->typeActionSets.at(i).at(tp).size(); ++j) { + GameStrategy strategy = this->m_support.GetGame() + ->GetPlayer(g.baggPtr->typeOffset[i] + tp + 1) + ->GetStrategy(j + 1); + const int &ind = this->m_support.m_profileIndex[strategy->GetId()]; + s.at(g.baggPtr->firstAction(i, tp) + j) = + static_cast((ind == -1) ? T(0) : this->m_probs[ind]); } } } } - return (T) g.baggPtr->getMixedPayoff(bplayer,btype, s); + return (T)g.baggPtr->getMixedPayoff(bplayer, btype, s); } template class BAGGMixedStrategyProfileRep; template class BAGGMixedStrategyProfileRep; - //------------------------------------------------------------------------ // GameBAGGRep: Lifecycle //------------------------------------------------------------------------ @@ -209,19 +214,19 @@ GameBAGGRep::GameBAGGRep(std::shared_ptr _baggPtr) { int k = 1; for (int pl = 1; pl <= baggPtr->getNumPlayers(); pl++) { - for (int j = 0; j < baggPtr->getNumTypes(pl-1); j++,k++) { - m_players.push_back(new GamePlayerRep(this, k, - baggPtr->getNumActions(pl-1, j))); + for (int j = 0; j < baggPtr->getNumTypes(pl - 1); j++, k++) { + m_players.push_back(new GamePlayerRep(this, k, baggPtr->getNumActions(pl - 1, j))); m_players[k]->m_label = lexical_cast(k); agent2baggPlayer[k] = pl; for (int st = 1; st <= m_players[k]->NumStrategies(); st++) { - m_players[k]->m_strategies[st]->SetLabel(lexical_cast(st)); + m_players[k]->m_strategies[st]->SetLabel(lexical_cast(st)); } } } for (int pl = 1, id = 1; pl <= m_players.Length(); pl++) { for (int st = 1; st <= m_players[pl]->m_strategies.Length(); - m_players[pl]->m_strategies[st++]->m_id = id++); + m_players[pl]->m_strategies[st++]->m_id = id++) + ; } } @@ -255,7 +260,6 @@ int GameBAGGRep::MixedProfileLength() const return res; } - PureStrategyProfile GameBAGGRep::NewPureStrategyProfile() const { return PureStrategyProfile(new BAGGPureStrategyProfileRep(const_cast(this))); @@ -263,23 +267,23 @@ PureStrategyProfile GameBAGGRep::NewPureStrategyProfile() const MixedStrategyProfile GameBAGGRep::NewMixedStrategyProfile(double) const { - return MixedStrategyProfile( - new BAGGMixedStrategyProfileRep(StrategySupportProfile(const_cast(this))) - ); + return MixedStrategyProfile(new BAGGMixedStrategyProfileRep( + StrategySupportProfile(const_cast(this)))); } MixedStrategyProfile GameBAGGRep::NewMixedStrategyProfile(const Rational &) const { - return MixedStrategyProfile( - new BAGGMixedStrategyProfileRep(StrategySupportProfile(const_cast(this))) - ); + return MixedStrategyProfile(new BAGGMixedStrategyProfileRep( + StrategySupportProfile(const_cast(this)))); } -MixedStrategyProfile GameBAGGRep::NewMixedStrategyProfile(double, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameBAGGRep::NewMixedStrategyProfile(double, const StrategySupportProfile &spt) const { return MixedStrategyProfile(new BAGGMixedStrategyProfileRep(spt)); } -MixedStrategyProfile GameBAGGRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameBAGGRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &spt) const { return MixedStrategyProfile(new BAGGMixedStrategyProfileRep(spt)); } @@ -288,8 +292,7 @@ MixedStrategyProfile GameBAGGRep::NewMixedStrategyProfile(const Ration // GameBAGGRep: Writing data files //------------------------------------------------------------------------ -void GameBAGGRep::Write(std::ostream &p_stream, - const std::string &p_format /*="native"*/) const +void GameBAGGRep::Write(std::ostream &p_stream, const std::string &p_format /*="native"*/) const { if (p_format == "native" || p_format == "bagg") { WriteBaggFile(p_stream); @@ -302,14 +305,11 @@ void GameBAGGRep::Write(std::ostream &p_stream, } } -void GameBAGGRep::WriteBaggFile(std::ostream &s) const -{ - s << (*baggPtr); -} +void GameBAGGRep::WriteBaggFile(std::ostream &s) const { s << (*baggPtr); } Game GameBAGGRep::ReadBaggFile(std::istream &in) { return new GameBAGGRep(agg::BAGG::makeBAGG(in)); } -} // end namespace Gambit +} // end namespace Gambit diff --git a/src/games/gamebagg.h b/src/games/gamebagg.h index 28b0eab7d..83bd38c98 100644 --- a/src/games/gamebagg.h +++ b/src/games/gamebagg.h @@ -45,7 +45,8 @@ class GameBAGGRep : public GameRep { /// Create a game from a serialized file in BAGG format static Game ReadBaggFile(std::istream &); /// Destructor - ~GameBAGGRep() override { + ~GameBAGGRep() override + { for (auto player : m_players) { player->Invalidate(); } @@ -63,14 +64,11 @@ class GameBAGGRep : public GameRep { /// The number of strategies for each player Array NumStrategies() const override; /// Gets the i'th strategy in the game, numbered globally - GameStrategy GetStrategy(int p_index) const override - { throw UndefinedException(); } + GameStrategy GetStrategy(int p_index) const override { throw UndefinedException(); } /// Returns the number of strategy contingencies in the game - int NumStrategyContingencies() const override - { throw UndefinedException(); } + int NumStrategyContingencies() const override { throw UndefinedException(); } /// Returns the total number of actions in the game - int BehavProfileLength() const override - { throw UndefinedException(); } + int BehavProfileLength() const override { throw UndefinedException(); } /// Returns the total number of strategies in the game int MixedProfileLength() const override; //@} @@ -78,8 +76,10 @@ class GameBAGGRep : public GameRep { PureStrategyProfile NewPureStrategyProfile() const override; MixedStrategyProfile NewMixedStrategyProfile(double) const override; MixedStrategyProfile NewMixedStrategyProfile(const Rational &) const override; - MixedStrategyProfile NewMixedStrategyProfile(double, const StrategySupportProfile&) const override; - MixedStrategyProfile NewMixedStrategyProfile(const Rational &, const StrategySupportProfile&) const override; + MixedStrategyProfile + NewMixedStrategyProfile(double, const StrategySupportProfile &) const override; + MixedStrategyProfile + NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &) const override; /// @name Players //@{ @@ -88,42 +88,33 @@ class GameBAGGRep : public GameRep { /// Returns the pl'th player in the game GamePlayer GetPlayer(int pl) const override { return m_players[pl]; } /// Returns the chance (nature) player - GamePlayer GetChance() const override - { throw UndefinedException(); } + GamePlayer GetChance() const override { throw UndefinedException(); } /// Creates a new player in the game, with no moves - GamePlayer NewPlayer() override - { throw UndefinedException(); } + GamePlayer NewPlayer() override { throw UndefinedException(); } //@} /// @name Information sets //@{ /// Returns the iset'th information set in the game (numbered globally) - GameInfoset GetInfoset(int iset) const override - { throw UndefinedException(); } + GameInfoset GetInfoset(int iset) const override { throw UndefinedException(); } /// Returns the set of information sets in the game - Array GetInfosets() const override - { throw UndefinedException(); } + Array GetInfosets() const override { throw UndefinedException(); } /// Returns an array with the number of information sets per personal player - Array NumInfosets() const override - { throw UndefinedException(); } + Array NumInfosets() const override { throw UndefinedException(); } /// Returns the act'th action in the game (numbered globally) - GameAction GetAction(int act) const override - { throw UndefinedException(); } + GameAction GetAction(int act) const override { throw UndefinedException(); } //@} - /// @name Outcomes //@{ /// Returns the number of outcomes defined in the game - int NumOutcomes() const override { throw UndefinedException(); } + int NumOutcomes() const override { throw UndefinedException(); } /// Returns the index'th outcome defined in the game - GameOutcome GetOutcome(int index) const override - { throw UndefinedException(); } + GameOutcome GetOutcome(int index) const override { throw UndefinedException(); } /// Creates a new outcome in the game - GameOutcome NewOutcome() override { throw UndefinedException(); } + GameOutcome NewOutcome() override { throw UndefinedException(); } /// Deletes the specified outcome from the game - void DeleteOutcome(const GameOutcome &) override - { throw UndefinedException(); } + void DeleteOutcome(const GameOutcome &) override { throw UndefinedException(); } //@} /// @name Nodes @@ -131,15 +122,14 @@ class GameBAGGRep : public GameRep { /// Returns the root node of the game GameNode GetRoot() const override { throw UndefinedException(); } /// Returns the number of nodes in the game - int NumNodes() const override { throw UndefinedException(); } + int NumNodes() const override { throw UndefinedException(); } //@} /// @name General data access //@{ bool IsTree() const override { return false; } virtual bool IsBagg() const { return true; } - bool IsPerfectRecall(GameInfoset &, GameInfoset &) const override - { return true; } + bool IsPerfectRecall(GameInfoset &, GameInfoset &) const override { return true; } bool IsConstSum() const override { throw UndefinedException(); } /// Returns the smallest payoff in any outcome of the game Rational GetMinPayoff(int) const override { return Rational(baggPtr->getMinPayoff()); } @@ -150,19 +140,20 @@ class GameBAGGRep : public GameRep { /// @name Writing data files //@{ /// Write the game to a savefile in the specified format. - void Write(std::ostream &p_stream, - const std::string &p_format="native") const override; - void WriteNfgFile(std::ostream &) const override - { throw UndefinedException(); } + void Write(std::ostream &p_stream, const std::string &p_format = "native") const override; + void WriteNfgFile(std::ostream &) const override { throw UndefinedException(); } virtual void WriteBaggFile(std::ostream &) const; //@} /// @name Modification //@{ - Game SetChanceProbs(const GameInfoset &, const Array &) override { throw UndefinedException(); } + Game SetChanceProbs(const GameInfoset &, const Array &) override + { + throw UndefinedException(); + } //@} }; } // end namespace Gambit -#endif // GAMEBAGG_H +#endif // GAMEBAGG_H diff --git a/src/games/gameexpl.cc b/src/games/gameexpl.cc index c3bc5e788..fca6069ab 100644 --- a/src/games/gameexpl.cc +++ b/src/games/gameexpl.cc @@ -120,7 +120,7 @@ GameStrategy GameExplicitRep::GetStrategy(int p_index) const for (int pl = 1, i = 1; pl <= m_players.Length(); pl++) { for (int st = 1; st <= m_players[pl]->m_strategies.Length(); st++, i++) { if (p_index == i) { - return m_players[pl]->m_strategies[st]; + return m_players[pl]->m_strategies[st]; } } } @@ -130,22 +130,18 @@ GameStrategy GameExplicitRep::GetStrategy(int p_index) const int GameExplicitRep::NumStrategyContingencies() const { const_cast(this)->BuildComputedValues(); - return std::accumulate( - m_players.begin(), m_players.end(), 1, - [](int ncont, GamePlayerRep *p) { return ncont * p->m_strategies.size(); } - ); + return std::accumulate(m_players.begin(), m_players.end(), 1, [](int ncont, GamePlayerRep *p) { + return ncont * p->m_strategies.size(); + }); } int GameExplicitRep::MixedProfileLength() const { const_cast(this)->BuildComputedValues(); - return std::accumulate( - m_players.begin(), m_players.end(), 0, - [](int size, GamePlayerRep *p) { return size + p->m_strategies.size(); } - ); + return std::accumulate(m_players.begin(), m_players.end(), 0, + [](int size, GamePlayerRep *p) { return size + p->m_strategies.size(); }); } - //------------------------------------------------------------------------ // GameExplicitRep: Outcomes //------------------------------------------------------------------------ @@ -161,14 +157,12 @@ GameOutcome GameExplicitRep::NewOutcome() //------------------------------------------------------------------------ void GameExplicitRep::Write(std::ostream &p_stream, - const std::string &p_format /*="native"*/) const + const std::string &p_format /*="native"*/) const { - if (p_format == "efg" || - (p_format == "native" && IsTree())) { + if (p_format == "efg" || (p_format == "native" && IsTree())) { WriteEfgFile(p_stream); } - else if (p_format == "nfg" || - (p_format == "native" && !IsTree())) { + else if (p_format == "nfg" || (p_format == "native" && !IsTree())) { WriteNfgFile(p_stream); } else { @@ -176,7 +170,4 @@ void GameExplicitRep::Write(std::ostream &p_stream, } } - - - -} // end namespace Gambit +} // end namespace Gambit diff --git a/src/games/gameexpl.h b/src/games/gameexpl.h index c7716aeb7..0e30ebb56 100644 --- a/src/games/gameexpl.h +++ b/src/games/gameexpl.h @@ -29,6 +29,7 @@ namespace Gambit { class GameExplicitRep : public GameRep { template friend class MixedStrategyProfile; + protected: Array m_players; Array m_outcomes; @@ -79,11 +80,10 @@ class GameExplicitRep : public GameRep { /// @name Writing data files //@{ - void Write(std::ostream &p_stream, - const std::string &p_format="native") const override; + void Write(std::ostream &p_stream, const std::string &p_format = "native") const override; //@} }; -} +} // namespace Gambit -#endif // GAMEEXPL_H +#endif // GAMEEXPL_H diff --git a/src/games/gameobject.h b/src/games/gameobject.h index 1f847d38d..7abac8336 100644 --- a/src/games/gameobject.h +++ b/src/games/gameobject.h @@ -43,8 +43,7 @@ class GameObject { /// @name Lifecycle //@{ /// Constructor; initializes reference count - GameObject() : m_refCount(0), m_valid(true) - {} + GameObject() : m_refCount(0), m_valid(true) {} /// Destructor virtual ~GameObject() = default; @@ -53,31 +52,38 @@ class GameObject { /// @name Validation //@{ /// Is the object still valid? - bool IsValid() const - { return m_valid; } + bool IsValid() const { return m_valid; } /// Invalidate the object; delete if not referenced elsewhere void Invalidate() - { if (!m_refCount) delete this; else m_valid = false; } + { + if (!m_refCount) { + delete this; + } + else { + m_valid = false; + } + } //@} /// @name Reference counting //@{ /// Increment the reference count - void IncRef() - { m_refCount++; } + void IncRef() { m_refCount++; } /// Decrement the reference count; delete if reference count is zero. void DecRef() - { if (!--m_refCount && !m_valid) delete this; } + { + if (!--m_refCount && !m_valid) { + delete this; + } + } /// Returns the reference count - int RefCount() const - { return m_refCount; } + int RefCount() const { return m_refCount; } //@} }; - class BaseGameRep { protected: int m_refCount; @@ -86,8 +92,7 @@ class BaseGameRep { /// @name Lifecycle //@{ /// Constructor; initializes reference count - BaseGameRep() : m_refCount(0) - {} + BaseGameRep() : m_refCount(0) {} /// Destructor virtual ~BaseGameRep() = default; @@ -96,27 +101,32 @@ class BaseGameRep { /// @name Validation //@{ /// Is the object still valid? - bool IsValid() const - { return true; } + bool IsValid() const { return true; } /// Invalidate the object; delete if not referenced elsewhere void Invalidate() - { if (!m_refCount) delete this; } + { + if (!m_refCount) { + delete this; + } + } //@} /// @name Reference counting //@{ /// Increment the reference count - void IncRef() - { m_refCount++; } + void IncRef() { m_refCount++; } /// Decrement the reference count; delete if reference count is zero. void DecRef() - { if (!--m_refCount) delete this; } + { + if (!--m_refCount) { + delete this; + } + } /// Returns the reference count - int RefCount() const - { return m_refCount; } + int RefCount() const { return m_refCount; } //@} }; @@ -125,67 +135,78 @@ class InvalidObjectException : public Exception { public: ~InvalidObjectException() noexcept override = default; - const char *what() const noexcept override - { return "Dereferencing an invalidated object"; } + const char *what() const noexcept override { return "Dereferencing an invalidated object"; } }; - // // This is a handle class that is used by all calling code to refer to // member objects of games. It takes care of all the reference-counting // considerations. // -template -class GameObjectPtr { +template class GameObjectPtr { private: T *rep; public: GameObjectPtr(T *r = nullptr) : rep(r) - { if (rep) rep->IncRef(); } + { + if (rep) { + rep->IncRef(); + } + } GameObjectPtr(const GameObjectPtr &r) : rep(r.rep) - { if (rep) rep->IncRef(); } + { + if (rep) { + rep->IncRef(); + } + } ~GameObjectPtr() - { if (rep) rep->DecRef(); } + { + if (rep) { + rep->DecRef(); + } + } GameObjectPtr &operator=(const GameObjectPtr &r) { if (&r != this) { - if (rep) rep->DecRef(); + if (rep) { + rep->DecRef(); + } rep = r.rep; - if (rep) rep->IncRef(); + if (rep) { + rep->IncRef(); + } } return *this; } T *operator->() const { - if (!rep) throw NullException(); - if (!rep->IsValid()) throw InvalidObjectException(); + if (!rep) { + throw NullException(); + } + if (!rep->IsValid()) { + throw InvalidObjectException(); + } return rep; } - bool operator==(const GameObjectPtr &r) const - { return (rep == r.rep); } + bool operator==(const GameObjectPtr &r) const { return (rep == r.rep); } - bool operator==(T *r) const - { return (rep == r); } + bool operator==(T *r) const { return (rep == r); } - bool operator!=(const GameObjectPtr &r) const - { return (rep != r.rep); } + bool operator!=(const GameObjectPtr &r) const { return (rep != r.rep); } - bool operator!=(T *r) const - { return (rep != r); } + bool operator!=(T *r) const { return (rep != r); } - operator T *() const - { return rep; } + operator T *() const { return rep; } - bool operator!() const - { return !rep; } + bool operator!() const { return !rep; } }; -} // end namespace Gambit +} // end namespace Gambit -#endif // GAMBIT_GAMES_GAMEOBJECT_H +#endif // GAMBIT_GAMES_GAMEOBJECT_H diff --git a/src/games/gametable.cc b/src/games/gametable.cc index c18c6dda5..8d44fb982 100644 --- a/src/games/gametable.cc +++ b/src/games/gametable.cc @@ -33,7 +33,7 @@ namespace Gambit { class TablePureStrategyProfileRep : public PureStrategyProfileRep { protected: - long m_index {1L}; + long m_index{1L}; PureStrategyProfileRep *Copy() const override; @@ -54,7 +54,7 @@ class TablePureStrategyProfileRep : public PureStrategyProfileRep { TablePureStrategyProfileRep::TablePureStrategyProfileRep(const Game &p_nfg) : PureStrategyProfileRep(p_nfg) { - for (int pl = 1; pl <= m_nfg->NumPlayers(); pl++) { + for (int pl = 1; pl <= m_nfg->NumPlayers(); pl++) { m_index += m_profile[pl]->m_offset; } } @@ -100,11 +100,12 @@ Rational TablePureStrategyProfileRep::GetPayoff(int pl) const } } -Rational -TablePureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const +Rational TablePureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const { int player = p_strategy->GetPlayer()->GetNumber(); - GameOutcomeRep *outcome = dynamic_cast(*m_nfg).m_results[m_index - m_profile[player]->m_offset + p_strategy->m_offset]; + GameOutcomeRep *outcome = + dynamic_cast(*m_nfg) + .m_results[m_index - m_profile[player]->m_offset + p_strategy->m_offset]; if (outcome) { return static_cast(outcome->GetPayoff(player)); } @@ -122,25 +123,24 @@ PureStrategyProfile GameTableRep::NewPureStrategyProfile() const // TableMixedStrategyProfileRep //======================================================================== -template class TableMixedStrategyProfileRep - : public MixedStrategyProfileRep { +template class TableMixedStrategyProfileRep : public MixedStrategyProfileRep { private: /// @name Private recursive payoff functions //@{ /// Recursive computation of payoff to player pl T GetPayoff(int pl, int index, int i) const; /// Recursive computation of payoff derivative - void GetPayoffDeriv(int pl, int const_pl, int cur_pl, long index, - const T &prob, T &value) const; + void GetPayoffDeriv(int pl, int const_pl, int cur_pl, long index, const T &prob, T &value) const; /// Recursive computation of payoff second derivative - void GetPayoffDeriv(int pl, int const_pl1, int const_pl2, - int cur_pl, long index, const T &prob, T &value) const; + void GetPayoffDeriv(int pl, int const_pl1, int const_pl2, int cur_pl, long index, const T &prob, + T &value) const; //@} public: explicit TableMixedStrategyProfileRep(const StrategySupportProfile &p_support) : MixedStrategyProfileRep(p_support) - { } + { + } ~TableMixedStrategyProfileRep() override = default; MixedStrategyProfileRep *Copy() const override; @@ -149,8 +149,7 @@ template class TableMixedStrategyProfileRep T GetPayoffDeriv(int pl, const GameStrategy &, const GameStrategy &) const override; }; -template -MixedStrategyProfileRep *TableMixedStrategyProfileRep::Copy() const +template MixedStrategyProfileRep *TableMixedStrategyProfileRep::Copy() const { return new TableMixedStrategyProfileRep(*this); } @@ -158,7 +157,7 @@ MixedStrategyProfileRep *TableMixedStrategyProfileRep::Copy() const template T TableMixedStrategyProfileRep::GetPayoff(int pl, int index, int current) const { - if (current > this->m_support.GetGame()->NumPlayers()) { + if (current > this->m_support.GetGame()->NumPlayers()) { Game game = this->m_support.GetGame(); auto &g = dynamic_cast(*game); GameOutcomeRep *outcome = g.m_results[index]; @@ -166,15 +165,14 @@ T TableMixedStrategyProfileRep::GetPayoff(int pl, int index, int current) con return static_cast(outcome->GetPayoff(pl)); } else { - return (T) 0; + return (T)0; } } T sum = static_cast(0); for (auto s : this->m_support.GetStrategies(this->m_support.GetGame()->GetPlayer(current))) { - if ((*this)[s] != (T) 0) { - sum += ((*this)[s] * - GetPayoff(pl, index + s->m_offset, current + 1)); + if ((*this)[s] != (T)0) { + sum += ((*this)[s] * GetPayoff(pl, index + s->m_offset, current + 1)); } } return sum; @@ -186,15 +184,13 @@ template T TableMixedStrategyProfileRep::GetPayoff(int pl) const } template -void -TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, int const_pl, - int cur_pl, long index, - const T &prob, T &value) const +void TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, int const_pl, int cur_pl, long index, + const T &prob, T &value) const { if (cur_pl == const_pl) { cur_pl++; } - if (cur_pl > this->m_support.GetGame()->NumPlayers()) { + if (cur_pl > this->m_support.GetGame()->NumPlayers()) { Game game = this->m_support.GetGame(); auto &g = dynamic_cast(*game); GameOutcomeRep *outcome = g.m_results[index]; @@ -202,37 +198,32 @@ TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, int const_pl, value += prob * static_cast(outcome->GetPayoff(pl)); } } - else { + else { for (auto s : this->m_support.GetStrategies(this->m_support.GetGame()->GetPlayer(cur_pl))) { - if ((*this)[s] > (T) 0) { - GetPayoffDeriv(pl, const_pl, cur_pl + 1, - index + s->m_offset, prob * (*this)[s], value); + if ((*this)[s] > (T)0) { + GetPayoffDeriv(pl, const_pl, cur_pl + 1, index + s->m_offset, prob * (*this)[s], value); } } } } -template T -TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, - const GameStrategy &strategy) const +template +T TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &strategy) const { - T value = (T) 0; - GetPayoffDeriv(pl, strategy->GetPlayer()->GetNumber(), 1, - strategy->m_offset + 1, (T) 1, value); + T value = (T)0; + GetPayoffDeriv(pl, strategy->GetPlayer()->GetNumber(), 1, strategy->m_offset + 1, (T)1, value); return value; } template -void -TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, int const_pl1, - int const_pl2, - int cur_pl, long index, - const T &prob, T &value) const +void TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, int const_pl1, int const_pl2, + int cur_pl, long index, const T &prob, + T &value) const { while (cur_pl == const_pl1 || cur_pl == const_pl2) { cur_pl++; } - if (cur_pl > this->m_support.GetGame()->NumPlayers()) { + if (cur_pl > this->m_support.GetGame()->NumPlayers()) { Game game = this->m_support.GetGame(); auto &g = dynamic_cast(*game); GameOutcomeRep *outcome = g.m_results[index]; @@ -240,38 +231,35 @@ TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, int const_pl1, value += prob * static_cast(outcome->GetPayoff(pl)); } } - else { + else { for (auto s : this->m_support.GetStrategies(this->m_support.GetGame()->GetPlayer(cur_pl))) { if ((*this)[s] > static_cast(0)) { - GetPayoffDeriv(pl, const_pl1, const_pl2, - cur_pl + 1, index + s->m_offset, - prob * (*this)[s], - value); + GetPayoffDeriv(pl, const_pl1, const_pl2, cur_pl + 1, index + s->m_offset, + prob * (*this)[s], value); } } } } -template T -TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, - const GameStrategy &strategy1, - const GameStrategy &strategy2) const +template +T TableMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &strategy1, + const GameStrategy &strategy2) const { GamePlayerRep *player1 = strategy1->GetPlayer(); GamePlayerRep *player2 = strategy2->GetPlayer(); - if (player1 == player2) return (T) 0; + if (player1 == player2) { + return (T)0; + } - T value = (T) 0; - GetPayoffDeriv(pl, player1->GetNumber(), player2->GetNumber(), - 1, strategy1->m_offset + strategy2->m_offset + 1, - (T) 1, value); + T value = (T)0; + GetPayoffDeriv(pl, player1->GetNumber(), player2->GetNumber(), 1, + strategy1->m_offset + strategy2->m_offset + 1, (T)1, value); return value; } template class TableMixedStrategyProfileRep; template class TableMixedStrategyProfileRep; - //------------------------------------------------------------------------ // GameTableRep: Lifecycle //------------------------------------------------------------------------ @@ -290,12 +278,10 @@ int Product(const Array &dim) } // end anonymous namespace - -GameTableRep::GameTableRep(const Array &dim, - bool p_sparseOutcomes /* = false */) +GameTableRep::GameTableRep(const Array &dim, bool p_sparseOutcomes /* = false */) { m_results = Array(Product(dim)); - for (int pl = 1; pl <= dim.Length(); pl++) { + for (int pl = 1; pl <= dim.Length(); pl++) { m_players.push_back(new GamePlayerRep(this, pl, dim[pl])); m_players[pl]->m_label = lexical_cast(pl); for (int st = 1; st <= m_players[pl]->NumStrategies(); st++) { @@ -305,8 +291,8 @@ GameTableRep::GameTableRep(const Array &dim, IndexStrategies(); if (p_sparseOutcomes) { - for (int cont = 1; cont <= m_results.Length(); - m_results[cont++] = 0); + for (int cont = 1; cont <= m_results.Length(); m_results[cont++] = 0) + ; } else { m_outcomes = Array(m_results.Length()); @@ -363,15 +349,17 @@ std::string EscapeQuotes(const std::string &s) { std::string ret; - for (char c : s) { - if (c == '"') ret += '\\'; + for (char c : s) { + if (c == '"') { + ret += '\\'; + } ret += c; } return ret; } -} // end anonymous namespace +} // end anonymous namespace /// /// Write the game to a savefile in .nfg outcome format. @@ -387,16 +375,18 @@ void GameTableRep::WriteNfgFile(std::ostream &p_file) const p_file << "NFG 1 R"; p_file << " \"" << EscapeQuotes(GetTitle()) << "\" { "; - for (int i = 1; i <= NumPlayers(); i++) + for (int i = 1; i <= NumPlayers(); i++) { p_file << '"' << EscapeQuotes(GetPlayer(i)->GetLabel()) << "\" "; + } p_file << "}\n\n{ "; - for (int i = 1; i <= NumPlayers(); i++) { + for (int i = 1; i <= NumPlayers(); i++) { GamePlayerRep *player = GetPlayer(i); p_file << "{ "; - for (int j = 1; j <= player->NumStrategies(); j++) + for (int j = 1; j <= player->NumStrategies(); j++) { p_file << '"' << EscapeQuotes(player->GetStrategy(j)->GetLabel()) << "\" "; + } p_file << "}\n"; } @@ -410,20 +400,21 @@ void GameTableRep::WriteNfgFile(std::ostream &p_file) const } p_file << "{\n"; - for (auto outcome: m_outcomes) { + for (auto outcome : m_outcomes) { p_file << "{ \"" << EscapeQuotes(outcome->m_label) << "\" "; for (int pl = 1; pl <= m_players.Length(); pl++) { - p_file << (const std::string &) outcome->m_payoffs[pl]; + p_file << (const std::string &)outcome->m_payoffs[pl]; if (pl < m_players.Length()) { p_file << ", "; - } else { + } + else { p_file << " }\n"; } } } p_file << "}\n"; - for (int cont = 1; cont <= ncont; cont++) { + for (int cont = 1; cont <= ncont; cont++) { if (m_results[cont] != 0) { p_file << m_results[cont]->m_number << ' '; } @@ -474,19 +465,23 @@ void GameTableRep::DeleteOutcome(const GameOutcome &p_outcome) MixedStrategyProfile GameTableRep::NewMixedStrategyProfile(double) const { - return StrategySupportProfile(const_cast(this)).NewMixedStrategyProfile(); + return StrategySupportProfile(const_cast(this)) + .NewMixedStrategyProfile(); } MixedStrategyProfile GameTableRep::NewMixedStrategyProfile(const Rational &) const { - return StrategySupportProfile(const_cast(this)).NewMixedStrategyProfile(); + return StrategySupportProfile(const_cast(this)) + .NewMixedStrategyProfile(); } -MixedStrategyProfile GameTableRep::NewMixedStrategyProfile(double, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameTableRep::NewMixedStrategyProfile(double, const StrategySupportProfile &spt) const { return MixedStrategyProfile(new TableMixedStrategyProfileRep(spt)); } -MixedStrategyProfile GameTableRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameTableRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &spt) const { return MixedStrategyProfile(new TableMixedStrategyProfileRep(spt)); } @@ -508,19 +503,20 @@ void GameTableRep::RebuildTable() } Array newResults(size); - for (int i = 1; i <= newResults.Length(); newResults[i++] = 0); + for (int i = 1; i <= newResults.Length(); newResults[i++] = 0) + ; for (StrategyProfileIterator iter(StrategySupportProfile(const_cast(this))); !iter.AtEnd(); iter++) { long newindex = 1L; for (int pl = 1; pl <= m_players.Length(); pl++) { if (iter.m_profile->GetStrategy(pl)->m_offset < 0) { - // This is a contingency involving a new strategy... skip - newindex = -1L; - break; + // This is a contingency involving a new strategy... skip + newindex = -1L; + break; } else { - newindex += (iter.m_profile->GetStrategy(pl)->m_number - 1) * offsets[pl]; + newindex += (iter.m_profile->GetStrategy(pl)->m_number - 1) * offsets[pl]; } } @@ -537,7 +533,7 @@ void GameTableRep::RebuildTable() void GameTableRep::IndexStrategies() { long offset = 1L; - for (auto player : m_players) { + for (auto player : m_players) { int st = 1; for (auto strategy : player->m_strategies) { strategy->m_number = st; @@ -555,5 +551,4 @@ void GameTableRep::IndexStrategies() } } - -} // end namespace Gambit +} // end namespace Gambit diff --git a/src/games/gametable.h b/src/games/gametable.h index aadd3b7ba..7bd8fc2cc 100644 --- a/src/games/gametable.h +++ b/src/games/gametable.h @@ -34,6 +34,7 @@ class GameTableRep : public GameExplicitRep { friend class PureStrategyProfileRep; template friend class MixedStrategyProfile; template friend class TableMixedStrategyProfileRep; + private: Array m_results; @@ -56,21 +57,17 @@ class GameTableRep : public GameExplicitRep { //@{ bool IsTree() const override { return false; } bool IsConstSum() const override; - bool IsPerfectRecall(GameInfoset &, GameInfoset &) const override - { return true; } + bool IsPerfectRecall(GameInfoset &, GameInfoset &) const override { return true; } //@} /// @name Dimensions of the game //@{ /// The number of actions in each information set - PVector NumActions() const override - { throw UndefinedException(); } + PVector NumActions() const override { throw UndefinedException(); } /// The number of members in each information set - PVector NumMembers() const override - { throw UndefinedException(); } + PVector NumMembers() const override { throw UndefinedException(); } /// Returns the total number of actions in the game - int BehavProfileLength() const override - { throw UndefinedException(); } + int BehavProfileLength() const override { throw UndefinedException(); } //@} /// @name Players @@ -84,17 +81,13 @@ class GameTableRep : public GameExplicitRep { /// @name Information sets //@{ /// Returns the iset'th information set in the game (numbered globally) - GameInfoset GetInfoset(int iset) const override - { throw UndefinedException(); } + GameInfoset GetInfoset(int iset) const override { throw UndefinedException(); } /// Returns the set of information sets in the game - Array GetInfosets() const override - { throw UndefinedException(); } + Array GetInfosets() const override { throw UndefinedException(); } /// Returns an array with the number of information sets per personal player - Array NumInfosets() const override - { throw UndefinedException(); } + Array NumInfosets() const override { throw UndefinedException(); } /// Returns the act'th action in the game (numbered globally) - GameAction GetAction(int act) const override - { throw UndefinedException(); } + GameAction GetAction(int act) const override { throw UndefinedException(); } //@} /// @name Nodes @@ -118,19 +111,21 @@ class GameTableRep : public GameExplicitRep { /// @name Modification //@{ - Game SetChanceProbs(const GameInfoset &, const Array &) override { throw UndefinedException(); } + Game SetChanceProbs(const GameInfoset &, const Array &) override + { + throw UndefinedException(); + } //@} PureStrategyProfile NewPureStrategyProfile() const override; MixedStrategyProfile NewMixedStrategyProfile(double) const override; MixedStrategyProfile NewMixedStrategyProfile(const Rational &) const override; - MixedStrategyProfile NewMixedStrategyProfile(double, const StrategySupportProfile&) const override; - MixedStrategyProfile NewMixedStrategyProfile(const Rational &, const StrategySupportProfile&) const override; - + MixedStrategyProfile + NewMixedStrategyProfile(double, const StrategySupportProfile &) const override; + MixedStrategyProfile + NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &) const override; }; -} - - +} // namespace Gambit -#endif // GAMETABLE_H +#endif // GAMETABLE_H diff --git a/src/games/gametree.cc b/src/games/gametree.cc index 08ecb2db5..3f54dc38a 100644 --- a/src/games/gametree.cc +++ b/src/games/gametree.cc @@ -38,12 +38,13 @@ namespace Gambit { //======================================================================== template -TreeMixedStrategyProfileRep::TreeMixedStrategyProfileRep(const MixedBehaviorProfile &p_profile) +TreeMixedStrategyProfileRep::TreeMixedStrategyProfileRep( + const MixedBehaviorProfile &p_profile) : MixedStrategyProfileRep(p_profile.GetGame()) -{ } +{ +} -template -MixedStrategyProfileRep *TreeMixedStrategyProfileRep::Copy() const +template MixedStrategyProfileRep *TreeMixedStrategyProfileRep::Copy() const { return new TreeMixedStrategyProfileRep(*this); } @@ -54,9 +55,8 @@ template T TreeMixedStrategyProfileRep::GetPayoff(int pl) const return MixedBehaviorProfile(profile).GetPayoff(pl); } -template T -TreeMixedStrategyProfileRep::GetPayoffDeriv(int pl, - const GameStrategy &strategy) const +template +T TreeMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &strategy) const { MixedStrategyProfile foo(Copy()); for (auto s : this->m_support.GetStrategies(this->m_support.GetGame()->GetPlayer(pl))) { @@ -66,25 +66,26 @@ TreeMixedStrategyProfileRep::GetPayoffDeriv(int pl, return foo.GetPayoff(pl); } -template T -TreeMixedStrategyProfileRep::GetPayoffDeriv(int pl, - const GameStrategy &strategy1, - const GameStrategy &strategy2) const +template +T TreeMixedStrategyProfileRep::GetPayoffDeriv(int pl, const GameStrategy &strategy1, + const GameStrategy &strategy2) const { GamePlayerRep *player1 = strategy1->GetPlayer(); GamePlayerRep *player2 = strategy2->GetPlayer(); - if (player1 == player2) return (T) 0; + if (player1 == player2) { + return (T)0; + } MixedStrategyProfile foo(Copy()); for (auto strategy : this->m_support.GetStrategies(player1)) { - foo[strategy] = (T) 0; + foo[strategy] = (T)0; } - foo[strategy1] = (T) 1; + foo[strategy1] = (T)1; for (auto strategy : this->m_support.GetStrategies(player2)) { - foo[strategy] = (T) 0; + foo[strategy] = (T)0; } - foo[strategy2] = (T) 1; + foo[strategy2] = (T)1; return foo.GetPayoff(pl); } @@ -92,8 +93,6 @@ TreeMixedStrategyProfileRep::GetPayoffDeriv(int pl, template class TreeMixedStrategyProfileRep; template class TreeMixedStrategyProfileRep; - - //======================================================================== // class GameTreeActionRep //======================================================================== @@ -115,14 +114,15 @@ bool GameTreeActionRep::Precedes(const GameNode &n) const void GameTreeActionRep::DeleteAction() { - if (m_infoset->NumActions() == 1) throw UndefinedException(); + if (m_infoset->NumActions() == 1) { + throw UndefinedException(); + } m_infoset->GetGame()->IncrementVersion(); int where; - for (where = 1; - where <= m_infoset->m_actions.Length() && - m_infoset->m_actions[where] != this; - where++); + for (where = 1; where <= m_infoset->m_actions.Length() && m_infoset->m_actions[where] != this; + where++) + ; m_infoset->RemoveAction(where); for (auto member : m_infoset->m_members) { @@ -131,7 +131,7 @@ void GameTreeActionRep::DeleteAction() } if (m_infoset->IsChanceInfoset()) { - m_infoset->m_efg->NormalizeChanceProbs(m_infoset); + m_infoset->m_efg->NormalizeChanceProbs(m_infoset); } m_infoset->m_efg->ClearComputedValues(); m_infoset->m_efg->Canonicalize(); @@ -143,13 +143,11 @@ GameInfoset GameTreeActionRep::GetInfoset() const { return m_infoset; } // class GameTreeInfosetRep //======================================================================== -GameTreeInfosetRep::GameTreeInfosetRep(GameTreeRep *p_efg, int p_number, - GamePlayerRep *p_player, - int p_actions) - : m_efg(p_efg), m_number(p_number), m_player(p_player), - m_actions(p_actions), flag(0) +GameTreeInfosetRep::GameTreeInfosetRep(GameTreeRep *p_efg, int p_number, GamePlayerRep *p_player, + int p_actions) + : m_efg(p_efg), m_number(p_number), m_player(p_player), m_actions(p_actions), flag(0) { - while (p_actions) { + while (p_actions) { m_actions[p_actions] = new GameTreeActionRep(p_actions, "", this); p_actions--; } @@ -167,8 +165,7 @@ GameTreeInfosetRep::GameTreeInfosetRep(GameTreeRep *p_efg, int p_number, GameTreeInfosetRep::~GameTreeInfosetRep() { - std::for_each(m_actions.begin(), m_actions.end(), - [](GameActionRep *a) { a->Invalidate(); }); + std::for_each(m_actions.begin(), m_actions.end(), [](GameActionRep *a) { a->Invalidate(); }); } Game GameTreeInfosetRep::GetGame() const { return m_efg; } @@ -176,16 +173,22 @@ Game GameTreeInfosetRep::GetGame() const { return m_efg; } Array GameTreeInfosetRep::GetActions() const { Array ret(m_actions.size()); - std::transform(m_actions.cbegin(), m_actions.end(), - ret.begin(), [](GameActionRep *a) -> GameAction { return a; }); + std::transform(m_actions.cbegin(), m_actions.end(), ret.begin(), + [](GameActionRep *a) -> GameAction { return a; }); return ret; } void GameTreeInfosetRep::SetPlayer(GamePlayer p_player) { - if (p_player->GetGame() != m_efg) throw MismatchException(); - if (m_player->IsChance() || p_player->IsChance()) throw UndefinedException(); - if (m_player == p_player) return; + if (p_player->GetGame() != m_efg) { + throw MismatchException(); + } + if (m_player->IsChance() || p_player->IsChance()) { + throw UndefinedException(); + } + if (m_player == p_player) { + return; + } m_efg->IncrementVersion(); m_player->m_infosets.Remove(m_player->m_infosets.Find(this)); @@ -212,12 +215,15 @@ bool GameTreeInfosetRep::Precedes(GameNode p_node) const GameAction GameTreeInfosetRep::InsertAction(GameAction p_action /* =0 */) { - if (p_action && p_action->GetInfoset() != this) throw MismatchException(); + if (p_action && p_action->GetInfoset() != this) { + throw MismatchException(); + } m_efg->IncrementVersion(); int where = m_actions.Length() + 1; if (p_action) { - for (where = 1; m_actions[where] != p_action; where++); + for (where = 1; m_actions[where] != p_action; where++) + ; } auto *action = new GameTreeActionRep(where, "", this); @@ -231,8 +237,7 @@ GameAction GameTreeInfosetRep::InsertAction(GameAction p_action /* =0 */) } for (int i = 1; i <= m_members.Length(); i++) { - m_members[i]->children.Insert(new GameTreeNodeRep(m_efg, m_members[i]), - where); + m_members[i]->children.Insert(new GameTreeNodeRep(m_efg, m_members[i]), where); } m_efg->ClearComputedValues(); @@ -240,7 +245,6 @@ GameAction GameTreeInfosetRep::InsertAction(GameAction p_action /* =0 */) return action; } - void GameTreeInfosetRep::RemoveAction(int which) { m_efg->IncrementVersion(); @@ -295,27 +299,19 @@ void GameTreeInfosetRep::Reveal(GamePlayer p_player) m_efg->Canonicalize(); } -GameNode GameTreeInfosetRep::GetMember(int p_index) const -{ - return m_members[p_index]; -} +GameNode GameTreeInfosetRep::GetMember(int p_index) const { return m_members[p_index]; } Array GameTreeInfosetRep::GetMembers() const { Array ret(m_members.size()); - std::transform(m_members.cbegin(), m_members.cend(), - ret.begin(), [](GameTreeNodeRep *n) -> GameNode { return n; }); + std::transform(m_members.cbegin(), m_members.cend(), ret.begin(), + [](GameTreeNodeRep *n) -> GameNode { return n; }); return ret; } -GamePlayer GameTreeInfosetRep::GetPlayer() const -{ - return m_player; -} - -bool GameTreeInfosetRep::IsChanceInfoset() const -{ return m_player->IsChance(); } +GamePlayer GameTreeInfosetRep::GetPlayer() const { return m_player; } +bool GameTreeInfosetRep::IsChanceInfoset() const { return m_player->IsChance(); } //======================================================================== // class GameTreeNodeRep @@ -323,12 +319,12 @@ bool GameTreeInfosetRep::IsChanceInfoset() const GameTreeNodeRep::GameTreeNodeRep(GameTreeRep *e, GameTreeNodeRep *p) : number(0), m_efg(e), infoset(nullptr), m_parent(p), outcome(nullptr) -{ } +{ +} GameTreeNodeRep::~GameTreeNodeRep() { - std::for_each(children.begin(), children.end(), - [](GameNodeRep *n) { n->Invalidate(); }); + std::for_each(children.begin(), children.end(), [](GameNodeRep *n) { n->Invalidate(); }); } Game GameTreeNodeRep::GetGame() const { return m_efg; } @@ -336,8 +332,8 @@ Game GameTreeNodeRep::GetGame() const { return m_efg; } Array GameTreeNodeRep::GetChildren() const { Array ret(children.size()); - std::transform(children.cbegin(), children.cend(), - ret.begin(), [](GameTreeNodeRep *n) -> GameNode { return n; }); + std::transform(children.cbegin(), children.cend(), ret.begin(), + [](GameTreeNodeRep *n) -> GameNode { return n; }); return ret; } @@ -384,7 +380,9 @@ GameAction GameTreeNodeRep::GetPriorAction() const void GameTreeNodeRep::DeleteOutcome(GameOutcomeRep *outc) { m_efg->IncrementVersion(); - if (outc == outcome) outcome = nullptr; + if (outc == outcome) { + outcome = nullptr; + } for (auto child : children) { child->DeleteOutcome(outc); } @@ -402,15 +400,21 @@ void GameTreeNodeRep::SetOutcome(const GameOutcome &p_outcome) bool GameTreeNodeRep::IsSuccessorOf(GameNode p_node) const { auto *n = const_cast(this); - while (n && n != p_node) n = n->m_parent; + while (n && n != p_node) { + n = n->m_parent; + } return (n == p_node); } bool GameTreeNodeRep::IsSubgameRoot() const { // First take care of a couple easy cases - if (children.empty() || infoset->NumMembers() > 1) return false; - if (!m_parent) return true; + if (children.empty() || infoset->NumMembers() > 1) { + return false; + } + if (!m_parent) { + return true; + } // A node is a subgame root if and only if in every information set, // either all members succeed the node in the tree, @@ -432,7 +436,9 @@ bool GameTreeNodeRep::IsSubgameRoot() const void GameTreeNodeRep::DeleteParent() { - if (!m_parent) return; + if (!m_parent) { + return; + } m_efg->IncrementVersion(); GameTreeNodeRep *oldParent = m_parent; @@ -479,7 +485,7 @@ void GameTreeNodeRep::CopySubtree(GameTreeNodeRep *src, GameTreeNodeRep *stop) return; } - if (src->children.Length()) { + if (src->children.Length()) { AppendMove(src->infoset); for (int i = 1; i <= src->children.Length(); i++) { children[i]->CopySubtree(src->children[i], stop); @@ -492,13 +498,17 @@ void GameTreeNodeRep::CopySubtree(GameTreeNodeRep *src, GameTreeNodeRep *stop) void GameTreeNodeRep::CopyTree(GameNode p_src) { - if (p_src->GetGame() != m_efg) throw MismatchException(); - if (p_src == this || !children.empty()) return; + if (p_src->GetGame() != m_efg) { + throw MismatchException(); + } + if (p_src == this || !children.empty()) { + return; + } m_efg->IncrementVersion(); auto *src = dynamic_cast(p_src.operator->()); - if (!src->children.empty()) { + if (!src->children.empty()) { AppendMove(src->infoset); for (int i = 1; i <= src->children.Length(); i++) { children[i]->CopySubtree(src->children[i], this); @@ -511,7 +521,9 @@ void GameTreeNodeRep::CopyTree(GameNode p_src) void GameTreeNodeRep::MoveTree(GameNode p_src) { - if (p_src->GetGame() != m_efg) throw MismatchException(); + if (p_src->GetGame() != m_efg) { + throw MismatchException(); + } if (p_src == this || !children.empty() || IsSuccessorOf(p_src)) { return; } @@ -549,10 +561,15 @@ Game GameTreeNodeRep::CopySubgame() const void GameTreeNodeRep::SetInfoset(GameInfoset p_infoset) { - if (p_infoset->GetGame() != m_efg) throw MismatchException(); - if (!infoset || infoset == p_infoset) return; - if (p_infoset->NumActions() != children.Length()) + if (p_infoset->GetGame() != m_efg) { + throw MismatchException(); + } + if (!infoset || infoset == p_infoset) { + return; + } + if (p_infoset->NumActions() != children.Length()) { throw DimensionException(); + } m_efg->IncrementVersion(); infoset->RemoveMember(this); dynamic_cast(p_infoset.operator->())->AddMember(this); @@ -564,16 +581,20 @@ void GameTreeNodeRep::SetInfoset(GameInfoset p_infoset) GameInfoset GameTreeNodeRep::LeaveInfoset() { - if (!infoset) return nullptr; + if (!infoset) { + return nullptr; + } m_efg->IncrementVersion(); GameTreeInfosetRep *oldInfoset = infoset; - if (oldInfoset->m_members.Length() == 1) return oldInfoset; + if (oldInfoset->m_members.Length() == 1) { + return oldInfoset; + } GamePlayerRep *player = oldInfoset->m_player; oldInfoset->RemoveMember(this); - infoset = new GameTreeInfosetRep(m_efg, player->m_infosets.Length() + 1, player, - children.Length()); + infoset = + new GameTreeInfosetRep(m_efg, player->m_infosets.Length() + 1, player, children.Length()); infoset->AddMember(this); for (int i = 1; i <= oldInfoset->m_actions.Length(); i++) { infoset->m_actions[i]->SetLabel(oldInfoset->m_actions[i]->GetLabel()); @@ -586,19 +607,26 @@ GameInfoset GameTreeNodeRep::LeaveInfoset() GameInfoset GameTreeNodeRep::AppendMove(GamePlayer p_player, int p_actions) { - if (p_actions <= 0 || !children.empty()) throw UndefinedException(); - if (p_player->GetGame() != m_efg) throw MismatchException(); + if (p_actions <= 0 || !children.empty()) { + throw UndefinedException(); + } + if (p_player->GetGame() != m_efg) { + throw MismatchException(); + } m_efg->IncrementVersion(); - return AppendMove(new GameTreeInfosetRep(m_efg, - p_player->m_infosets.size() + 1, - p_player, p_actions)); + return AppendMove( + new GameTreeInfosetRep(m_efg, p_player->m_infosets.size() + 1, p_player, p_actions)); } GameInfoset GameTreeNodeRep::AppendMove(GameInfoset p_infoset) { - if (!children.empty()) throw UndefinedException(); - if (p_infoset->GetGame() != m_efg) throw MismatchException(); + if (!children.empty()) { + throw UndefinedException(); + } + if (p_infoset->GetGame() != m_efg) { + throw MismatchException(); + } m_efg->IncrementVersion(); infoset = dynamic_cast(p_infoset.operator->()); @@ -614,18 +642,23 @@ GameInfoset GameTreeNodeRep::AppendMove(GameInfoset p_infoset) GameInfoset GameTreeNodeRep::InsertMove(GamePlayer p_player, int p_actions) { - if (p_actions <= 0) throw UndefinedException(); - if (p_player->GetGame() != m_efg) throw MismatchException(); + if (p_actions <= 0) { + throw UndefinedException(); + } + if (p_player->GetGame() != m_efg) { + throw MismatchException(); + } m_efg->IncrementVersion(); - return InsertMove(new GameTreeInfosetRep(m_efg, - p_player->m_infosets.Length() + 1, - p_player, p_actions)); + return InsertMove( + new GameTreeInfosetRep(m_efg, p_player->m_infosets.Length() + 1, p_player, p_actions)); } GameInfoset GameTreeNodeRep::InsertMove(GameInfoset p_infoset) { - if (p_infoset->GetGame() != m_efg) throw MismatchException(); + if (p_infoset->GetGame() != m_efg) { + throw MismatchException(); + } m_efg->IncrementVersion(); auto *newNode = new GameTreeNodeRep(m_efg, m_parent); @@ -651,7 +684,6 @@ GameInfoset GameTreeNodeRep::InsertMove(GameInfoset p_infoset) return p_infoset; } - //======================================================================== // class GameTreeRep //======================================================================== @@ -661,9 +693,10 @@ GameInfoset GameTreeNodeRep::InsertMove(GameInfoset p_infoset) //------------------------------------------------------------------------ GameTreeRep::GameTreeRep() - : m_computedValues(false), m_doCanon(true), - m_root(new GameTreeNodeRep(this, nullptr)), m_chance(new GamePlayerRep(this, 0)) -{ } + : m_computedValues(false), m_doCanon(true), m_root(new GameTreeNodeRep(this, nullptr)), + m_chance(new GamePlayerRep(this, 0)) +{ +} GameTreeRep::~GameTreeRep() { @@ -679,7 +712,7 @@ Game GameTreeRep::Copy() const return ReadGame(is); } -Game NewTree() { return new GameTreeRep(); } +Game NewTree() { return new GameTreeRep(); } //------------------------------------------------------------------------ // GameTreeRep: General data access @@ -701,7 +734,7 @@ Rational SubtreeSum(const GameNode &p_node) sum = SubtreeSum(p_node->GetChild(1)); for (int i = 2; i <= p_node->NumChildren(); i++) { if (SubtreeSum(p_node->GetChild(i)) != sum) { - throw NotZeroSumException(); + throw NotZeroSumException(); } } } @@ -714,8 +747,7 @@ Rational SubtreeSum(const GameNode &p_node) return sum; } -} // end anonymous namespace - +} // end anonymous namespace bool GameTreeRep::IsConstSum() const { @@ -778,7 +810,6 @@ bool GameTreeRep::IsPerfectRecall(GameInfoset &s1, GameInfoset &s2) const return true; } - //------------------------------------------------------------------------ // GameTreeRep: Managing the representation //------------------------------------------------------------------------ @@ -786,13 +817,15 @@ bool GameTreeRep::IsPerfectRecall(GameInfoset &s1, GameInfoset &s2) const void GameTreeRep::NumberNodes(GameTreeNodeRep *n, int &index) { n->number = index++; - for (int child = 1; child <= n->children.Length(); - NumberNodes(n->children[child++], index)); + for (int child = 1; child <= n->children.Length(); NumberNodes(n->children[child++], index)) + ; } void GameTreeRep::Canonicalize() { - if (!m_doCanon) return; + if (!m_doCanon) { + return; + } int nodeindex = 1; NumberNodes(m_root, nodeindex); @@ -805,13 +838,13 @@ void GameTreeRep::Canonicalize() for (int iset = 1; iset <= player->m_infosets.Length(); iset++) { GameTreeInfosetRep *infoset = player->m_infosets[iset]; for (int i = 1; i < infoset->m_members.Length(); i++) { - for (int j = 1; j < infoset->m_members.Length() - i; j++) { - if (infoset->m_members[j+1]->number < infoset->m_members[j]->number) { - GameTreeNodeRep *tmp = infoset->m_members[j]; - infoset->m_members[j] = infoset->m_members[j+1]; - infoset->m_members[j+1] = tmp; - } - } + for (int j = 1; j < infoset->m_members.Length() - i; j++) { + if (infoset->m_members[j + 1]->number < infoset->m_members[j]->number) { + GameTreeNodeRep *tmp = infoset->m_members[j]; + infoset->m_members[j] = infoset->m_members[j + 1]; + infoset->m_members[j + 1] = tmp; + } + } } } @@ -820,16 +853,18 @@ void GameTreeRep::Canonicalize() // find a quicksort worthwhile. for (int i = 1; i < player->m_infosets.Length(); i++) { for (int j = 1; j < player->m_infosets.Length() - i; j++) { - int a = ((player->m_infosets[j+1]->m_members.Length()) ? - player->m_infosets[j+1]->m_members[1]->number : 0); - int b = ((player->m_infosets[j]->m_members.Length()) ? - player->m_infosets[j]->m_members[1]->number : 0); - - if (a < b || b == 0) { - GameTreeInfosetRep *tmp = player->m_infosets[j]; - player->m_infosets[j] = player->m_infosets[j+1]; - player->m_infosets[j+1] = tmp; - } + int a = ((player->m_infosets[j + 1]->m_members.Length()) + ? player->m_infosets[j + 1]->m_members[1]->number + : 0); + int b = ((player->m_infosets[j]->m_members.Length()) + ? player->m_infosets[j]->m_members[1]->number + : 0); + + if (a < b || b == 0) { + GameTreeInfosetRep *tmp = player->m_infosets[j]; + player->m_infosets[j] = player->m_infosets[j + 1]; + player->m_infosets[j + 1] = tmp; + } } } @@ -853,7 +888,9 @@ void GameTreeRep::ClearComputedValues() const void GameTreeRep::BuildComputedValues() { - if (m_computedValues) return; + if (m_computedValues) { + return; + } Canonicalize(); @@ -863,7 +900,8 @@ void GameTreeRep::BuildComputedValues() for (int pl = 1, id = 1; pl <= m_players.Length(); pl++) { for (int st = 1; st <= m_players[pl]->m_strategies.Length(); - m_players[pl]->m_strategies[st++]->m_id = id++); + m_players[pl]->m_strategies[st++]->m_id = id++) + ; } m_computedValues = true; @@ -879,8 +917,10 @@ std::string EscapeQuotes(const std::string &s) { std::string ret; - for (char c : s) { - if (c == '"') ret += '\\'; + for (char c : s) { + if (c == '"') { + ret += '\\'; + } ret += c; } @@ -901,21 +941,21 @@ void PrintActions(std::ostream &p_stream, GameTreeInfosetRep *p_infoset) void WriteEfgFile(std::ostream &f, GameTreeNodeRep *n) { - if (n->NumChildren() == 0) { + if (n->NumChildren() == 0) { f << "t \"" << EscapeQuotes(n->GetLabel()) << "\" "; - if (n->GetOutcome()) { - f << n->GetOutcome()->GetNumber() << " \"" << - EscapeQuotes(n->GetOutcome()->GetLabel()) << "\" "; + if (n->GetOutcome()) { + f << n->GetOutcome()->GetNumber() << " \"" << EscapeQuotes(n->GetOutcome()->GetLabel()) + << "\" "; f << "{ "; - for (int pl = 1; pl <= n->GetGame()->NumPlayers(); pl++) { - f << static_cast(n->GetOutcome()->GetPayoff(pl)); - - if (pl < n->GetGame()->NumPlayers()) { - f << ", "; - } - else { - f << " }\n"; - } + for (int pl = 1; pl <= n->GetGame()->NumPlayers(); pl++) { + f << static_cast(n->GetOutcome()->GetPayoff(pl)); + + if (pl < n->GetGame()->NumPlayers()) { + f << ", "; + } + else { + f << " }\n"; + } } } else { @@ -935,28 +975,31 @@ void WriteEfgFile(std::ostream &f, GameTreeNodeRep *n) if (!n->GetInfoset()->IsChanceInfoset()) { f << n->GetInfoset()->GetPlayer()->GetNumber() << ' '; } - f << n->GetInfoset()->GetNumber() << " \"" << - EscapeQuotes(n->GetInfoset()->GetLabel()) << "\" "; + f << n->GetInfoset()->GetNumber() << " \"" << EscapeQuotes(n->GetInfoset()->GetLabel()) << "\" "; PrintActions(f, dynamic_cast(n->GetInfoset().operator->())); f << " "; - if (n->GetOutcome()) { - f << n->GetOutcome()->GetNumber() << " \"" << - EscapeQuotes(n->GetOutcome()->GetLabel()) << "\" "; + if (n->GetOutcome()) { + f << n->GetOutcome()->GetNumber() << " \"" << EscapeQuotes(n->GetOutcome()->GetLabel()) + << "\" "; f << "{ "; - for (int pl = 1; pl <= n->GetGame()->NumPlayers(); pl++) { + for (int pl = 1; pl <= n->GetGame()->NumPlayers(); pl++) { f << static_cast(n->GetOutcome()->GetPayoff(pl)); - if (pl < n->GetGame()->NumPlayers()) - f << ", "; - else - f << " }\n"; + if (pl < n->GetGame()->NumPlayers()) { + f << ", "; + } + else { + f << " }\n"; + } } } - else + else { f << "0\n"; + } for (int i = 1; i <= n->NumChildren(); - WriteEfgFile(f, dynamic_cast(n->GetChild(i++).operator->()))); + WriteEfgFile(f, dynamic_cast(n->GetChild(i++).operator->()))) + ; } } // end anonymous namespace @@ -965,8 +1008,9 @@ void GameTreeRep::WriteEfgFile(std::ostream &p_file) const { p_file << "EFG 2 R"; p_file << " \"" << EscapeQuotes(GetTitle()) << "\" { "; - for (int i = 1; i <= m_players.Length(); i++) + for (int i = 1; i <= m_players.Length(); i++) { p_file << '"' << EscapeQuotes(m_players[i]->m_label) << "\" "; + } p_file << "}\n"; p_file << "\"" << EscapeQuotes(GetComment()) << "\"\n\n"; @@ -977,13 +1021,13 @@ void GameTreeRep::WriteEfgFile(std::ostream &p_file, const GameNode &p_root) con { p_file << "EFG 2 R"; p_file << " \"" << EscapeQuotes(GetTitle()) << "\" { "; - for (int i = 1; i <= m_players.Length(); i++) + for (int i = 1; i <= m_players.Length(); i++) { p_file << '"' << EscapeQuotes(m_players[i]->m_label) << "\" "; + } p_file << "}\n"; p_file << "\"" << EscapeQuotes(GetComment()) << "\"\n\n"; - Gambit::WriteEfgFile(p_file, - dynamic_cast(p_root.operator->())); + Gambit::WriteEfgFile(p_file, dynamic_cast(p_root.operator->())); } void GameTreeRep::WriteNfgFile(std::ostream &p_file) const @@ -1001,8 +1045,9 @@ PVector GameTreeRep::NumActions() const { Array foo(m_players.Length()); int i; - for (i = 1; i <= m_players.Length(); i++) + for (i = 1; i <= m_players.Length(); i++) { foo[i] = m_players[i]->m_infosets.Length(); + } PVector bar(foo); for (i = 1; i <= m_players.Length(); i++) { @@ -1067,7 +1112,7 @@ GamePlayer GameTreeRep::NewPlayer() GameInfoset GameTreeRep::GetInfoset(int p_index) const { int index = 1; - for (auto player: m_players) { + for (auto player : m_players) { for (auto infoset : player->m_infosets) { if (index++ == p_index) { return infoset; @@ -1079,12 +1124,12 @@ GameInfoset GameTreeRep::GetInfoset(int p_index) const Array GameTreeRep::GetInfosets() const { - auto infosets = Array(std::accumulate( - m_players.begin(), m_players.end(), 0, - [](int ct, GamePlayerRep *player) { return ct + player->NumInfosets(); })); + auto infosets = Array( + std::accumulate(m_players.begin(), m_players.end(), 0, + [](int ct, GamePlayerRep *player) { return ct + player->NumInfosets(); })); int i = 1; - for (auto player: m_players) { - for (auto infoset: player->m_infosets) { + for (auto player : m_players) { + for (auto infoset : player->m_infosets) { infosets[i++] = infoset; } } @@ -1103,7 +1148,7 @@ Array GameTreeRep::NumInfosets() const GameAction GameTreeRep::GetAction(int p_index) const { int index = 1; - for (auto player: m_players) { + for (auto player : m_players) { for (auto infoset : player->m_infosets) { for (auto action : infoset->m_actions) { if (index++ == p_index) { @@ -1115,7 +1160,6 @@ GameAction GameTreeRep::GetAction(int p_index) const throw IndexException(); } - //------------------------------------------------------------------------ // GameTreeRep: Outcomes //------------------------------------------------------------------------ @@ -1139,18 +1183,14 @@ namespace { int CountNodes(GameNode p_node) { int num = 1; - for (int i = 1; i <= p_node->NumChildren(); - num += CountNodes(p_node->GetChild(i++))); + for (int i = 1; i <= p_node->NumChildren(); num += CountNodes(p_node->GetChild(i++))) + ; return num; } -} // end anonymous namespace - -int GameTreeRep::NumNodes() const -{ - return CountNodes(m_root); -} +} // end anonymous namespace +int GameTreeRep::NumNodes() const { return CountNodes(m_root); } //------------------------------------------------------------------------ // GameTreeRep: Modification @@ -1162,7 +1202,8 @@ Game GameTreeRep::SetChanceProbs(const GameInfoset &p_infoset, const ArrayIsChanceInfoset()) { - throw UndefinedException("Action probabilities can only be specified for chance information sets"); + throw UndefinedException( + "Action probabilities can only be specified for chance information sets"); } if (p_infoset->NumActions() != p_probs.size()) { throw DimensionException("The number of probabilities given must match the number of actions"); @@ -1192,7 +1233,7 @@ Game GameTreeRep::NormalizeChanceProbs(const GameInfoset &m_infoset) } if (!m_infoset->IsChanceInfoset()) { throw UndefinedException( - "Action probabilities can only be normalized for chance information sets"); + "Action probabilities can only be normalized for chance information sets"); } IncrementVersion(); Rational sum(0); @@ -1234,10 +1275,12 @@ MixedStrategyProfile GameTreeRep::NewMixedStrategyProfile(const Ration if (!IsPerfectRecall()) { throw UndefinedException("Mixed strategies not supported for games with imperfect recall."); } - return StrategySupportProfile(const_cast(this)).NewMixedStrategyProfile(); + return StrategySupportProfile(const_cast(this)) + .NewMixedStrategyProfile(); } -MixedStrategyProfile GameTreeRep::NewMixedStrategyProfile(double, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameTreeRep::NewMixedStrategyProfile(double, const StrategySupportProfile &spt) const { if (!IsPerfectRecall()) { throw UndefinedException("Mixed strategies not supported for games with imperfect recall."); @@ -1245,7 +1288,8 @@ MixedStrategyProfile GameTreeRep::NewMixedStrategyProfile(double, const return MixedStrategyProfile(new TreeMixedStrategyProfileRep(spt)); } -MixedStrategyProfile GameTreeRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile& spt) const +MixedStrategyProfile +GameTreeRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &spt) const { if (!IsPerfectRecall()) { throw UndefinedException("Mixed strategies not supported for games with imperfect recall."); @@ -1253,7 +1297,6 @@ MixedStrategyProfile GameTreeRep::NewMixedStrategyProfile(const Ration return MixedStrategyProfile(new TreeMixedStrategyProfileRep(spt)); } - //======================================================================== // class TreePureStrategyProfileRep //======================================================================== @@ -1263,13 +1306,10 @@ class TreePureStrategyProfileRep : public PureStrategyProfileRep { PureStrategyProfileRep *Copy() const override; public: - TreePureStrategyProfileRep(const Game &p_game) - : PureStrategyProfileRep(p_game) { } + TreePureStrategyProfileRep(const Game &p_game) : PureStrategyProfileRep(p_game) {} void SetStrategy(const GameStrategy &) override; - GameOutcome GetOutcome() const override - { throw UndefinedException(); } - void SetOutcome(GameOutcome p_outcome) override - { throw UndefinedException(); } + GameOutcome GetOutcome() const override { throw UndefinedException(); } + void SetOutcome(GameOutcome p_outcome) override { throw UndefinedException(); } Rational GetPayoff(int pl) const override; Rational GetStrategyValue(const GameStrategy &) const override; }; @@ -1305,20 +1345,18 @@ Rational TreePureStrategyProfileRep::GetPayoff(int pl) const for (int iset = 1; iset <= player->NumInfosets(); iset++) { int act = m_profile[i]->m_behav[iset]; if (act) { - behav.SetAction(player->GetInfoset(iset)->GetAction(act)); + behav.SetAction(player->GetInfoset(iset)->GetAction(act)); } } } return behav.GetPayoff(pl); } -Rational -TreePureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const +Rational TreePureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const { PureStrategyProfile copy(Copy()); copy->SetStrategy(p_strategy); return copy->GetPayoff(p_strategy->GetPlayer()->GetNumber()); } - -} // end namespace Gambit +} // end namespace Gambit diff --git a/src/games/gametree.h b/src/games/gametree.h index d70a74762..eb3eb6cfb 100644 --- a/src/games/gametree.h +++ b/src/games/gametree.h @@ -39,10 +39,11 @@ class GameTreeActionRep : public GameActionRep { std::string m_label; GameTreeInfosetRep *m_infoset; - GameTreeActionRep(int p_number, const std::string &p_label, - GameTreeInfosetRep *p_infoset) - : m_number(p_number), m_label(p_label), m_infoset(p_infoset) { } - ~GameTreeActionRep() override = default; + GameTreeActionRep(int p_number, const std::string &p_label, GameTreeInfosetRep *p_infoset) + : m_number(p_number), m_label(p_label), m_infoset(p_infoset) + { + } + ~GameTreeActionRep() override = default; public: int GetNumber() const override { return m_number; } @@ -70,11 +71,10 @@ class GameTreeInfosetRep : public GameInfosetRep { GamePlayerRep *m_player; Array m_actions; Array m_members; - int flag, whichbranch { 0 }; + int flag, whichbranch{0}; Array m_probs; - GameTreeInfosetRep(GameTreeRep *p_efg, int p_number, GamePlayerRep *p_player, - int p_actions); + GameTreeInfosetRep(GameTreeRep *p_efg, int p_number, GamePlayerRep *p_player, int p_actions); ~GameTreeInfosetRep() override; /// Adds the node to the information set @@ -125,7 +125,6 @@ class GameTreeInfosetRep : public GameInfosetRep { void Reveal(GamePlayer) override; }; - class GameTreeNodeRep : public GameNodeRep { friend class GameTreeRep; friend class GameTreeActionRep; @@ -142,7 +141,7 @@ class GameTreeNodeRep : public GameNodeRep { GameTreeNodeRep *m_parent; GameOutcomeRep *outcome; Array children; - GameTreeNodeRep *whichbranch { nullptr }, *ptr { nullptr }; + GameTreeNodeRep *whichbranch{nullptr}, *ptr{nullptr}; GameTreeNodeRep(GameTreeRep *e, GameTreeNodeRep *p); ~GameTreeNodeRep() override; @@ -158,10 +157,12 @@ class GameTreeNodeRep : public GameNodeRep { int GetNumber() const override { return number; } int NumberInInfoset() const override - { return infoset->m_members.Find(const_cast(this)); } + { + return infoset->m_members.Find(const_cast(this)); + } - int NumChildren() const override { return children.size(); } - GameNode GetChild(int i) const override { return children[i]; } + int NumChildren() const override { return children.size(); } + GameNode GetChild(int i) const override { return children[i]; } GameNode GetChild(const GameAction &p_action) const override { if (p_action->GetInfoset() != infoset) { @@ -171,15 +172,14 @@ class GameTreeNodeRep : public GameNodeRep { } Array GetChildren() const override; - GameInfoset GetInfoset() const override { return infoset; } + GameInfoset GetInfoset() const override { return infoset; } void SetInfoset(GameInfoset) override; GameInfoset LeaveInfoset() override; bool IsTerminal() const override { return children.empty(); } - GamePlayer GetPlayer() const override - { return (infoset) ? infoset->GetPlayer() : nullptr; } + GamePlayer GetPlayer() const override { return (infoset) ? infoset->GetPlayer() : nullptr; } GameAction GetPriorAction() const override; // returns null if root node - GameNode GetParent() const override { return m_parent; } + GameNode GetParent() const override { return m_parent; } GameNode GetNextSibling() const override; GameNode GetPriorSibling() const override; @@ -203,11 +203,11 @@ class GameTreeNodeRep : public GameNodeRep { GameInfoset InsertMove(GameInfoset p_infoset) override; }; - class GameTreeRep : public GameExplicitRep { friend class GameTreeNodeRep; friend class GameTreeInfosetRep; friend class GameTreeActionRep; + protected: mutable bool m_computedValues, m_doCanon; GameTreeNodeRep *m_root; @@ -243,8 +243,12 @@ class GameTreeRep : public GameExplicitRep { bool IsPerfectRecall(GameInfoset &, GameInfoset &) const override; /// Turn on or off automatic canonicalization of the game void SetCanonicalization(bool p_doCanon) const - { m_doCanon = p_doCanon; - if (m_doCanon) const_cast(this)->Canonicalize(); } + { + m_doCanon = p_doCanon; + if (m_doCanon) { + const_cast(this)->Canonicalize(); + } + } //@} /// @name Players @@ -302,17 +306,18 @@ class GameTreeRep : public GameExplicitRep { PureStrategyProfile NewPureStrategyProfile() const override; MixedStrategyProfile NewMixedStrategyProfile(double) const override; MixedStrategyProfile NewMixedStrategyProfile(const Rational &) const override; - MixedStrategyProfile NewMixedStrategyProfile(double, const StrategySupportProfile&) const override; - MixedStrategyProfile NewMixedStrategyProfile(const Rational &, const StrategySupportProfile&) const override; - + MixedStrategyProfile + NewMixedStrategyProfile(double, const StrategySupportProfile &) const override; + MixedStrategyProfile + NewMixedStrategyProfile(const Rational &, const StrategySupportProfile &) const override; }; -template class TreeMixedStrategyProfileRep - : public MixedStrategyProfileRep { +template class TreeMixedStrategyProfileRep : public MixedStrategyProfileRep { public: explicit TreeMixedStrategyProfileRep(const StrategySupportProfile &p_support) : MixedStrategyProfileRep(p_support) - { } + { + } explicit TreeMixedStrategyProfileRep(const MixedBehaviorProfile &); ~TreeMixedStrategyProfileRep() override = default; @@ -322,6 +327,6 @@ template class TreeMixedStrategyProfileRep T GetPayoffDeriv(int pl, const GameStrategy &, const GameStrategy &) const override; }; -} +} // namespace Gambit -#endif // GAMETREE_H +#endif // GAMETREE_H diff --git a/src/games/nash.cc b/src/games/nash.cc index a3a74eed5..de22e97e0 100644 --- a/src/games/nash.cc +++ b/src/games/nash.cc @@ -24,9 +24,9 @@ namespace Gambit::Nash { -template void -MixedStrategyCSVRenderer::Render(const MixedStrategyProfile &p_profile, - const std::string &p_label) const +template +void MixedStrategyCSVRenderer::Render(const MixedStrategyProfile &p_profile, + const std::string &p_label) const { m_stream << p_label; for (size_t i = 1; i <= p_profile.MixedProfileLength(); i++) { @@ -35,9 +35,9 @@ MixedStrategyCSVRenderer::Render(const MixedStrategyProfile &p_profile, m_stream << std::endl; } -template void -MixedStrategyDetailRenderer::Render(const MixedStrategyProfile &p_profile, - const std::string &p_label) const +template +void MixedStrategyDetailRenderer::Render(const MixedStrategyProfile &p_profile, + const std::string &p_label) const { for (auto player : p_profile.GetGame()->GetPlayers()) { m_stream << "Strategy profile for player " << player->GetNumber() << ":\n"; @@ -56,8 +56,7 @@ MixedStrategyDetailRenderer::Render(const MixedStrategyProfile &p_profile, m_stream << lexical_cast(p_profile[strategy], m_numDecimals); m_stream << " "; m_stream << std::setw(11); - m_stream << lexical_cast(p_profile.GetPayoff(strategy), - m_numDecimals); + m_stream << lexical_cast(p_profile.GetPayoff(strategy), m_numDecimals); m_stream << std::endl; } } @@ -65,7 +64,7 @@ MixedStrategyDetailRenderer::Render(const MixedStrategyProfile &p_profile, template void BehavStrategyCSVRenderer::Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label) const + const std::string &p_label) const { m_stream << p_label; for (size_t i = 1; i <= p_profile.BehaviorProfileLength(); i++) { @@ -74,9 +73,9 @@ void BehavStrategyCSVRenderer::Render(const MixedBehaviorProfile &p_profil m_stream << std::endl; } -template void -BehavStrategyDetailRenderer::Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label) const +template +void BehavStrategyDetailRenderer::Render(const MixedBehaviorProfile &p_profile, + const std::string &p_label) const { for (auto player : p_profile.GetGame()->GetPlayers()) { m_stream << "Behavior profile for player " << player->GetNumber() << ":\n"; @@ -88,29 +87,28 @@ BehavStrategyDetailRenderer::Render(const MixedBehaviorProfile &p_profile, GameInfoset infoset = player->GetInfoset(iset); for (int act = 1; act <= infoset->NumActions(); act++) { - GameAction action = infoset->GetAction(act); - - if (!infoset->GetLabel().empty()) { - m_stream << std::setw(7) << infoset->GetLabel() << " "; - } - else { - m_stream << std::setw(7) << infoset->GetNumber() << " "; - } - if (!action->GetLabel().empty()) { - m_stream << std::setw(7) << action->GetLabel() << " "; - } - else { - m_stream << std::setw(7) << action->GetNumber() << " "; - } - m_stream << std::setw(11); - m_stream << lexical_cast(p_profile(player->GetNumber(), - iset, act), - m_numDecimals); - m_stream << " "; - m_stream << std::setw(11); - m_stream << lexical_cast(p_profile.GetPayoff(infoset->GetAction(act)), - m_numDecimals); - m_stream << std::endl; + GameAction action = infoset->GetAction(act); + + if (!infoset->GetLabel().empty()) { + m_stream << std::setw(7) << infoset->GetLabel() << " "; + } + else { + m_stream << std::setw(7) << infoset->GetNumber() << " "; + } + if (!action->GetLabel().empty()) { + m_stream << std::setw(7) << action->GetLabel() << " "; + } + else { + m_stream << std::setw(7) << action->GetNumber() << " "; + } + m_stream << std::setw(11); + m_stream << lexical_cast(p_profile(player->GetNumber(), iset, act), + m_numDecimals); + m_stream << " "; + m_stream << std::setw(11); + m_stream << lexical_cast(p_profile.GetPayoff(infoset->GetAction(act)), + m_numDecimals); + m_stream << std::endl; } } @@ -122,27 +120,27 @@ BehavStrategyDetailRenderer::Render(const MixedBehaviorProfile &p_profile, GameInfoset infoset = player->GetInfoset(iset); for (int n = 1; n <= infoset->NumMembers(); n++) { - GameNode node = infoset->GetMember(n); - if (!infoset->GetLabel().empty()) { - m_stream << std::setw(7) << infoset->GetLabel() << " "; - } - else { - m_stream << std::setw(7) << infoset->GetNumber() << " "; - } - if (!node->GetLabel().empty()) { - m_stream << std::setw(7) << node->GetLabel() << " "; - } - else { - m_stream << std::setw(7) << node->GetNumber() << " "; - } - m_stream << std::setw(11); - m_stream << lexical_cast(p_profile.GetBeliefProb(infoset->GetMember(n)), - m_numDecimals); - m_stream << " "; - m_stream << std::setw(11); - m_stream << lexical_cast(p_profile.GetRealizProb(infoset->GetMember(n)), - m_numDecimals); - m_stream << std::endl; + GameNode node = infoset->GetMember(n); + if (!infoset->GetLabel().empty()) { + m_stream << std::setw(7) << infoset->GetLabel() << " "; + } + else { + m_stream << std::setw(7) << infoset->GetNumber() << " "; + } + if (!node->GetLabel().empty()) { + m_stream << std::setw(7) << node->GetLabel() << " "; + } + else { + m_stream << std::setw(7) << node->GetNumber() << " "; + } + m_stream << std::setw(11); + m_stream << lexical_cast(p_profile.GetBeliefProb(infoset->GetMember(n)), + m_numDecimals); + m_stream << " "; + m_stream << std::setw(11); + m_stream << lexical_cast(p_profile.GetRealizProb(infoset->GetMember(n)), + m_numDecimals); + m_stream << std::endl; } } m_stream << std::endl; @@ -173,10 +171,9 @@ template class BehavStrategyCSVRenderer; template class BehavStrategyDetailRenderer; template class BehavStrategyDetailRenderer; - - template -StrategySolver::StrategySolver(std::shared_ptr > p_onEquilibrium /* = 0 */) +StrategySolver::StrategySolver( + std::shared_ptr> p_onEquilibrium /* = 0 */) : m_onEquilibrium(p_onEquilibrium) { if (m_onEquilibrium.get() == nullptr) { @@ -185,7 +182,7 @@ StrategySolver::StrategySolver(std::shared_ptr > p } template -BehavSolver::BehavSolver(std::shared_ptr > p_onEquilibrium /* = 0 */) +BehavSolver::BehavSolver(std::shared_ptr> p_onEquilibrium /* = 0 */) : m_onEquilibrium(p_onEquilibrium) { if (m_onEquilibrium.get() == nullptr) { @@ -194,28 +191,31 @@ BehavSolver::BehavSolver(std::shared_ptr > p_onEqu } template -BehavViaStrategySolver::BehavViaStrategySolver(std::shared_ptr > p_solver, - std::shared_ptr > p_onEquilibrium /* = 0 */) +BehavViaStrategySolver::BehavViaStrategySolver( + std::shared_ptr> p_solver, + std::shared_ptr> p_onEquilibrium /* = 0 */) : BehavSolver(p_onEquilibrium), m_solver(p_solver) -{ } +{ +} -template List > -BehavViaStrategySolver::Solve(const Game &p_game) const +template +List> BehavViaStrategySolver::Solve(const Game &p_game) const { - List > output = m_solver->Solve(p_game); - List > solutions; + List> output = m_solver->Solve(p_game); + List> solutions; for (const auto &profile : output) { solutions.push_back(MixedBehaviorProfile(profile)); } return solutions; } - template -SubgameBehavSolver::SubgameBehavSolver(std::shared_ptr > p_solver, - std::shared_ptr > p_onEquilibrium /* = 0 */) +SubgameBehavSolver::SubgameBehavSolver( + std::shared_ptr> p_solver, + std::shared_ptr> p_onEquilibrium /* = 0 */) : BehavSolver(p_onEquilibrium), m_solver(p_solver) -{ } +{ +} // A nested anonymous namespace to privatize these functions @@ -231,12 +231,12 @@ void ChildSubgames(const GameNode &p_node, List &p_list) p_list.push_back(p_node); } else { - for (int i = 1; i <= p_node->NumChildren(); - ChildSubgames(p_node->GetChild(i++), p_list)); + for (int i = 1; i <= p_node->NumChildren(); ChildSubgames(p_node->GetChild(i++), p_list)) + ; } } -} // end nested anonymous namespace +} // namespace // // Some general notes on the strategy for solving by subgames: @@ -255,40 +255,37 @@ void ChildSubgames(const GameNode &p_node, List &p_list) // at the end of the computation // -template -void SubgameBehavSolver::SolveSubgames(const Game &p_game, - const DVector &p_templateSolution, - const GameNode &n, - List > &solns, +template +void SubgameBehavSolver::SolveSubgames(const Game &p_game, const DVector &p_templateSolution, + const GameNode &n, List> &solns, List &values) const { - List > thissolns; + List> thissolns; thissolns.push_back(p_templateSolution); - ((Vector &) thissolns[1]).operator=(T(0)); + ((Vector &)thissolns[1]).operator=(T(0)); List subroots; for (int i = 1; i <= n->NumChildren(); i++) { ChildSubgames(n->GetChild(i), subroots); } - List > subrootvalues; + List> subrootvalues; subrootvalues.push_back(Array(subroots.Length())); - for (int i = 1; i <= subroots.Length(); i++) { - //printf("Looking at subgame %d of %d\n", i, subroots.Length()); - List > subsolns; + for (int i = 1; i <= subroots.Length(); i++) { + // printf("Looking at subgame %d of %d\n", i, subroots.Length()); + List> subsolns; List subvalues; - SolveSubgames(p_game, p_templateSolution, - subroots[i], subsolns, subvalues); + SolveSubgames(p_game, p_templateSolution, subroots[i], subsolns, subvalues); - if (subsolns.empty()) { - solns = List >(); + if (subsolns.empty()) { + solns = List>(); return; } - List > newsolns; - List > newsubrootvalues; + List> newsolns; + List> newsubrootvalues; for (int soln = 1; soln <= thissolns.Length(); soln++) { for (int subsoln = 1; subsoln <= subsolns.Length(); subsoln++) { @@ -306,11 +303,11 @@ void SubgameBehavSolver::SolveSubgames(const Game &p_game, thissolns = newsolns; subrootvalues = newsubrootvalues; - //printf("Finished solving subgame %d\n", i); + // printf("Finished solving subgame %d\n", i); } - for (int soln = 1; soln <= thissolns.Length(); soln++) { - //printf("Analyzing scenario %d of %d\n", soln, thissolns.Length()); + for (int soln = 1; soln <= thissolns.Length(); soln++) { + // printf("Analyzing scenario %d of %d\n", soln, thissolns.Length()); for (int i = 1; i <= subroots.Length(); i++) { subroots[i]->SetOutcome(subrootvalues[soln][i]); } @@ -321,43 +318,43 @@ void SubgameBehavSolver::SolveSubgames(const Game &p_game, subgame->GetRoot()->SetOutcome(nullptr); BehaviorSupportProfile subsupport(subgame); - List > sol = m_solver->Solve(p_game); + List> sol = m_solver->Solve(p_game); - if (sol.empty()) { - solns = List >(); + if (sol.empty()) { + solns = List>(); return; } // Put behavior profile in "total" solution here... - for (int solno = 1; solno <= sol.Length(); solno++) { + for (int solno = 1; solno <= sol.Length(); solno++) { solns.push_back(thissolns[soln]); - for (int pl = 1; pl <= subgame->NumPlayers(); pl++) { - GamePlayer subplayer = subgame->GetPlayer(pl); - GamePlayer player = p_game->GetPlayer(pl); - - for (int iset = 1; iset <= subplayer->NumInfosets(); iset++) { - GameInfoset subinfoset = subplayer->GetInfoset(iset); - - for (int j = 1; j <= player->NumInfosets(); j++) { - if (subinfoset->GetLabel() == player->GetInfoset(j)->GetLabel()) { - int id = atoi(subinfoset->GetLabel().c_str()); - for (int act = 1; act <= subsupport.NumActions(pl, iset); act++) { - int actno = subsupport.GetAction(pl, iset, act)->GetNumber(); - solns[solns.Length()](pl, id, actno) = sol[solno](pl, iset, act); - } - break; - } - } - } + for (int pl = 1; pl <= subgame->NumPlayers(); pl++) { + GamePlayer subplayer = subgame->GetPlayer(pl); + GamePlayer player = p_game->GetPlayer(pl); + + for (int iset = 1; iset <= subplayer->NumInfosets(); iset++) { + GameInfoset subinfoset = subplayer->GetInfoset(iset); + + for (int j = 1; j <= player->NumInfosets(); j++) { + if (subinfoset->GetLabel() == player->GetInfoset(j)->GetLabel()) { + int id = atoi(subinfoset->GetLabel().c_str()); + for (int act = 1; act <= subsupport.NumActions(pl, iset); act++) { + int actno = subsupport.GetAction(pl, iset, act)->GetNumber(); + solns[solns.Length()](pl, id, actno) = sol[solno](pl, iset, act); + } + break; + } + } + } } Vector subval(subgame->NumPlayers()); GameOutcome outcome = n->GetOutcome(); - for (int pl = 1; pl <= subgame->NumPlayers(); pl++) { - subval[pl] = sol[solno].GetPayoff(pl); - if (outcome) { - subval[pl] += static_cast(outcome->GetPayoff(pl)); + for (int pl = 1; pl <= subgame->NumPlayers(); pl++) { + subval[pl] = sol[solno].GetPayoff(pl); + if (outcome) { + subval[pl] += static_cast(outcome->GetPayoff(pl)); } } @@ -368,16 +365,15 @@ void SubgameBehavSolver::SolveSubgames(const Game &p_game, values.push_back(ov); } - //printf("Finished with scenario %d of %d; total solutions so far = %d\n", - //soln, thissolns.Length(), solns.Length()); + // printf("Finished with scenario %d of %d; total solutions so far = %d\n", + // soln, thissolns.Length(), solns.Length()); } n->DeleteTree(); } template -List > -SubgameBehavSolver::Solve(const Game &p_game) const +List> SubgameBehavSolver::Solve(const Game &p_game) const { Game efg = p_game->GetRoot()->CopySubgame(); @@ -387,12 +383,11 @@ SubgameBehavSolver::Solve(const Game &p_game) const } } - List > vectors; + List> vectors; List values; - SolveSubgames(efg, DVector(efg->NumActions()), - efg->GetRoot(), vectors, values); + SolveSubgames(efg, DVector(efg->NumActions()), efg->GetRoot(), vectors, values); - List > solutions; + List> solutions; for (int i = 1; i <= vectors.Length(); i++) { solutions.push_back(MixedBehaviorProfile(p_game)); for (int j = 1; j <= vectors[i].Length(); j++) { diff --git a/src/games/nash.h b/src/games/nash.h index 63976bef5..7bab8ce06 100644 --- a/src/games/nash.h +++ b/src/games/nash.h @@ -30,17 +30,17 @@ namespace Gambit { namespace Nash { -using StrategyCallbackType = std::function &, const std::string &)>; +using StrategyCallbackType = + std::function &, const std::string &)>; /// @brief A fallback callback function for mixed strategy profiles that does nothing -inline void NullStrategyCallback(const MixedStrategyProfile &, const std::string &) -{ } +inline void NullStrategyCallback(const MixedStrategyProfile &, const std::string &) {} -using BehaviorCallbackType = std::function &, const std::string &)>; +using BehaviorCallbackType = + std::function &, const std::string &)>; /// @brief A fallback callback function for mixed behavior profiles that does nothing -inline void NullBehaviorCallback(const MixedBehaviorProfile &, const std::string &) -{ } +inline void NullBehaviorCallback(const MixedBehaviorProfile &, const std::string &) {} //======================================================================== // Profile renderer classes @@ -50,9 +50,9 @@ template class StrategyProfileRenderer { public: virtual ~StrategyProfileRenderer() = default; virtual void Render(const MixedStrategyProfile &p_profile, - const std::string &p_label = "NE") const = 0; + const std::string &p_label = "NE") const = 0; virtual void Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label = "NE") const = 0; + const std::string &p_label = "NE") const = 0; }; // @@ -64,42 +64,47 @@ template class MixedStrategyRenderer : public StrategyProfileRenderer< public: ~MixedStrategyRenderer() override = default; void Render(const MixedStrategyProfile &p_profile, - const std::string &p_label = "NE") const override = 0; + const std::string &p_label = "NE") const override = 0; void Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label = "NE") const override - { Render(p_profile.ToMixedProfile(), p_label); } + const std::string &p_label = "NE") const override + { + Render(p_profile.ToMixedProfile(), p_label); + } }; -template -class MixedStrategyNullRenderer : public MixedStrategyRenderer { +template class MixedStrategyNullRenderer : public MixedStrategyRenderer { public: ~MixedStrategyNullRenderer() override = default; void Render(const MixedStrategyProfile &p_profile, - const std::string &p_label = "NE") const override { } + const std::string &p_label = "NE") const override + { + } }; -template -class MixedStrategyCSVRenderer : public MixedStrategyRenderer { +template class MixedStrategyCSVRenderer : public MixedStrategyRenderer { public: explicit MixedStrategyCSVRenderer(std::ostream &p_stream, int p_numDecimals = 6) - : m_stream(p_stream), m_numDecimals(p_numDecimals) { } + : m_stream(p_stream), m_numDecimals(p_numDecimals) + { + } ~MixedStrategyCSVRenderer() override = default; void Render(const MixedStrategyProfile &p_profile, - const std::string &p_label = "NE") const override; + const std::string &p_label = "NE") const override; private: std::ostream &m_stream; int m_numDecimals; }; -template -class MixedStrategyDetailRenderer : public MixedStrategyRenderer { +template class MixedStrategyDetailRenderer : public MixedStrategyRenderer { public: explicit MixedStrategyDetailRenderer(std::ostream &p_stream, int p_numDecimals = 6) - : m_stream(p_stream), m_numDecimals(p_numDecimals) { } + : m_stream(p_stream), m_numDecimals(p_numDecimals) + { + } ~MixedStrategyDetailRenderer() override = default; void Render(const MixedStrategyProfile &p_profile, - const std::string &p_label = "NE") const override; + const std::string &p_label = "NE") const override; private: std::ostream &m_stream; @@ -113,42 +118,47 @@ template class BehavStrategyRenderer : public StrategyProfileRenderer< public: ~BehavStrategyRenderer() override = default; void Render(const MixedStrategyProfile &p_profile, - const std::string &p_label = "NE") const override - { Render(MixedBehaviorProfile(p_profile), p_label); } + const std::string &p_label = "NE") const override + { + Render(MixedBehaviorProfile(p_profile), p_label); + } void Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label = "NE") const override = 0; + const std::string &p_label = "NE") const override = 0; }; -template -class BehavStrategyNullRenderer : public BehavStrategyRenderer { +template class BehavStrategyNullRenderer : public BehavStrategyRenderer { public: ~BehavStrategyNullRenderer() override = default; void Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label = "NE") const override { } + const std::string &p_label = "NE") const override + { + } }; -template -class BehavStrategyCSVRenderer : public BehavStrategyRenderer { +template class BehavStrategyCSVRenderer : public BehavStrategyRenderer { public: explicit BehavStrategyCSVRenderer(std::ostream &p_stream, int p_numDecimals = 6) - : m_stream(p_stream), m_numDecimals(p_numDecimals) { } + : m_stream(p_stream), m_numDecimals(p_numDecimals) + { + } ~BehavStrategyCSVRenderer() override = default; void Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label = "NE") const override; + const std::string &p_label = "NE") const override; private: std::ostream &m_stream; int m_numDecimals; }; -template -class BehavStrategyDetailRenderer : public BehavStrategyRenderer { +template class BehavStrategyDetailRenderer : public BehavStrategyRenderer { public: explicit BehavStrategyDetailRenderer(std::ostream &p_stream, int p_numDecimals = 6) - : m_stream(p_stream), m_numDecimals(p_numDecimals) { } + : m_stream(p_stream), m_numDecimals(p_numDecimals) + { + } ~BehavStrategyDetailRenderer() override = default; void Render(const MixedBehaviorProfile &p_profile, - const std::string &p_label = "NE") const override; + const std::string &p_label = "NE") const override; private: std::ostream &m_stream; @@ -163,24 +173,24 @@ class BehavStrategyDetailRenderer : public BehavStrategyRenderer { template class StrategySolver { public: - explicit StrategySolver(std::shared_ptr > p_onEquilibrium = nullptr); - virtual ~StrategySolver() = default; + explicit StrategySolver(std::shared_ptr> p_onEquilibrium = nullptr); + virtual ~StrategySolver() = default; - virtual List > Solve(const Game &) const = 0; + virtual List> Solve(const Game &) const = 0; protected: - std::shared_ptr > m_onEquilibrium; + std::shared_ptr> m_onEquilibrium; }; template class BehavSolver { public: - explicit BehavSolver(std::shared_ptr > p_onEquilibrium = nullptr); - virtual ~BehavSolver() = default; + explicit BehavSolver(std::shared_ptr> p_onEquilibrium = nullptr); + virtual ~BehavSolver() = default; - virtual List > Solve(const Game &) const = 0; + virtual List> Solve(const Game &) const = 0; protected: - std::shared_ptr > m_onEquilibrium; + std::shared_ptr> m_onEquilibrium; }; // @@ -189,33 +199,31 @@ template class BehavSolver { // template class BehavViaStrategySolver : public BehavSolver { public: - explicit BehavViaStrategySolver(std::shared_ptr > p_solver, - std::shared_ptr > p_onEquilibrium = 0); + explicit BehavViaStrategySolver(std::shared_ptr> p_solver, + std::shared_ptr> p_onEquilibrium = 0); ~BehavViaStrategySolver() override = default; - List > Solve(const Game &) const override; + List> Solve(const Game &) const override; protected: - std::shared_ptr > m_solver; + std::shared_ptr> m_solver; }; template class SubgameBehavSolver : public BehavSolver { public: - explicit SubgameBehavSolver(std::shared_ptr > p_solver, - std::shared_ptr > p_onEquilibrium = nullptr); - ~SubgameBehavSolver() override = default; + explicit SubgameBehavSolver( + std::shared_ptr> p_solver, + std::shared_ptr> p_onEquilibrium = nullptr); + ~SubgameBehavSolver() override = default; - List > Solve(const Game &) const override; + List> Solve(const Game &) const override; protected: - std::shared_ptr > m_solver; + std::shared_ptr> m_solver; private: - void SolveSubgames(const Game &p_game, - const DVector &p_templateSolution, - const GameNode &n, - List > &solns, - List &values) const; + void SolveSubgames(const Game &p_game, const DVector &p_templateSolution, const GameNode &n, + List> &solns, List &values) const; }; // @@ -229,9 +237,8 @@ class EquilibriumLimitReached : public Exception { const char *what() const noexcept override { return "Reached target number of equilibria"; } }; -} // namespace Gambit::Nash +} // namespace Nash -} // namespace Gambit +} // namespace Gambit - -#endif // LIBGAMBIT_NASH_H +#endif // LIBGAMBIT_NASH_H diff --git a/src/games/number.h b/src/games/number.h index 08fb0f742..9a57d0b5a 100644 --- a/src/games/number.h +++ b/src/games/number.h @@ -45,21 +45,22 @@ class Number { public: /// Construct a new number with representation "0" - Number() - : m_text("0"), m_rational(0), m_double(0.0) { } + Number() : m_text("0"), m_rational(0), m_double(0.0) {} /// Construct a new number with representation p_text /// @param p_text The text representation of the number explicit Number(const std::string &p_text) : m_text(p_text), m_rational(lexical_cast(p_text)), m_double(static_cast(m_rational)) - { } + { + } /// Construct a new number with rational representation p_rational /// @param p_rational The rational representation of the number explicit Number(const Rational &p_rational) : m_text(lexical_cast(p_rational)), m_rational(p_rational), m_double(static_cast(p_rational)) - { } + { + } ~Number() = default; Number &operator=(const Number &p_number) = default; @@ -85,6 +86,6 @@ class Number { explicit operator const std::string &() const { return m_text; } }; -} +} // namespace Gambit #endif // LIBGAMBIT_NUMBER_H diff --git a/src/games/stratmixed.h b/src/games/stratmixed.h index 341deb4d1..8f42900d3 100644 --- a/src/games/stratmixed.h +++ b/src/games/stratmixed.h @@ -45,26 +45,30 @@ template class MixedStrategyProfileRep { void Randomize(int p_denom); /// Returns the probability the strategy is played const T &operator[](const GameStrategy &p_strategy) const - { return m_probs[m_support.m_profileIndex[p_strategy->GetId()]]; } + { + return m_probs[m_support.m_profileIndex[p_strategy->GetId()]]; + } /// Returns the probability the strategy is played T &operator[](const GameStrategy &p_strategy) - { return m_probs[m_support.m_profileIndex[p_strategy->GetId()]]; } + { + return m_probs[m_support.m_profileIndex[p_strategy->GetId()]]; + } virtual T GetPayoff(int pl) const = 0; virtual T GetPayoffDeriv(int pl, const GameStrategy &) const = 0; virtual T GetPayoffDeriv(int pl, const GameStrategy &, const GameStrategy &) const = 0; - T GetPayoff(const GamePlayer &p_player) const - { return GetPayoff(p_player->GetNumber()); } + T GetPayoff(const GamePlayer &p_player) const { return GetPayoff(p_player->GetNumber()); } T GetPayoff(const GameStrategy &p_strategy) const - { return GetPayoffDeriv(p_strategy->GetPlayer()->GetNumber(), p_strategy); } + { + return GetPayoffDeriv(p_strategy->GetPlayer()->GetNumber(), p_strategy); + } T GetRegret(const GameStrategy &) const; T GetRegret(const GamePlayer &) const; T GetMaxRegret() const; }; - /// \brief A probability distribution over strategies in a game /// /// A probability distribution over strategies, such that each player @@ -77,9 +81,7 @@ template class MixedStrategyProfile { public: /// @name Lifecycle //@{ - explicit MixedStrategyProfile(MixedStrategyProfileRep *p_rep) - : m_rep(p_rep) - { } + explicit MixedStrategyProfile(MixedStrategyProfileRep *p_rep) : m_rep(p_rep) {} /// Convert a behavior strategy profile to a mixed strategy profile explicit MixedStrategyProfile(const MixedBehaviorProfile &); @@ -101,38 +103,66 @@ template class MixedStrategyProfile { MixedStrategyProfile &operator=(const MixedStrategyProfile &); MixedStrategyProfile &operator=(const Vector &v) - { m_rep->m_probs = v; return *this; } + { + m_rep->m_probs = v; + return *this; + } MixedStrategyProfile &operator=(const T &c) - { m_rep->m_probs = c; return *this; } + { + m_rep->m_probs = c; + return *this; + } //@} /// @name Operator overloading //@{ /// Test for the equality of two profiles bool operator==(const MixedStrategyProfile &p_profile) const - { return (m_rep->m_support == p_profile.m_rep->m_support && - m_rep->m_probs == p_profile.m_rep->m_probs); } + { + return (m_rep->m_support == p_profile.m_rep->m_support && + m_rep->m_probs == p_profile.m_rep->m_probs); + } /// Test for the inequality of two profiles bool operator!=(const MixedStrategyProfile &p_profile) const - { return (m_rep->m_support != p_profile.m_rep->m_support || - m_rep->m_probs != p_profile.m_rep->m_probs); } + { + return (m_rep->m_support != p_profile.m_rep->m_support || + m_rep->m_probs != p_profile.m_rep->m_probs); + } /// Vector-style access to probabilities - const T &operator[](int i) const { CheckVersion(); return m_rep->m_probs[i]; } + const T &operator[](int i) const + { + CheckVersion(); + return m_rep->m_probs[i]; + } /// Vector-style access to probabilities - T &operator[](int i) { CheckVersion(); return m_rep->m_probs[i]; } + T &operator[](int i) + { + CheckVersion(); + return m_rep->m_probs[i]; + } /// Returns the probability the strategy is played const T &operator[](const GameStrategy &p_strategy) const - { CheckVersion(); return m_rep->operator[](p_strategy); } + { + CheckVersion(); + return m_rep->operator[](p_strategy); + } /// Returns the probability the strategy is played T &operator[](const GameStrategy &p_strategy) - { CheckVersion(); return m_rep->operator[](p_strategy); } + { + CheckVersion(); + return m_rep->operator[](p_strategy); + } /// Returns the mixed strategy for the player Vector operator[](const GamePlayer &p_player) const; - explicit operator const Vector &() const { CheckVersion(); return m_rep->m_probs; } + explicit operator const Vector &() const + { + CheckVersion(); + return m_rep->m_probs; + } //@} /// @name General data access @@ -140,26 +170,47 @@ template class MixedStrategyProfile { /// Returns the game on which the profile is defined Game GetGame() const { return m_rep->m_support.GetGame(); } /// Returns the support on which the profile is defined - const StrategySupportProfile &GetSupport() const { CheckVersion(); return m_rep->m_support; } + const StrategySupportProfile &GetSupport() const + { + CheckVersion(); + return m_rep->m_support; + } /// Returns whether the profile has been invalidated by a subsequent revision to the game bool IsInvalidated() const - { return m_rep->m_gameversion != m_rep->m_support.GetGame()->GetVersion(); } + { + return m_rep->m_gameversion != m_rep->m_support.GetGame()->GetVersion(); + } /// Sets all strategies for each player to equal probabilities - void SetCentroid() { CheckVersion(); m_rep->SetCentroid(); } + void SetCentroid() + { + CheckVersion(); + m_rep->SetCentroid(); + } /// Create a new mixed strategy profile where strategies are played /// in the same proportions, but with probabilities for each player /// summing to one. MixedStrategyProfile Normalize() const - { CheckVersion(); return MixedStrategyProfile(m_rep->Normalize()); } + { + CheckVersion(); + return MixedStrategyProfile(m_rep->Normalize()); + } /// Generate a random mixed strategy profile according to the uniform distribution - void Randomize() { CheckVersion(); m_rep->Randomize(); } + void Randomize() + { + CheckVersion(); + m_rep->Randomize(); + } /// Generate a random mixed strategy profile according to the uniform distribution /// on a grid with spacing p_denom - void Randomize(int p_denom) { CheckVersion(); m_rep->Randomize(p_denom); } + void Randomize(int p_denom) + { + CheckVersion(); + m_rep->Randomize(p_denom); + } /// Returns the total number of strategies in the profile size_t MixedProfileLength() const { return m_rep->m_probs.size(); } @@ -171,29 +222,45 @@ template class MixedStrategyProfile { /// @name Computation of interesting quantities //@{ /// Computes the payoff of the profile to player 'pl' - T GetPayoff(int pl) const { CheckVersion(); return m_rep->GetPayoff(pl); } + T GetPayoff(int pl) const + { + CheckVersion(); + return m_rep->GetPayoff(pl); + } /// Computes the payoff of the profile to the player T GetPayoff(const GamePlayer &p_player) const - { CheckVersion(); return GetPayoff(p_player->GetNumber()); } + { + CheckVersion(); + return GetPayoff(p_player->GetNumber()); + } /// \brief Computes the derivative of the player's payoff /// /// Computes the derivative of the payoff to the player with respect /// to the probability the strategy is played T GetPayoffDeriv(int pl, const GameStrategy &s) const - { CheckVersion(); return m_rep->GetPayoffDeriv(pl, s); } + { + CheckVersion(); + return m_rep->GetPayoffDeriv(pl, s); + } /// \brief Computes the second derivative of the player's payoff /// /// Computes the second derivative of the payoff to the player, /// with respect to the probabilities with which the strategies are played T GetPayoffDeriv(int pl, const GameStrategy &s1, const GameStrategy &s2) const - { CheckVersion(); return m_rep->GetPayoffDeriv(pl, s1, s2); } + { + CheckVersion(); + return m_rep->GetPayoffDeriv(pl, s1, s2); + } /// Computes the payoff to playing the pure strategy against the profile T GetPayoff(const GameStrategy &p_strategy) const - { CheckVersion(); return GetPayoffDeriv(p_strategy->GetPlayer()->GetNumber(), p_strategy); } + { + CheckVersion(); + return GetPayoffDeriv(p_strategy->GetPlayer()->GetNumber(), p_strategy); + } /// @brief Computes the regret to playing \p p_strategy /// @details Computes the regret to the player of playing strategy \p p_strategy @@ -204,7 +271,10 @@ template class MixedStrategyProfile { /// @sa GetRegret(const GamePlayer &) const; /// GetMaxRegret() const T GetRegret(const GameStrategy &p_strategy) const - { CheckVersion(); return m_rep->GetRegret(p_strategy); } + { + CheckVersion(); + return m_rep->GetRegret(p_strategy); + } /// @brief Computes the regret for player \p p_player /// @details Computes the regret to the player of playing their mixed strategy @@ -215,14 +285,20 @@ template class MixedStrategyProfile { /// @sa GetRegret(const GameStrategy &) const; /// GetMaxRegret() const T GetRegret(const GamePlayer &p_player) const - { CheckVersion(); return m_rep->GetRegret(p_player); } + { + CheckVersion(); + return m_rep->GetRegret(p_player); + } /// @brief Computes the maximum regret to any player in the profile /// @details Computes the maximum of the regrets of the players in the profile. /// @sa GetRegret(const GamePlayer &) const; /// GetRegret(const GameStrategy &) const T GetMaxRegret() const - { CheckVersion(); return m_rep->GetMaxRegret(); } + { + CheckVersion(); + return m_rep->GetMaxRegret(); + } /// @brief Computes the Lyapunov value of the profile /// @details Computes the Lyapunov value of the profile. This is a nonnegative diff --git a/src/games/stratpure.cc b/src/games/stratpure.cc index a28608149..eec80258f 100644 --- a/src/games/stratpure.cc +++ b/src/games/stratpure.cc @@ -74,8 +74,7 @@ bool PureStrategyProfileRep::IsBestResponse(const GamePlayer &p_player) const return true; } -List -PureStrategyProfileRep::GetBestResponse(const GamePlayer &p_player) const +List PureStrategyProfileRep::GetBestResponse(const GamePlayer &p_player) const { auto strategy = p_player->GetStrategy(1); Rational max_payoff = GetStrategyValue(strategy); @@ -94,8 +93,7 @@ PureStrategyProfileRep::GetBestResponse(const GamePlayer &p_player) const return br; } -MixedStrategyProfile -PureStrategyProfileRep::ToMixedStrategyProfile() const +MixedStrategyProfile PureStrategyProfileRep::ToMixedStrategyProfile() const { MixedStrategyProfile temp(m_nfg->NewMixedStrategyProfile(Rational(0))); temp = Rational(0); @@ -114,20 +112,16 @@ PureStrategyProfileRep::ToMixedStrategyProfile() const //--------------------------------------------------------------------------- StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p_support) - : m_atEnd(false), m_support(p_support), - m_currentStrat(m_support.GetGame()->NumPlayers()), - m_profile(m_support.GetGame()->NewPureStrategyProfile()), - m_frozen1(0), m_frozen2(0) + : m_atEnd(false), m_support(p_support), m_currentStrat(m_support.GetGame()->NumPlayers()), + m_profile(m_support.GetGame()->NewPureStrategyProfile()), m_frozen1(0), m_frozen2(0) { First(); } -StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p_support, - int pl, int st) - : m_atEnd(false), m_support(p_support), - m_currentStrat(m_support.GetGame()->NumPlayers()), - m_profile(m_support.GetGame()->NewPureStrategyProfile()), - m_frozen1(pl), m_frozen2(0) +StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p_support, int pl, + int st) + : m_atEnd(false), m_support(p_support), m_currentStrat(m_support.GetGame()->NumPlayers()), + m_profile(m_support.GetGame()->NewPureStrategyProfile()), m_frozen1(pl), m_frozen2(0) { m_currentStrat[pl] = st; m_profile->SetStrategy(m_support.GetStrategy(pl, st)); @@ -136,25 +130,19 @@ StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p_support, const GameStrategy &p_strategy) - : m_atEnd(false), m_support(p_support), - m_currentStrat(p_support.GetGame()->NumPlayers()), + : m_atEnd(false), m_support(p_support), m_currentStrat(p_support.GetGame()->NumPlayers()), m_profile(p_support.GetGame()->NewPureStrategyProfile()), - m_frozen1(p_strategy->GetPlayer()->GetNumber()), - m_frozen2(0) + m_frozen1(p_strategy->GetPlayer()->GetNumber()), m_frozen2(0) { m_currentStrat[m_frozen1] = p_strategy->GetNumber(); m_profile->SetStrategy(p_strategy); First(); } - -StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p_support, - int pl1, int st1, - int pl2, int st2) - : m_atEnd(false), m_support(p_support), - m_currentStrat(m_support.GetGame()->NumPlayers()), - m_profile(m_support.GetGame()->NewPureStrategyProfile()), - m_frozen1(pl1), m_frozen2(pl2) +StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p_support, int pl1, + int st1, int pl2, int st2) + : m_atEnd(false), m_support(p_support), m_currentStrat(m_support.GetGame()->NumPlayers()), + m_profile(m_support.GetGame()->NewPureStrategyProfile()), m_frozen1(pl1), m_frozen2(pl2) { m_currentStrat[pl1] = st1; m_profile->SetStrategy(m_support.GetStrategy(pl1, st1)); @@ -170,7 +158,9 @@ StrategyProfileIterator::StrategyProfileIterator(const StrategySupportProfile &p void StrategyProfileIterator::First() { for (int pl = 1; pl <= m_support.GetGame()->NumPlayers(); pl++) { - if (pl == m_frozen1 || pl == m_frozen2) continue; + if (pl == m_frozen1 || pl == m_frozen2) { + continue; + } m_profile->SetStrategy(m_support.GetStrategy(pl, 1)); m_currentStrat[pl] = 1; } @@ -180,7 +170,7 @@ void StrategyProfileIterator::operator++() { int pl = 1; - while (true) { + while (true) { if (pl == m_frozen1 || pl == m_frozen2) { pl++; if (pl > m_support.GetGame()->NumPlayers()) { @@ -204,4 +194,4 @@ void StrategyProfileIterator::operator++() } } -} +} // namespace Gambit diff --git a/src/games/stratpure.h b/src/games/stratpure.h index 6564561d5..444f787f1 100644 --- a/src/games/stratpure.h +++ b/src/games/stratpure.h @@ -41,7 +41,7 @@ class PureStrategyProfileRep { protected: Game m_nfg; - Array m_profile; + Array m_profile; /// Construct a new strategy profile explicit PureStrategyProfileRep(const Game &p_game); @@ -56,16 +56,16 @@ class PureStrategyProfileRep { /// @name Data access and manipulation //@{ /// Get the index uniquely identifying the strategy profile - virtual long GetIndex() const - { throw UndefinedException(); } + virtual long GetIndex() const { throw UndefinedException(); } /// Get the strategy played by player pl - const GameStrategy &GetStrategy(int pl) const - { return m_profile[pl]; } + const GameStrategy &GetStrategy(int pl) const { return m_profile[pl]; } /// Get the strategy played by the player const GameStrategy &GetStrategy(const GamePlayer &p_player) const - { return m_profile[p_player->GetNumber()]; } + { + return m_profile[p_player->GetNumber()]; + } /// Set the strategy for a player virtual void SetStrategy(const GameStrategy &) = 0; @@ -80,8 +80,7 @@ class PureStrategyProfileRep { virtual Rational GetPayoff(int pl) const = 0; /// Get the payoff to the player resulting from the profile - Rational GetPayoff(const GamePlayer &p_player) const - { return GetPayoff(p_player->GetNumber()); } + Rational GetPayoff(const GamePlayer &p_player) const { return GetPayoff(p_player->GetNumber()); } /// Get the value of playing strategy against the profile virtual Rational GetStrategyValue(const GameStrategy &) const = 0; @@ -96,10 +95,10 @@ class PureStrategyProfileRep { bool IsBestResponse(const GamePlayer &p_player) const; /// Get the list of best response strategies for a player - List GetBestResponse(const GamePlayer &p_player) const; + List GetBestResponse(const GamePlayer &p_player) const; /// Convert to a mixed strategy representation - MixedStrategyProfile ToMixedStrategyProfile() const; + MixedStrategyProfile ToMixedStrategyProfile() const; //@} }; @@ -108,14 +107,11 @@ class PureStrategyProfile { PureStrategyProfileRep *rep; public: - PureStrategyProfile(const PureStrategyProfile &r) : rep(r.rep->Copy()) - {} + PureStrategyProfile(const PureStrategyProfile &r) : rep(r.rep->Copy()) {} - explicit PureStrategyProfile(PureStrategyProfileRep *p_rep) : rep(p_rep) - {} + explicit PureStrategyProfile(PureStrategyProfileRep *p_rep) : rep(p_rep) {} - ~PureStrategyProfile() - { delete rep; } + ~PureStrategyProfile() { delete rep; } PureStrategyProfile &operator=(const PureStrategyProfile &r) { @@ -126,11 +122,9 @@ class PureStrategyProfile { return *this; } - PureStrategyProfileRep *operator->() const - { return rep; } + PureStrategyProfileRep *operator->() const { return rep; } - explicit operator PureStrategyProfileRep *() const - { return rep; } + explicit operator PureStrategyProfileRep *() const { return rep; } }; /// This class iterates through the contingencies in a strategic game. @@ -141,6 +135,7 @@ class PureStrategyProfile { class StrategyProfileIterator { friend class GameRep; friend class GameTableRep; + private: bool m_atEnd; StrategySupportProfile m_support; @@ -161,8 +156,7 @@ class StrategyProfileIterator { /// Construct a new iterator on the support, fixing the given strategy StrategyProfileIterator(const StrategySupportProfile &, const GameStrategy &); /// Construct a new iterator on the support, fixing two players' strategies - StrategyProfileIterator(const StrategySupportProfile &s, - int pl1, int st1, int pl2, int st2); + StrategyProfileIterator(const StrategySupportProfile &s, int pl1, int st1, int pl2, int st2); //@} /// @name Iteration and data access @@ -181,7 +175,6 @@ class StrategyProfileIterator { //@} }; - } // end namespace Gambit #endif // GAMBIT_GAMES_STRATPURE_H diff --git a/src/games/stratspt.cc b/src/games/stratspt.cc index 03ffeb9de..3d759e2fc 100644 --- a/src/games/stratspt.cc +++ b/src/games/stratspt.cc @@ -38,8 +38,7 @@ StrategySupportProfile::StrategySupportProfile(const Game &p_nfg) { for (int pl = 1, index = 1; pl <= p_nfg->NumPlayers(); pl++) { m_support.push_back(Array()); - for (int st = 1; st <= p_nfg->GetPlayer(pl)->NumStrategies(); - st++, index++) { + for (int st = 1; st <= p_nfg->GetPlayer(pl)->NumStrategies(); st++, index++) { m_support[pl].push_back(p_nfg->GetPlayer(pl)->GetStrategy(st)); m_profileIndex[index] = index; } @@ -63,59 +62,58 @@ Array StrategySupportProfile::NumStrategies() const int StrategySupportProfile::MixedProfileLength() const { int total = 0; - for (int pl = 1; pl <= m_nfg->NumPlayers(); - total += m_support[pl++].Length()); + for (int pl = 1; pl <= m_nfg->NumPlayers(); total += m_support[pl++].Length()) + ; return total; } -template<> -MixedStrategyProfile StrategySupportProfile::NewMixedStrategyProfile() const +template <> MixedStrategyProfile StrategySupportProfile::NewMixedStrategyProfile() const { return m_nfg->NewMixedStrategyProfile(0.0, *this); - } -template<> -MixedStrategyProfile StrategySupportProfile::NewMixedStrategyProfile() const +template <> MixedStrategyProfile StrategySupportProfile::NewMixedStrategyProfile() const { return m_nfg->NewMixedStrategyProfile(Rational(0), *this); } bool StrategySupportProfile::IsSubsetOf(const StrategySupportProfile &p_support) const { - if (m_nfg != p_support.m_nfg) return false; + if (m_nfg != p_support.m_nfg) { + return false; + } for (int pl = 1; pl <= m_support.Length(); pl++) { if (m_support[pl].Length() > p_support.m_support[pl].Length()) { return false; } else { for (int st = 1; st <= m_support[pl].Length(); st++) { - if (!p_support.m_support[pl].Contains(m_support[pl][st])) { - return false; - } + if (!p_support.m_support[pl].Contains(m_support[pl][st])) { + return false; + } } } } return true; } - namespace { std::string EscapeQuotes(const std::string &s) { std::string ret; - for (char c : s) { - if (c == '"') ret += '\\'; + for (char c : s) { + if (c == '"') { + ret += '\\'; + } ret += c; } return ret; } -} // end anonymous namespace - +} // end anonymous namespace void StrategySupportProfile::WriteNfgFile(std::ostream &p_file) const { @@ -163,9 +161,7 @@ void StrategySupportProfile::AddStrategy(const GameStrategy &p_strategy) { // Get the null-pointer checking out of the way once and for all GameStrategyRep *strategy = p_strategy; - Array &support = - m_support[strategy->GetPlayer()->GetNumber()]; - + Array &support = m_support[strategy->GetPlayer()->GetNumber()]; for (int i = 1; i <= support.Length(); i++) { GameStrategyRep *s = support[i]; @@ -177,7 +173,9 @@ void StrategySupportProfile::AddStrategy(const GameStrategy &p_strategy) // Shift all higher-id strategies by one in the profile m_profileIndex[strategy->GetId()] = m_profileIndex[s->GetId()]; for (int id = s->GetId(); id <= m_profileIndex.Length(); id++) { - if (m_profileIndex[id] >= 0) m_profileIndex[id]++; + if (m_profileIndex[id] >= 0) { + m_profileIndex[id]++; + } } // Insert here support.Insert(strategy, i); @@ -189,8 +187,10 @@ void StrategySupportProfile::AddStrategy(const GameStrategy &p_strategy) // support for this player; append. GameStrategyRep *last = support[support.Last()]; m_profileIndex[strategy->GetId()] = m_profileIndex[last->GetId()] + 1; - for (int id = strategy->GetId()+1; id <= m_profileIndex.Length(); id++) { - if (m_profileIndex[id] >= 0) m_profileIndex[id]++; + for (int id = strategy->GetId() + 1; id <= m_profileIndex.Length(); id++) { + if (m_profileIndex[id] >= 0) { + m_profileIndex[id]++; + } } support.push_back(strategy); } @@ -200,7 +200,9 @@ bool StrategySupportProfile::RemoveStrategy(const GameStrategy &p_strategy) GameStrategyRep *strategy = p_strategy; Array &support = m_support[strategy->GetPlayer()->GetNumber()]; - if (support.Length() == 1) return false; + if (support.Length() == 1) { + return false; + } for (int i = 1; i <= support.Length(); i++) { GameStrategyRep *s = support[i]; @@ -208,8 +210,10 @@ bool StrategySupportProfile::RemoveStrategy(const GameStrategy &p_strategy) support.Remove(i); m_profileIndex[strategy->GetId()] = -1; // Shift strategies left in the profile - for (int id = strategy->GetId()+1; id <= m_profileIndex.Length(); id++) { - if (m_profileIndex[id] >= 0) m_profileIndex[id]--; + for (int id = strategy->GetId() + 1; id <= m_profileIndex.Length(); id++) { + if (m_profileIndex[id] >= 0) { + m_profileIndex[id]--; + } } return true; } @@ -218,14 +222,12 @@ bool StrategySupportProfile::RemoveStrategy(const GameStrategy &p_strategy) return false; } - //--------------------------------------------------------------------------- // Identification of dominated strategies //--------------------------------------------------------------------------- -bool StrategySupportProfile::Dominates(const GameStrategy &s, - const GameStrategy &t, - bool p_strict) const +bool StrategySupportProfile::Dominates(const GameStrategy &s, const GameStrategy &t, + bool p_strict) const { bool equal = true; @@ -236,25 +238,26 @@ bool StrategySupportProfile::Dominates(const GameStrategy &s, return false; } else if (!p_strict) { - if (ap < bp) return false; - else if (ap > bp) equal = false; + if (ap < bp) { + return false; + } + else if (ap > bp) { + equal = false; + } } } return (p_strict || !equal); } - -bool StrategySupportProfile::IsDominated(const GameStrategy &s, - bool p_strict, - bool p_external) const +bool StrategySupportProfile::IsDominated(const GameStrategy &s, bool p_strict, + bool p_external) const { if (p_external) { GamePlayer player = s->GetPlayer(); for (int st = 1; st <= player->NumStrategies(); st++) { - if (player->GetStrategy(st) != s && - Dominates(player->GetStrategy(st), s, p_strict)) { - return true; + if (player->GetStrategy(st) != s && Dominates(player->GetStrategy(st), s, p_strict)) { + return true; } } return false; @@ -262,21 +265,19 @@ bool StrategySupportProfile::IsDominated(const GameStrategy &s, else { for (int i = 1; i <= NumStrategies(s->GetPlayer()->GetNumber()); i++) { if (GetStrategy(s->GetPlayer()->GetNumber(), i) != s && - Dominates(GetStrategy(s->GetPlayer()->GetNumber(), i), s, - p_strict)) { - return true; + Dominates(GetStrategy(s->GetPlayer()->GetNumber(), i), s, p_strict)) { + return true; } } return false; } } -bool StrategySupportProfile::Undominated(StrategySupportProfile &newS, int p_player, - bool p_strict, bool p_external) const +bool StrategySupportProfile::Undominated(StrategySupportProfile &newS, int p_player, bool p_strict, + bool p_external) const { - Array set((p_external) ? - m_nfg->GetPlayer(p_player)->NumStrategies() : - NumStrategies(p_player)); + Array set((p_external) ? m_nfg->GetPlayer(p_player)->NumStrategies() + : NumStrategies(p_player)); if (p_external) { for (int st = 1; st <= set.Length(); st++) { @@ -293,34 +294,36 @@ bool StrategySupportProfile::Undominated(StrategySupportProfile &newS, int p_pla while (min <= dis) { int pp; - for (pp = 0; - pp < min && !Dominates(set[pp+1], set[dis+1], p_strict); - pp++); - if (pp < min) + for (pp = 0; pp < min && !Dominates(set[pp + 1], set[dis + 1], p_strict); pp++) + ; + if (pp < min) { dis--; - else { - GameStrategy foo = set[dis+1]; - set[dis+1] = set[min+1]; - set[min+1] = foo; - - for (int inc = min + 1; inc <= dis; ) { - if (Dominates(set[min+1], set[dis+1], p_strict)) { - //p_tracefile << GetStrategy(p_player, set[dis+1])->GetNumber() << " dominated by " << GetStrategy(p_player, set[min+1])->GetNumber() << '\n'; - dis--; - } - else if (Dominates(set[dis+1], set[min+1], p_strict)) { - //p_tracefile << GetStrategy(p_player, set[min+1])->GetNumber() << " dominated by " << GetStrategy(p_player, set[dis+1])->GetNumber() << '\n'; - foo = set[dis+1]; - set[dis+1] = set[min+1]; - set[min+1] = foo; - dis--; - } - else { - foo = set[dis+1]; - set[dis+1] = set[inc+1]; - set[inc+1] = foo; - inc++; - } + } + else { + GameStrategy foo = set[dis + 1]; + set[dis + 1] = set[min + 1]; + set[min + 1] = foo; + + for (int inc = min + 1; inc <= dis;) { + if (Dominates(set[min + 1], set[dis + 1], p_strict)) { + // p_tracefile << GetStrategy(p_player, set[dis+1])->GetNumber() << " dominated by " << + // GetStrategy(p_player, set[min+1])->GetNumber() << '\n'; + dis--; + } + else if (Dominates(set[dis + 1], set[min + 1], p_strict)) { + // p_tracefile << GetStrategy(p_player, set[min+1])->GetNumber() << " dominated by " << + // GetStrategy(p_player, set[dis+1])->GetNumber() << '\n'; + foo = set[dis + 1]; + set[dis + 1] = set[min + 1]; + set[min + 1] = foo; + dis--; + } + else { + foo = set[dis + 1]; + set[dis + 1] = set[inc + 1]; + set[inc + 1] = foo; + inc++; + } } min++; } @@ -338,25 +341,24 @@ bool StrategySupportProfile::Undominated(StrategySupportProfile &newS, int p_pla } } -StrategySupportProfile StrategySupportProfile::Undominated(bool p_strict, - bool p_external) const +StrategySupportProfile StrategySupportProfile::Undominated(bool p_strict, bool p_external) const { StrategySupportProfile newS(*this); - for (int pl = 1; pl <= m_nfg->NumPlayers(); pl++) { + for (int pl = 1; pl <= m_nfg->NumPlayers(); pl++) { Undominated(newS, pl, p_strict, p_external); } return newS; } -StrategySupportProfile -StrategySupportProfile::Undominated(bool p_strict, const Array &players) const +StrategySupportProfile StrategySupportProfile::Undominated(bool p_strict, + const Array &players) const { StrategySupportProfile newS(*this); - for (int i = 1; i <= players.Length(); i++) { - //tracefile << "Dominated strategies for player " << pl << ":\n"; + for (int i = 1; i <= players.Length(); i++) { + // tracefile << "Dominated strategies for player " << pl << ":\n"; Undominated(newS, players[i], p_strict); } @@ -367,9 +369,8 @@ StrategySupportProfile::Undominated(bool p_strict, const Array &players) co // Identification of overwhelmed strategies //--------------------------------------------------------------------------- -bool StrategySupportProfile::Overwhelms(const GameStrategy &s, - const GameStrategy &t, - bool p_strict) const +bool StrategySupportProfile::Overwhelms(const GameStrategy &s, const GameStrategy &t, + bool p_strict) const { StrategyProfileIterator iter(*this); Rational sMin = (*iter)->GetStrategyValue(s); @@ -396,10 +397,9 @@ bool StrategySupportProfile::Overwhelms(const GameStrategy &s, // class StrategySupportProfile::iterator //=========================================================================== - bool StrategySupportProfile::iterator::GoToNext() { - if (strat != support.NumStrategies(pl)) { + if (strat != support.NumStrategies(pl)) { strat++; return true; } @@ -413,20 +413,20 @@ bool StrategySupportProfile::iterator::GoToNext() } } -bool -StrategySupportProfile::iterator::IsSubsequentTo(const GameStrategy &s) const +bool StrategySupportProfile::iterator::IsSubsequentTo(const GameStrategy &s) const { - if (pl > s->GetPlayer()->GetNumber()) + if (pl > s->GetPlayer()->GetNumber()) { return true; - else if (pl < s->GetPlayer()->GetNumber()) + } + else if (pl < s->GetPlayer()->GetNumber()) { return false; - else - if (strat > s->GetNumber()) - return true; - else - return false; + } + else if (strat > s->GetNumber()) { + return true; + } + else { + return false; + } } - - } // end namespace Gambit diff --git a/src/games/stratspt.h b/src/games/stratspt.h index 078ecf4bb..70e2268ae 100644 --- a/src/games/stratspt.h +++ b/src/games/stratspt.h @@ -45,15 +45,16 @@ class StrategySupportProfile { template friend class MixedStrategyProfileRep; template friend class AGGMixedStrategyProfileRep; template friend class BAGGMixedStrategyProfileRep; + protected: Game m_nfg; - Array > m_support; + Array> m_support; /// The index into a strategy profile for a strategy (-1 if not in support) Array m_profileIndex; - bool Undominated(StrategySupportProfile &newS, int p_player, - bool p_strict, bool p_external = false) const; + bool Undominated(StrategySupportProfile &newS, int p_player, bool p_strict, + bool p_external = false) const; public: /// @name Lifecycle @@ -66,10 +67,14 @@ class StrategySupportProfile { //@{ /// Test for the equality of two supports (same strategies for all players) bool operator==(const StrategySupportProfile &p_support) const - { return (m_support == p_support.m_support); } + { + return (m_support == p_support.m_support); + } /// Test for the inequality of two supports bool operator!=(const StrategySupportProfile &p_support) const - { return (m_support != p_support.m_support); } + { + return (m_support != p_support.m_support); + } //@} /// @name General information @@ -78,7 +83,7 @@ class StrategySupportProfile { Game GetGame() const { return m_nfg; } /// Returns the number of strategies in the support for player pl. - int NumStrategies(int pl) const { return m_support[pl].size(); } + int NumStrategies(int pl) const { return m_support[pl].size(); } /// Returns the number of strategies in the support for all players. Array NumStrategies() const; @@ -89,8 +94,7 @@ class StrategySupportProfile { template MixedStrategyProfile NewMixedStrategyProfile() const; /// Returns the strategy in the st'th position for player pl. - GameStrategy GetStrategy(int pl, int st) const - { return m_support[pl][st]; } + GameStrategy GetStrategy(int pl, int st) const { return m_support[pl][st]; } /// Returns the number of players in the game int NumPlayers() const { return m_nfg->NumPlayers(); } @@ -98,11 +102,12 @@ class StrategySupportProfile { Array GetPlayers() const { return m_nfg->GetPlayers(); } /// Returns the set of strategies in the support for a player const Array &GetStrategies(const GamePlayer &p_player) const - { return m_support[p_player->GetNumber()]; } + { + return m_support[p_player->GetNumber()]; + } /// Returns true exactly when the strategy is in the support. - bool Contains(const GameStrategy &s) const - { return m_profileIndex[s->GetId()] >= 0; } + bool Contains(const GameStrategy &s) const { return m_profileIndex[s->GetId()] >= 0; } /// Returns true iff this support is a (weak) subset of the specified support bool IsSubsetOf(const StrategySupportProfile &) const; @@ -130,10 +135,8 @@ class StrategySupportProfile { /// @name Identification of dominated strategies //@{ - bool Dominates(const GameStrategy &s, const GameStrategy &t, - bool p_strict) const; - bool IsDominated(const GameStrategy &s, bool p_strict, - bool p_external = false) const; + bool Dominates(const GameStrategy &s, const GameStrategy &t, bool p_strict) const; + bool IsDominated(const GameStrategy &s, bool p_strict, bool p_external = false) const; /// Returns a copy of the support with dominated strategies eliminated StrategySupportProfile Undominated(bool p_strict, bool p_external = false) const; @@ -142,23 +145,26 @@ class StrategySupportProfile { /// @name Identification of overwhelmed strategies //@{ - bool Overwhelms(const GameStrategy &s, const GameStrategy &t, - bool p_strict) const; + bool Overwhelms(const GameStrategy &s, const GameStrategy &t, bool p_strict) const; //@} class iterator { public: /// @name Lifecycle //@{ - explicit iterator(const StrategySupportProfile &S, int p_pl = 1, int p_st = 1) : - support(S), pl(p_pl), strat(p_st) { } + explicit iterator(const StrategySupportProfile &S, int p_pl = 1, int p_st = 1) + : support(S), pl(p_pl), strat(p_st) + { + } ~iterator() = default; //@} /// @name Operator overloading //@{ bool operator==(const iterator &other) const - { return (support == other.support && pl == other.pl && strat == other.strat); } + { + return (support == other.support && pl == other.pl && strat == other.strat); + } bool operator!=(const iterator &other) const { return !(*this == other); } //@} @@ -172,16 +178,14 @@ class StrategySupportProfile { /// @name Access to state information //@{ - GameStrategy GetStrategy() const - { return support.GetStrategy(pl, strat); } + GameStrategy GetStrategy() const { return support.GetStrategy(pl, strat); } int StrategyIndex() const { return strat; } - GamePlayer GetPlayer() const - { return support.GetGame()->GetPlayer(pl); } + GamePlayer GetPlayer() const { return support.GetGame()->GetPlayer(pl); } int PlayerIndex() const { return pl; } bool IsLast() const - { return (pl == support.GetGame()->NumPlayers() && - strat == support.NumStrategies(pl)); + { + return (pl == support.GetGame()->NumPlayers() && strat == support.NumStrategies(pl)); } bool IsSubsequentTo(const GameStrategy &) const; //@} @@ -192,7 +196,7 @@ class StrategySupportProfile { }; iterator begin() const { return iterator(*this); } - iterator end() const { return iterator(*this, m_nfg->NumPlayers() + 1); } + iterator end() const { return iterator(*this, m_nfg->NumPlayers() + 1); } }; } // end namespace Gambit diff --git a/src/games/writer.cc b/src/games/writer.cc index 898093989..a60bb4ed3 100644 --- a/src/games/writer.cc +++ b/src/games/writer.cc @@ -25,26 +25,25 @@ using namespace Gambit; -std::string HTMLGameWriter::Write(const Game &p_game, - int p_rowPlayer, int p_colPlayer) const +std::string HTMLGameWriter::Write(const Game &p_game, int p_rowPlayer, int p_colPlayer) const { std::string theHtml; theHtml += "

" + p_game->GetTitle() + "

\n"; - for (StrategyProfileIterator iter(p_game, p_rowPlayer, 1, p_colPlayer, 1); - !iter.AtEnd(); iter++) { + for (StrategyProfileIterator iter(p_game, p_rowPlayer, 1, p_colPlayer, 1); !iter.AtEnd(); + iter++) { if (p_game->NumPlayers() > 2) { theHtml += "
Subtable with strategies:
"; for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { - if (pl == p_rowPlayer || pl == p_colPlayer) { - continue; - } + if (pl == p_rowPlayer || pl == p_colPlayer) { + continue; + } - theHtml += "
Player "; - theHtml += lexical_cast(pl); - theHtml += " Strategy "; - theHtml += lexical_cast((*iter)->GetStrategy(pl)->GetNumber()); - theHtml += "
"; + theHtml += "
Player "; + theHtml += lexical_cast(pl); + theHtml += " Strategy "; + theHtml += lexical_cast((*iter)->GetStrategy(pl)->GetNumber()); + theHtml += "
"; } } @@ -65,25 +64,25 @@ std::string HTMLGameWriter::Write(const Game &p_game, theHtml += p_game->GetPlayer(p_rowPlayer)->GetStrategy(st1)->GetLabel(); theHtml += ""; for (int st2 = 1; st2 <= p_game->GetPlayer(p_colPlayer)->NumStrategies(); st2++) { - profile->SetStrategy(p_game->GetPlayer(p_colPlayer)->GetStrategy(st2)); - theHtml += ""; - for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { - try { - if (profile->GetOutcome()) { - theHtml += static_cast(profile->GetOutcome()->GetPayoff(pl)); - } - else { - theHtml += "0"; - } - } - catch (UndefinedException &) { - theHtml += lexical_cast(profile->GetPayoff(pl)); - } - if (pl < p_game->NumPlayers()) { - theHtml += ","; - } - } - theHtml += ""; + profile->SetStrategy(p_game->GetPlayer(p_colPlayer)->GetStrategy(st2)); + theHtml += ""; + for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { + try { + if (profile->GetOutcome()) { + theHtml += static_cast(profile->GetOutcome()->GetPayoff(pl)); + } + else { + theHtml += "0"; + } + } + catch (UndefinedException &) { + theHtml += lexical_cast(profile->GetPayoff(pl)); + } + if (pl < p_game->NumPlayers()) { + theHtml += ","; + } + } + theHtml += ""; } theHtml += ""; } @@ -94,13 +93,12 @@ std::string HTMLGameWriter::Write(const Game &p_game, return theHtml; } -std::string LaTeXGameWriter::Write(const Game &p_game, - int p_rowPlayer, int p_colPlayer) const +std::string LaTeXGameWriter::Write(const Game &p_game, int p_rowPlayer, int p_colPlayer) const { std::string theHtml; - for (StrategyProfileIterator iter(p_game, p_rowPlayer, 1, p_colPlayer, 1); - !iter.AtEnd(); iter++) { + for (StrategyProfileIterator iter(p_game, p_rowPlayer, 1, p_colPlayer, 1); !iter.AtEnd(); + iter++) { theHtml += "\\begin{game}{"; theHtml += lexical_cast(p_game->GetPlayer(p_rowPlayer)->NumStrategies()); theHtml += "}{"; @@ -114,15 +112,15 @@ std::string LaTeXGameWriter::Write(const Game &p_game, if (p_game->NumPlayers() > 2) { theHtml += "["; for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { - if (pl == p_rowPlayer || pl == p_colPlayer) { - continue; - } + if (pl == p_rowPlayer || pl == p_colPlayer) { + continue; + } - theHtml += "Player "; - theHtml += lexical_cast(pl); - theHtml += " Strategy "; - theHtml += lexical_cast((*iter)->GetStrategy(pl)->GetNumber()); - theHtml += " "; + theHtml += "Player "; + theHtml += lexical_cast(pl); + theHtml += " Strategy "; + theHtml += lexical_cast((*iter)->GetStrategy(pl)->GetNumber()); + theHtml += " "; } theHtml += "]"; } @@ -132,7 +130,7 @@ std::string LaTeXGameWriter::Write(const Game &p_game, for (int st = 1; st <= p_game->GetPlayer(p_colPlayer)->NumStrategies(); st++) { theHtml += p_game->GetPlayer(p_colPlayer)->GetStrategy(st)->GetLabel(); if (st < p_game->GetPlayer(p_colPlayer)->NumStrategies()) { - theHtml += " & "; + theHtml += " & "; } } theHtml += "\\\\\n"; @@ -143,31 +141,31 @@ std::string LaTeXGameWriter::Write(const Game &p_game, theHtml += p_game->GetPlayer(p_rowPlayer)->GetStrategy(st1)->GetLabel(); theHtml += " & "; for (int st2 = 1; st2 <= p_game->GetPlayer(p_colPlayer)->NumStrategies(); st2++) { - profile->SetStrategy(p_game->GetPlayer(p_colPlayer)->GetStrategy(st2)); - theHtml += " $"; - for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { - try { - if (profile->GetOutcome()) { - theHtml += static_cast(profile->GetOutcome()->GetPayoff(pl)); - } - else { - theHtml += "0"; - } - } - catch (UndefinedException &) { - theHtml += lexical_cast(profile->GetPayoff(pl)); - } - if (pl < p_game->NumPlayers()) { - theHtml += ","; - } - } - theHtml += "$ "; - if (st2 < p_game->GetPlayer(p_colPlayer)->NumStrategies()) { - theHtml += " & "; - } + profile->SetStrategy(p_game->GetPlayer(p_colPlayer)->GetStrategy(st2)); + theHtml += " $"; + for (int pl = 1; pl <= p_game->NumPlayers(); pl++) { + try { + if (profile->GetOutcome()) { + theHtml += static_cast(profile->GetOutcome()->GetPayoff(pl)); + } + else { + theHtml += "0"; + } + } + catch (UndefinedException &) { + theHtml += lexical_cast(profile->GetPayoff(pl)); + } + if (pl < p_game->NumPlayers()) { + theHtml += ","; + } + } + theHtml += "$ "; + if (st2 < p_game->GetPlayer(p_colPlayer)->NumStrategies()) { + theHtml += " & "; + } } if (st1 < p_game->GetPlayer(p_rowPlayer)->NumStrategies()) { - theHtml += "\\\\\n"; + theHtml += "\\\\\n"; } } diff --git a/src/games/writer.h b/src/games/writer.h index 73833da8e..546d50c0b 100644 --- a/src/games/writer.h +++ b/src/games/writer.h @@ -30,7 +30,7 @@ namespace Gambit { /// /// Abstract base class for objects that write games to various formats /// -class GameWriter { +class GameWriter { public: /// /// Convert the game to a string-based representation @@ -47,8 +47,7 @@ class HTMLGameWriter : public GameWriter { /// Convert the game to HTML, with player 1 on the rows and player 2 /// on the columns. /// - std::string Write(const Game &p_game) const override - { return Write(p_game, 1, 2); } + std::string Write(const Game &p_game) const override { return Write(p_game, 1, 2); } /// /// Convert the game to HTML, selecting the row and column player numbers. @@ -65,8 +64,7 @@ class LaTeXGameWriter : public GameWriter { /// Convert the game to LaTeX, with player 1 on the rows and player 2 /// on the columns. /// - std::string Write(const Game &p_game) const override - { return Write(p_game, 1, 2); } + std::string Write(const Game &p_game) const override { return Write(p_game, 1, 2); } /// /// Convert the game to LaTeX, selecting the row and column player numbers. diff --git a/src/labenski/include/wx/plotctrl/fourier.h b/src/labenski/include/wx/plotctrl/fourier.h index 7a4b6f255..88371b22b 100644 --- a/src/labenski/include/wx/plotctrl/fourier.h +++ b/src/labenski/include/wx/plotctrl/fourier.h @@ -45,35 +45,32 @@ extern "C" { ** wasting memory. */ -int fft_double ( - unsigned NumSamples, /* must be a power of 2 */ - int InverseTransform, /* 0=forward FFT, 1=inverse FFT */ - double *RealIn, /* array of input's real samples */ - double *ImaginaryIn, /* array of input's imag samples */ - double *RealOut, /* array of output's reals */ - double *ImaginaryOut ); /* array of output's imaginaries */ - - -int fft_float ( - unsigned NumSamples, /* must be a power of 2 */ - int InverseTransform, /* 0=forward FFT, 1=inverse FFT */ - float *RealIn, /* array of input's real samples */ - float *ImaginaryIn, /* array of input's imag samples */ - float *RealOut, /* array of output's reals */ - float *ImaginaryOut ); /* array of output's imaginaries */ +int fft_double(unsigned NumSamples, /* must be a power of 2 */ + int InverseTransform, /* 0=forward FFT, 1=inverse FFT */ + double *RealIn, /* array of input's real samples */ + double *ImaginaryIn, /* array of input's imag samples */ + double *RealOut, /* array of output's reals */ + double *ImaginaryOut); /* array of output's imaginaries */ + +int fft_float(unsigned NumSamples, /* must be a power of 2 */ + int InverseTransform, /* 0=forward FFT, 1=inverse FFT */ + float *RealIn, /* array of input's real samples */ + float *ImaginaryIn, /* array of input's imag samples */ + float *RealOut, /* array of output's reals */ + float *ImaginaryOut); /* array of output's imaginaries */ /* IsPowerOfTwo returns 1 if x is a power of two or 0 if not */ -int IsPowerOfTwo ( unsigned x ); +int IsPowerOfTwo(unsigned x); /* NumberOfBitsNeeded returns the number of bits to make the number, 2^n */ -unsigned NumberOfBitsNeeded ( unsigned PowerOfTwo ); -unsigned ReverseBits ( unsigned index, unsigned NumBits ); +unsigned NumberOfBitsNeeded(unsigned PowerOfTwo); +unsigned ReverseBits(unsigned index, unsigned NumBits); /* ** The following function returns an "abstract frequency" of a ** given index into a buffer with a given number of frequency samples. ** Multiply return value by sampling rate to get frequency expressed in Hz. */ -double Index_to_frequency ( unsigned NumSamples, unsigned Index ); +double Index_to_frequency(unsigned NumSamples, unsigned Index); #ifdef __cplusplus } diff --git a/src/labenski/include/wx/plotctrl/fparser.h b/src/labenski/include/wx/plotctrl/fparser.h index e85733ea1..14ea7bd11 100644 --- a/src/labenski/include/wx/plotctrl/fparser.h +++ b/src/labenski/include/wx/plotctrl/fparser.h @@ -18,7 +18,7 @@ #ifndef ONCE_wxFPARSER_H_ #define ONCE_wxFPARSER_H_ #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #include "wx/plotctrl/plotdefs.h" @@ -52,75 +52,79 @@ class FunctionParser; // any modification other than adding some code. // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxFunctionParser -{ +class WXDLLIMPEXP_PLOTCTRL wxFunctionParser { public: - enum ParseErrorType - { - SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH, - EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS, - ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC, - FP_NO_ERROR - }; - - wxFunctionParser(); - // Copy constructor and assignment operator (implemented using the - // copy-on-write technique for efficiency): - wxFunctionParser(const wxFunctionParser&); - virtual ~wxFunctionParser(); - - // Parse the function string and a comma delimited list of the variables - // in the function. func = "sin(x) + 2*t*x", vars = "x,t" - int Parse(const wxString& Function, const wxString& Vars, - bool useDegrees = false); - - // Get a readable error message if error after a call to parse or empty string - wxString ErrorMsg() const; - // Get the wxFunctionParser::ParseErrorType error id - ParseErrorType GetParseErrorType() const; - - // Evaluate the function (must have called Parse first) where vars is an - // array of the variable values to use. - double Eval(const double* Vars); - // Not really sure - some sort of error flag? - int EvalError() const; - - // Add a constant to the function parser - bool AddConstant(const wxString& name, double value); - - // Function type that can be added to the parser - typedef double (*FunctionPtr)(const double*); - // Add a function to the parser - bool AddFunction(const wxString& name, - FunctionPtr, unsigned paramsAmount); - bool AddFunction(const wxString& name, wxFunctionParser&); - - // Try to optimize the parser, use after sucessful call to Parse - void Optimize(); - - // Ok is true after a sucessful call to Parse - bool Ok() const { return m_ok; } - // Get the number of comma delimited variables sent to Parse - int GetNumberVariables() const; - // Get the function string sent to Parse - wxString GetFunctionString() const { return m_function; } - // Get the variable string sent to Parse - wxString GetVariableString() const { return m_variables; } - // Get one of the variable names from the string sent to Parse - wxString GetVariableName(size_t n) const; - // Was this parsed using degrees - bool GetUseDegrees() const; - - // operators - wxFunctionParser& operator=(const wxFunctionParser&); - - // implementation - FunctionParser* GetFunctionParser() const { return m_functionParser; } + enum ParseErrorType { + SYNTAX_ERROR = 0, + MISM_PARENTH, + MISSING_PARENTH, + EMPTY_PARENTH, + EXPECT_OPERATOR, + OUT_OF_MEMORY, + UNEXPECTED_ERROR, + INVALID_VARS, + ILL_PARAMS_AMOUNT, + PREMATURE_EOS, + EXPECT_PARENTH_FUNC, + FP_NO_ERROR + }; + + wxFunctionParser(); + // Copy constructor and assignment operator (implemented using the + // copy-on-write technique for efficiency): + wxFunctionParser(const wxFunctionParser &); + virtual ~wxFunctionParser(); + + // Parse the function string and a comma delimited list of the variables + // in the function. func = "sin(x) + 2*t*x", vars = "x,t" + int Parse(const wxString &Function, const wxString &Vars, bool useDegrees = false); + + // Get a readable error message if error after a call to parse or empty string + wxString ErrorMsg() const; + // Get the wxFunctionParser::ParseErrorType error id + ParseErrorType GetParseErrorType() const; + + // Evaluate the function (must have called Parse first) where vars is an + // array of the variable values to use. + double Eval(const double *Vars); + // Not really sure - some sort of error flag? + int EvalError() const; + + // Add a constant to the function parser + bool AddConstant(const wxString &name, double value); + + // Function type that can be added to the parser + typedef double (*FunctionPtr)(const double *); + // Add a function to the parser + bool AddFunction(const wxString &name, FunctionPtr, unsigned paramsAmount); + bool AddFunction(const wxString &name, wxFunctionParser &); + + // Try to optimize the parser, use after sucessful call to Parse + void Optimize(); + + // Ok is true after a sucessful call to Parse + bool Ok() const { return m_ok; } + // Get the number of comma delimited variables sent to Parse + int GetNumberVariables() const; + // Get the function string sent to Parse + wxString GetFunctionString() const { return m_function; } + // Get the variable string sent to Parse + wxString GetVariableString() const { return m_variables; } + // Get one of the variable names from the string sent to Parse + wxString GetVariableName(size_t n) const; + // Was this parsed using degrees + bool GetUseDegrees() const; + + // operators + wxFunctionParser &operator=(const wxFunctionParser &); + + // implementation + FunctionParser *GetFunctionParser() const { return m_functionParser; } protected: - FunctionParser *m_functionParser; - wxString m_function, m_variables; - bool m_ok; + FunctionParser *m_functionParser; + wxString m_function, m_variables; + bool m_ok; }; #endif // ONCE_wxFPARSER_H_ diff --git a/src/labenski/include/wx/plotctrl/lm_lsqr.h b/src/labenski/include/wx/plotctrl/lm_lsqr.h index 0189aea8a..69f47572f 100644 --- a/src/labenski/include/wx/plotctrl/lm_lsqr.h +++ b/src/labenski/include/wx/plotctrl/lm_lsqr.h @@ -47,10 +47,9 @@ class WXDLLIMPEXP_PLOTCTRL wxPlotFunction; extern "C" { typedef bool (*LM_LeastSquareProgressHandler_)(const wxString &WXUNUSED(text), - int WXUNUSED(current), - int WXUNUSED(max)); -extern void SetLM_LeastSquareProgressHandler( LM_LeastSquareProgressHandler_ handler ); -extern void SetLM_LeastSquareProgressHandlerTicks( int iterations ); + int WXUNUSED(current), int WXUNUSED(max)); +extern void SetLM_LeastSquareProgressHandler(LM_LeastSquareProgressHandler_ handler); +extern void SetLM_LeastSquareProgressHandlerTicks(int iterations); } //============================================================================= @@ -67,7 +66,8 @@ extern void SetLM_LeastSquareProgressHandlerTicks( int iterations ); // Sample usage : // wxString message; // // Create some plotData, in this case from a known function -// wxPlotData data(wxPlotFunction("2.5*x*x-3*x+5+3.3*log(x)+13*exp(15*x/(x+4))", "x",dummy), 0, 1E-4, 10000); +// wxPlotData data(wxPlotFunction("2.5*x*x-3*x+5+3.3*log(x)+13*exp(15*x/(x+4))", "x",dummy), 0, +// 1E-4, 10000); // // Create the plotFunc we want to fit to the data, note: x is last var // wxPlotFunction func("a*x*x+b*x+c+d*log(x)+e*exp(f*x/(x+g))", "a,b,c,d,e,f,g,x", message); // LM_LeastSquare lmLeastSquare; @@ -75,117 +75,115 @@ extern void SetLM_LeastSquareProgressHandlerTicks( int iterations ); // lmLeastSquare.Fit(NULL); // or Fit(init, init_count) where double init[init_count] = { a, b, c, ... } // for (int k=0; k= m_m - double *m_qtf; // output array the first n elements of the vector (q transpose)*fvec - int *m_ipvt; // integer output array of length n - int m_maxfev; // maximum number of iterations to try + void ReInit(); // only after a call to destroy - reset the vars + void Destroy(); + + wxPlotData *m_plotData; + wxPlotFunction *m_plotFunc; + double m_init_value; + wxString m_resultMsg; + bool m_ok; + bool m_fitting; + bool m_abort_fitting; + + // this is the function to calculate the difference + virtual void fcn(int m, int n, double x[], double fvec[], int *iflag); + + void lmdif(int m, int n, double x[], double fvec[], double ftol, double xtol, double gtol, + int maxfev, double epsfcn, double diag[], int mode, double factor, int nprint, + int *info, int *nfev, double fjac[], int ldfjac, int ipvt[], double qtf[], + double wa1[], double wa2[], double wa3[], double wa4[]); + + // implementation - you probably don't want to mess with these! + + void lmpar(int n, double r[], int ldr, int ipvt[], double diag[], double qtb[], double delta, + double *par, double x[], double sdiag[], double wa1[], double wa2[]); + + void qrfac(int m, int n, double a[], int lda, int pivot, int ipvt[], int lipvt, double rdiag[], + double acnorm[], double wa[]); + + void qrsolv(int n, double r[], int ldr, int ipvt[], double diag[], double qtb[], double x[], + double sdiag[], double wa[]); + + double enorm(int n, double x[]); + + void fdjac2(int m, int n, double x[], double fvec[], double fjac[], int ldfjac, int *iflag, + double epsfcn, double wa[]); + + int m_n; // # of variables of plotFunc + int m_m; // # of functions = points in plotData + int m_info; // index of info message strings + double m_fnorm; // euclidean norm of errors + double m_eps; // resolution of arithmetic + double m_dwarf; // smallest nonzero number + int m_nfev; // # iterations completed + unsigned long m_nan; // # if times function evaluation had a NaN + double m_ftol; // relative error in the sum of the squares, if less done + double m_xtol; // relative error between two iterations, if less done + double m_gtol; // cosine of the angle between fvec and any column of the jacobian, if less done + double m_epsfcn; // step length for the forward-difference approximation + double m_factor; // initial step bound + double *m_vars; // variables + 1, where last is var 'x' for wxPlotFunction + double *m_x; // variables (size m_n) + double *m_fvec; // output of evaluated functions (size m_m) + double *m_diag; // multiplicative scale factors for the variables, see m_mode + int m_mode; // =1 the vars scaled internally. if 2, scaling specified by m_diag. + double *m_fjac; // output m by n array + int m_ldfjac; // the leading dimension of the array fjac >= m_m + double *m_qtf; // output array the first n elements of the vector (q transpose)*fvec + int *m_ipvt; // integer output array of length n + int m_maxfev; // maximum number of iterations to try private: - void Init(); + void Init(); }; #endif // _LM_LEASTSQUARE_H_ diff --git a/src/labenski/include/wx/plotctrl/plotctrl.h b/src/labenski/include/wx/plotctrl/plotctrl.h index a43c69bdb..302a90ad0 100644 --- a/src/labenski/include/wx/plotctrl/plotctrl.h +++ b/src/labenski/include/wx/plotctrl/plotctrl.h @@ -60,10 +60,10 @@ class WXDLLIMPEXP_PLOTCTRL wxPlotDrawerMarker; // wxPlot Constants //----------------------------------------------------------------------------- #ifdef __VISUALC__ - #include - // disable warning for stl::numeric_limits, - // C++ language change: to explicitly specialize - #pragma warning(disable:4663) +#include +// disable warning for stl::numeric_limits, +// C++ language change: to explicitly specialize +#pragma warning(disable : 4663) #endif // __VISUALC__ #include @@ -73,169 +73,161 @@ extern const wxDouble wxPlot_MIN_DBL; // = wxDouble_limits.min()*10 extern const wxDouble wxPlot_MAX_DBL; // = wxDouble_limits.max()/10 extern const wxDouble wxPlot_MAX_RANGE; // = wxPlot_MAX_DBL*2 -#define CURSOR_GRAB wxCURSOR_MAX // for a hand cursor with fingers closed +#define CURSOR_GRAB wxCURSOR_MAX // for a hand cursor with fingers closed #include "wx/dynarray.h" #ifndef WX_DECLARE_OBJARRAY_WITH_DECL // for wx2.4 backwards compatibility - #define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, expmode) WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_PLOTCTRL) +#define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, expmode) \ + WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_PLOTCTRL) #endif WX_DECLARE_OBJARRAY_WITH_DECL(wxPoint2DDouble, wxArrayPoint2DDouble, class WXDLLIMPEXP_PLOTCTRL); -WX_DECLARE_OBJARRAY_WITH_DECL(wxRect2DDouble, wxArrayRect2DDouble, class WXDLLIMPEXP_PLOTCTRL); -WX_DECLARE_OBJARRAY_WITH_DECL(wxPlotCurve, wxArrayPlotCurve, class WXDLLIMPEXP_PLOTCTRL); +WX_DECLARE_OBJARRAY_WITH_DECL(wxRect2DDouble, wxArrayRect2DDouble, class WXDLLIMPEXP_PLOTCTRL); +WX_DECLARE_OBJARRAY_WITH_DECL(wxPlotCurve, wxArrayPlotCurve, class WXDLLIMPEXP_PLOTCTRL); // What type of axis for wxPlotAxis window -enum wxPlotAxis_Type -{ - wxPLOT_X_AXIS = 0x0020, - wxPLOT_Y_AXIS = 0x0200, - wxPLOT_DEFAULT = wxPLOT_X_AXIS|wxPLOT_Y_AXIS +enum wxPlotAxis_Type { + wxPLOT_X_AXIS = 0x0020, + wxPLOT_Y_AXIS = 0x0200, + wxPLOT_DEFAULT = wxPLOT_X_AXIS | wxPLOT_Y_AXIS }; // What is the function of the mouse during left down and dragging -enum wxPlotMouse_Type -{ - wxPLOT_MOUSE_NOTHING, // do nothing - wxPLOT_MOUSE_ZOOM, // zoom into the plot - wxPLOT_MOUSE_SELECT, // select points in the active curve - wxPLOT_MOUSE_DESELECT, // deselect points in the active curve - wxPLOT_MOUSE_PAN // offset the origin +enum wxPlotMouse_Type { + wxPLOT_MOUSE_NOTHING, // do nothing + wxPLOT_MOUSE_ZOOM, // zoom into the plot + wxPLOT_MOUSE_SELECT, // select points in the active curve + wxPLOT_MOUSE_DESELECT, // deselect points in the active curve + wxPLOT_MOUSE_PAN // offset the origin }; // What sort of marker should be drawn for mouse left down and dragging -enum wxPlotMarker_Type -{ - wxPLOT_MARKER_NONE, // draw nothing - wxPLOT_MARKER_RECT, // draw a rectangle - wxPLOT_MARKER_VERT, // draw two vertical lines - wxPLOT_MARKER_HORIZ // draw two horizonal lines +enum wxPlotMarker_Type { + wxPLOT_MARKER_NONE, // draw nothing + wxPLOT_MARKER_RECT, // draw a rectangle + wxPLOT_MARKER_VERT, // draw two vertical lines + wxPLOT_MARKER_HORIZ // draw two horizonal lines }; // How does the selection mechanism act to selections -enum wxPlotSelection_Type -{ - wxPLOT_SELECT_NONE, // no selections - wxPLOT_SELECT_SINGLE, // only one selection in one curve at a time - wxPLOT_SELECT_SINGLE_CURVE, // only one curve may have selections at once - wxPLOT_SELECT_SINGLE_PER_CURVE, // multiple curves may one have one selection each - wxPLOT_SELECT_MULTIPLE // multiple curves may have multiple selections +enum wxPlotSelection_Type { + wxPLOT_SELECT_NONE, // no selections + wxPLOT_SELECT_SINGLE, // only one selection in one curve at a time + wxPLOT_SELECT_SINGLE_CURVE, // only one curve may have selections at once + wxPLOT_SELECT_SINGLE_PER_CURVE, // multiple curves may one have one selection each + wxPLOT_SELECT_MULTIPLE // multiple curves may have multiple selections }; // Redraw parts or all of the windows -enum wxPlotRedraw_Type -{ - wxPLOT_REDRAW_NONE = 0x000, // do nothing - wxPLOT_REDRAW_PLOT = 0x001, // redraw only the plot area - wxPLOT_REDRAW_XAXIS = 0x002, // redraw x-axis, combine w/ redraw_plot - wxPLOT_REDRAW_YAXIS = 0x004, // redraw y-axis, combine w/ redraw_plot - wxPLOT_REDRAW_WINDOW = 0x008, // wxPlotCtrl container window - wxPLOT_REDRAW_WHOLEPLOT = wxPLOT_REDRAW_PLOT|wxPLOT_REDRAW_XAXIS|wxPLOT_REDRAW_YAXIS, - wxPLOT_REDRAW_EVERYTHING = wxPLOT_REDRAW_WHOLEPLOT|wxPLOT_REDRAW_WINDOW, - wxPLOT_REDRAW_BLOCKER = 0x010 // don't let OnPaint redraw, used internally +enum wxPlotRedraw_Type { + wxPLOT_REDRAW_NONE = 0x000, // do nothing + wxPLOT_REDRAW_PLOT = 0x001, // redraw only the plot area + wxPLOT_REDRAW_XAXIS = 0x002, // redraw x-axis, combine w/ redraw_plot + wxPLOT_REDRAW_YAXIS = 0x004, // redraw y-axis, combine w/ redraw_plot + wxPLOT_REDRAW_WINDOW = 0x008, // wxPlotCtrl container window + wxPLOT_REDRAW_WHOLEPLOT = wxPLOT_REDRAW_PLOT | wxPLOT_REDRAW_XAXIS | wxPLOT_REDRAW_YAXIS, + wxPLOT_REDRAW_EVERYTHING = wxPLOT_REDRAW_WHOLEPLOT | wxPLOT_REDRAW_WINDOW, + wxPLOT_REDRAW_BLOCKER = 0x010 // don't let OnPaint redraw, used internally }; // Styles for the different plot window components -enum wxPlotStyle_Type -{ - wxPLOT_STYLE_WINDOW, - wxPLOT_STYLE_LABELS, - wxPLOT_STYLE_TITLE, - wxPLOT_STYLE_XAXIS_LABEL, - wxPLOT_STYLE_YAXIS_LABEL, - wxPLOT_STYLE_XAXIS_TICS, - wxPLOT_STYLE_YAXIS_TICS, - wxPLOT_STYLE_KEY, - - wxPLOT_STYLE_LAST +enum wxPlotStyle_Type { + wxPLOT_STYLE_WINDOW, + wxPLOT_STYLE_LABELS, + wxPLOT_STYLE_TITLE, + wxPLOT_STYLE_XAXIS_LABEL, + wxPLOT_STYLE_YAXIS_LABEL, + wxPLOT_STYLE_XAXIS_TICS, + wxPLOT_STYLE_YAXIS_TICS, + wxPLOT_STYLE_KEY, + + wxPLOT_STYLE_LAST }; -enum wxPlotStyleUse_Type -{ - wxPLOT_STYLEUSE_FORECOLOUR = 0x0001, - wxPLOT_STYLEUSE_BACKCOLOUR = 0x0002, - wxPLOT_STYLEUSE_FONT = 0x0004, - wxPLOT_STYLEUSE_LINEWIDTH = 0x0008 +enum wxPlotStyleUse_Type { + wxPLOT_STYLEUSE_FORECOLOUR = 0x0001, + wxPLOT_STYLEUSE_BACKCOLOUR = 0x0002, + wxPLOT_STYLEUSE_FONT = 0x0004, + wxPLOT_STYLEUSE_LINEWIDTH = 0x0008 }; //----------------------------------------------------------------------------- // wxPlotArea - window where the plot is drawn (privately used in wxPlotCtrl) //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotArea : public wxWindow -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotArea : public wxWindow { public: - wxPlotArea( wxWindow *parent, wxWindowID win_id ) - { - Init(); - (void)Create(parent, win_id); - } - - bool Create( wxWindow *parent, wxWindowID win_id ); - virtual ~wxPlotArea() {} - - // Get the owner (parent) wxPlotCtrl - wxPlotCtrl *GetOwner() const { return m_owner; } - - // Draw the area of the plot window in client coords bounded by rect - // resizes backing bitmap if necessary - void CreateBitmap( const wxRect &rect ); - - // implementation - void OnEraseBackground( wxEraseEvent & ) { } - void OnPaint( wxPaintEvent &event ); - void OnMouse( wxMouseEvent &event ); - void OnChar( wxKeyEvent &event ); - void OnKeyDown( wxKeyEvent &event ); - void OnKeyUp( wxKeyEvent &event ); - - wxRect m_mouseRect; // mouse drag rectangle, or 0,0,0,0 when not dragging - wxPoint m_mousePt; // last mouse position - wxBitmap m_bitmap; - wxPlotCtrl *m_owner; + wxPlotArea(wxWindow *parent, wxWindowID win_id) + { + Init(); + (void)Create(parent, win_id); + } + + bool Create(wxWindow *parent, wxWindowID win_id); + virtual ~wxPlotArea() {} + + // Get the owner (parent) wxPlotCtrl + wxPlotCtrl *GetOwner() const { return m_owner; } + + // Draw the area of the plot window in client coords bounded by rect + // resizes backing bitmap if necessary + void CreateBitmap(const wxRect &rect); + + // implementation + void OnEraseBackground(wxEraseEvent &) {} + void OnPaint(wxPaintEvent &event); + void OnMouse(wxMouseEvent &event); + void OnChar(wxKeyEvent &event); + void OnKeyDown(wxKeyEvent &event); + void OnKeyUp(wxKeyEvent &event); + + wxRect m_mouseRect; // mouse drag rectangle, or 0,0,0,0 when not dragging + wxPoint m_mousePt; // last mouse position + wxBitmap m_bitmap; + wxPlotCtrl *m_owner; private: - void Init(); - DECLARE_CLASS(wxPlotArea) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_CLASS(wxPlotArea) + DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // wxPlotAxis - X or Y axis window (privately used in wxPlotCtrl) //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotAxis : public wxWindow -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotAxis : public wxWindow { public: - wxPlotAxis( wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style ) - { - Init(); - (void)Create( parent, win_id, style ); - } + wxPlotAxis(wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style) + { + Init(); + (void)Create(parent, win_id, style); + } - bool Create( wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style ); - virtual ~wxPlotAxis() {} + bool Create(wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style); + virtual ~wxPlotAxis() {} - // Create the backing bitmap of the window contents - void CreateBitmap(); - // Get the owner (parent) wxPlotCtrl - wxPlotCtrl *GetOwner() const { return m_owner; } + // Create the backing bitmap of the window contents + void CreateBitmap(); + // Get the owner (parent) wxPlotCtrl + wxPlotCtrl *GetOwner() const { return m_owner; } - bool IsXAxis() const { return (m_style & wxPLOT_X_AXIS) != 0; } + bool IsXAxis() const { return (m_style & wxPLOT_X_AXIS) != 0; } - // implementation - void OnEraseBackground( wxEraseEvent & ) { } - void OnPaint( wxPaintEvent &event ); - void OnMouse( wxMouseEvent &event ); - void OnChar( wxKeyEvent &event ); + // implementation + void OnEraseBackground(wxEraseEvent &) {} + void OnPaint(wxPaintEvent &event); + void OnMouse(wxMouseEvent &event); + void OnChar(wxKeyEvent &event); - wxPoint m_mousePt; // last mouse position - wxPlotAxis_Type m_style; - wxBitmap m_bitmap; - wxPlotCtrl *m_owner; + wxPoint m_mousePt; // last mouse position + wxPlotAxis_Type m_style; + wxBitmap m_bitmap; + wxPlotCtrl *m_owner; private: - void Init(); - DECLARE_CLASS(wxPlotAxis) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_CLASS(wxPlotAxis) + DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- @@ -247,829 +239,934 @@ class WXDLLIMPEXP_PLOTCTRL wxPlotAxis : public wxWindow // //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl : public wxWindow -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl : public wxWindow { public: - wxPlotCtrl() : wxWindow() { Init(); } - - wxPlotCtrl( wxWindow *parent, wxWindowID win_id = wxID_ANY, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - wxPlotAxis_Type flags = wxPLOT_DEFAULT, - const wxString& name = wxT("wxPlotCtrl") ) - { - Init(); - (void)Create(parent, win_id, pos, size, flags, name); - } - - bool Create( wxWindow *parent, wxWindowID id = wxID_ANY, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - wxPlotAxis_Type flags = wxPLOT_DEFAULT, - const wxString& name = wxT("wxPlotCtrl") ); - - virtual ~wxPlotCtrl(); - - // ------------------------------------------------------------------------ - // Curve Accessors - // - // note: the curves are stored in an array casted to class wxPlotCurve - // in order to know the type and use it as a wxPlotFunction, wxPlotData - // or a class derived from one of these use - // wxPlotData *pd = wxDynamicCast( GetCurve(i), wxPlotData ); - // pd will be NULL if GetCurve isn't a wxPlotData (or derived from it) - // ------------------------------------------------------------------------ - - // Add a curve to the plot, takes ownership of the curve and deletes it - bool AddCurve( wxPlotCurve *curve, bool select=true, bool send_event=false ); - // Add a curve to the plot, increases ref count - bool AddCurve( const wxPlotCurve &curve, bool select=true, bool send_event=false ); - // Delete this curve - bool DeleteCurve( wxPlotCurve* curve, bool send_event=false ); - // Delete this curve, if curve_index = -1, delete all curves - bool DeleteCurve( int curve_index, bool send_event=false ); - - // Total number of curves associated with the plotctrl - int GetCurveCount() const { return m_curves.GetCount(); } - bool CurveIndexOk(int curve_index) const - { return (curve_index>=0) && (curve_index < int(m_curves.GetCount())); } - - // Get the curve at this index - wxPlotCurve *GetCurve( int curve_index ) const; - // returns NULL if curve_index is not wxPlotData or derived from it - wxPlotData *GetDataCurve( int curve_index ) const { return wxDynamicCast(GetCurve(curve_index), wxPlotData); } - // returns NULL if curve_index is not wxPlotFunction or derived from it - wxPlotFunction *GetFunctionCurve( int curve_index ) const { return wxDynamicCast(GetCurve(curve_index), wxPlotFunction); } - // returns true if the curve is a wxPlotData curve - bool IsDataCurve( int curve_index ) const { return GetDataCurve(curve_index) != NULL; } - // returns true if the curve is a wxPlotFunction curve - bool IsFunctionCurve( int curve_index ) const { return GetFunctionCurve(curve_index) != NULL; } - // Else the function must be some sort of subclassed wxPlotCurve - - // Sets the currently active curve, NULL for none active - void SetActiveCurve( wxPlotCurve* curve, bool send_event=false ); - // Gets the currently active curve, NULL if none - wxPlotCurve *GetActiveCurve() const { return m_activeCurve; } - // Gets the currently active curve as a wxPlotFunction - // returns NULL if its not a wxPlotFunction, even if a curve is active - wxPlotFunction *GetActiveFuncCurve() const { return wxDynamicCast(m_activeCurve, wxPlotFunction); } - // Gets the currently active curve as a wxPlotData - // returns NULL if its not a wxPlotData, even if a curve is active - wxPlotData *GetActiveDataCurve() const { return wxDynamicCast(m_activeCurve, wxPlotData); } - - // Set the curve_index curve active, use -1 to have none selected - void SetActiveIndex( int curve_index, bool send_event=false ); - // Get the index of the active curve, returns -1 if none active - int GetActiveIndex() const { return m_active_index; } - - // Get an array of curve indexes that are of class wxPlotData, - // wxPlotFunction or derived from either - wxArrayInt GetPlotDataIndexes() const; - wxArrayInt GetPlotFunctionIndexes() const; - - //------------------------------------------------------------------------- - // Markers - //------------------------------------------------------------------------- - - // Add a marker to be displayed - int AddMarker( const wxPlotMarker& marker ); - - void RemoveMarker(int marker); - void ClearMarkers(); - - wxPlotMarker GetMarker(int marker) const; - wxArrayPlotMarker& GetMarkerArray() { return m_plotMarkers; } - - //------------------------------------------------------------------------- - // Cursor position - a single selected point in a curve - //------------------------------------------------------------------------- - - // Hide the cursor - void InvalidateCursor(bool send_event=false); - // Does the cursor point to a valid curve and if a data curve a valid data index - bool IsCursorValid(); - // Get the index of the curve that the cursor is associated with, -1 if none - int GetCursorCurveIndex() const { return m_cursor_curve; } - // Get the index into the wxPlotData curve of the cursor, -1 if not on a data curve - int GetCursorDataIndex() const { return m_cursor_index; } - // Get the location of the cursor, valid for all curve types if cursor valid - wxPoint2DDouble GetCursorPoint(); - // Set the curve and the index into the wxPlotData of the cursor - // curve_index must point to a data curve and cursor_index valid in data - bool SetCursorDataIndex(int curve_index, int cursor_index, bool send_event=false); - // Set the curve and the x-value of the cursor, valid for all curve types - // if curve_index is a wxPlotData curve it finds nearest index - bool SetCursorXPoint(int curve_index, double x, bool send_event=false); - // The cursor must be valid, if center then it centers the plot on the cursor - // if !center then make the cursor just barely visible by shifting the view - void MakeCursorVisible(bool center, bool send_event=false); - - //------------------------------------------------------------------------- - // Selected points - //------------------------------------------------------------------------- - - // Is anything selected in a particular curve or any curve if index = -1 - bool HasSelection(int curve_index = -1) const; - - // double valued selections can be made for wxPlotCurves and wxPlotFunctions - // for curves that are wxPlotData, the selection is empty, see GetDataCurveSelections - const wxArrayRangeDoubleSelection& GetCurveSelections() const { return m_curveSelections; } - // Get the particluar selection for the curve at index curve_index - wxRangeDoubleSelection *GetCurveSelection(int curve_index) const; - - // the selections of wxPlotData curves are of the indexes of the data - // for curves that are wxPlotCurves or wxPlotFunctions the selection is empty - const wxArrayRangeIntSelection& GetDataCurveSelections() const { return m_dataSelections; } - // Get the particluar selection for the curve at index curve_index - wxRangeIntSelection *GetDataCurveSelection(int curve_index) const; - - // Get the number of individual selections of this curve - int GetSelectedRangeCount(int curve_index) const; - - // Selects points in a curve using a rectangular selection (see select range) - // this works for all plotcurve classes, for wxPlotData they're converted to the indexes however - // if there's nothing to select or already selected it returns false - // if curve_index == -1 then try to select points in all curves - bool SelectRectangle( int curve_index, const wxRect2DDouble &rect, bool send_event = false) - { return DoSelectRectangle(curve_index, rect, true, send_event); } - bool DeselectRectangle( int curve_index, const wxRect2DDouble &rect, bool send_event = false) - { return DoSelectRectangle(curve_index, rect, false, send_event); } - - // Select a single point wxRangeDouble(pt,pt) or a data range wxRangeDouble(pt1, pt2) - // this works for all plotcurve classes, for wxPlotData they're converted to the indexes however - // if there's nothing to select or already selected it returns false - // if curve_index == -1 then try to select points in all curves - bool SelectXRange(int curve_index, const wxRangeDouble &range, bool send_event = false) - { return DoSelectRectangle(curve_index, wxRect2DDouble(range.m_min, -wxPlot_MAX_DBL, range.GetRange(), wxPlot_MAX_RANGE), true, send_event); } - bool DeselectXRange(int curve_index, const wxRangeDouble &range, bool send_event = false) - { return DoSelectRectangle(curve_index, wxRect2DDouble(range.m_min, -wxPlot_MAX_DBL, range.GetRange(), wxPlot_MAX_RANGE), false, send_event); } - bool SelectYRange(int curve_index, const wxRangeDouble &range, bool send_event = false) - { return DoSelectRectangle(curve_index, wxRect2DDouble(-wxPlot_MAX_DBL, range.m_min, wxPlot_MAX_RANGE, range.GetRange()), true, send_event); } - bool DeselectYRange(int curve_index, const wxRangeDouble &range, bool send_event = false) - { return DoSelectRectangle(curve_index, wxRect2DDouble(-wxPlot_MAX_DBL, range.m_min, wxPlot_MAX_RANGE, range.GetRange()), false, send_event); } - - // Select a single point wxRangeInt(pt, pt) or a range of points wxRangeInt(pt1, pt2) - // if there's nothing to select or already selected it returns false, - // this ONLY works for wxPlotData curves - bool SelectDataRange(int curve_index, const wxRangeInt &range, bool send_event = false) - { return DoSelectDataRange(curve_index, range, true, send_event); } - bool DeselectDataRange(int curve_index, const wxRangeInt &range, bool send_event = false) - { return DoSelectDataRange(curve_index, range, false, send_event); } - - // Clear the ranges, if curve_index = -1 then clear them all - bool ClearSelectedRanges(int curve_index, bool send_event = false); - - // internal use, or not... - virtual bool DoSelectRectangle(int curve_index, const wxRect2DDouble &rect, bool select, bool send_event = false); - virtual bool DoSelectDataRange(int curve_index, const wxRangeInt &range, bool select, bool send_event = false); - // called from DoSelect... when selecting to ensure that the current selection - // matches the SetSelectionType by unselecting as appropriate - // The input curve_index implies that a selection will be made for that curve - // This is not called for a deselection event. - virtual bool UpdateSelectionState(int curve_index, bool send_event); - - // Set how the selections mechanism operates, see enum wxPlotSelection_Type - // You are responsible to clean up the selections if you change this, - // however it won't fail, but may be out of sync. - void SetSelectionType(wxPlotSelection_Type type) { m_selection_type = type; } - int GetSelectionType() const { return m_selection_type; } - - // ------------------------------------------------------------------------ - // Get/Set origin, size, and Zoom in/out of view, set scaling, size... - // ------------------------------------------------------------------------ - - // make this curve fully visible or -1 to make all curves visible - // uses wxPlotCurve::GetBoundingRect() - // data curves have known sizes, function curves use default rect, unless set - bool MakeCurveVisible(int curve_index, bool send_event=false); - - // Set the origin of the plot window - bool SetOrigin( double origin_x, double origin_y, bool send_event=false ) - { return SetZoom( m_zoom.m_x, m_zoom.m_y, origin_x, origin_y, send_event ); } - - // Get the bounds of the plot window view in plot coords - const wxRect2DDouble& GetViewRect() const { return m_viewRect; } - // Set the bounds of the plot window - bool SetViewRect(const wxRect2DDouble &view, bool send_event=false); - - // Get the zoom factor = (pixel size of window)/(GetViewRect().m_width or height) - const wxPoint2DDouble& GetZoom() const { return m_zoom; } - - // Zoom, if zoom_x or zoom_y <= 0 then fit that axis to window and center it - bool SetZoom( const wxPoint2DDouble &zoom, bool around_center=true, bool send_event=false ); - virtual bool SetZoom( double zoom_x, double zoom_y, - double origin_x, double origin_y, bool send_event=false ); - - // Zoom in client coordinates, window.[xy] is top left (unlike plot axis) - bool SetZoom( const wxRect &window, bool send_event=false ); - - // Set/Get the default size the plot should take when either no curves are - // loaded or only plot(curves/functions) that have no bounds are loaded - // The width and the height must both be > 0 - void SetDefaultBoundingRect( const wxRect2DDouble &rect, bool send_event = false ); - const wxRect2DDouble& GetDefaultBoundingRect() const { return m_defaultPlotRect; } - - // Get the bounding rect of all the curves, - // equals the default if no curves or no bounds on the curves - const wxRect2DDouble& GetCurveBoundingRect() const { return m_curveBoundingRect; } - - // Get client rect of the wxPlotArea window, 0, 0, client_width, client_height - const wxRect& GetPlotAreaRect() const { return m_areaClientRect; } - - // The history of mouse drag rects are saved (mouseFunc_zoom) - void NextHistoryView(bool foward, bool send_event=false); - int GetHistoryViewCount() const { return m_historyViews.GetCount(); } - int GetHistoryViewIndex() const { return m_history_views_index; } - - // Fix the aspect ratio of the x and y axes, if set then when the zoom is - // set the smaller of the two (x or y) zooms is multiplied by the ratio - // to calculate the other. - void SetFixAspectRatio(bool fix, double ratio = 1.0); - void FixAspectRatio( double *zoom_x, double *zoom_y, double *origin_x, double *origin_y ); - - // ------------------------------------------------------------------------ - // Mouse Functions for the area window - // ------------------------------------------------------------------------ - - // The current (last) pixel position of the mouse in the plotArea - const wxPoint& GetAreaMouseCoord() const { return m_area->m_mousePt; } - - // The current plotArea position of the mouse cursor - wxPoint2DDouble GetAreaMousePoint() const - { return wxPoint2DDouble(GetPlotCoordFromClientX(m_area->m_mousePt.x), - GetPlotCoordFromClientY(m_area->m_mousePt.y)); } - - // Get the rect during dragging mouse, else 0 - const wxRect& GetAreaMouseMarkedRect() const { return m_area->m_mouseRect; } - - // Set what the mouse will do for different actions - void SetAreaMouseFunction(wxPlotMouse_Type func, bool send_event=false); - wxPlotMouse_Type GetAreaMouseFunction() const { return m_area_mouse_func; } - - // Set what sort of marker should be drawn when dragging mouse - void SetAreaMouseMarker(wxPlotMarker_Type type); - wxPlotMarker_Type GetAreaMouseMarker() const { return m_area_mouse_marker; } - - // Set the mouse cursor wxCURSOR_XXX + CURSOR_GRAB for the plot area - void SetAreaMouseCursor(wxStockCursor cursorid); - - // ------------------------------------------------------------------------ - // Options - // ------------------------------------------------------------------------ - - // Scroll the window only when the mouse button is released (for slow machines) - bool GetScrollOnThumbRelease() const { return m_scroll_on_thumb_release; } - void SetScrollOnThumbRelease( bool scrollOnThumbRelease = true ) - { m_scroll_on_thumb_release = scrollOnThumbRelease; } - - // Use a full width/height crosshair as a cursor - bool GetCrossHairCursor() const { return m_crosshair_cursor; } - void SetCrossHairCursor( bool useCrosshairCursor = false ) - { m_crosshair_cursor = useCrosshairCursor; - m_area->m_mousePt = wxPoint(-1,-1); Redraw(wxPLOT_REDRAW_PLOT); } - - // Draw the data curve symbols on the plotctrl - bool GetDrawSymbols() const { return m_draw_symbols; } - void SetDrawSymbols( bool drawsymbols = true ) - { m_draw_symbols = drawsymbols; Redraw(wxPLOT_REDRAW_PLOT); } - - // Draw the interconnecting straight lines between data points - bool GetDrawLines() const { return m_draw_lines; } - void SetDrawLines( bool drawlines = true ) - { m_draw_lines = drawlines; Redraw(wxPLOT_REDRAW_PLOT); } - - // Draw the interconnecting splines between data points - bool GetDrawSpline() const { return m_draw_spline; } - void SetDrawSpline( bool drawspline = false ) - { m_draw_spline = drawspline; Redraw(wxPLOT_REDRAW_PLOT); } - - // Draw the plot grid over the whole window, else just tick marks at edge - bool GetDrawGrid() const { return m_draw_grid; } - void SetDrawGrid( bool drawgrid = true ) - { m_draw_grid = drawgrid; Redraw(wxPLOT_REDRAW_PLOT); } - - // Try to fit the window to show all curves when a new curve is added - bool GetFitPlotOnNewCurve() const { return m_fit_on_new_curve; } - void SetFitPlotOnNewCurve( bool fit = true ) { m_fit_on_new_curve = fit; } - - // Set the focus to this window if the mouse enters it, otherwise you have to click - // sometimes convenient, but often this is annoying - bool GetGreedyFocus() const { return m_greedy_focus; } - void SetGreedyFocus(bool grab_focus = false) { m_greedy_focus = grab_focus; } - - // turn on or off the Correct Ticks functions. Turning this off allows a graph - // that scrolls to scroll smoothly in the direction expected. Turning this - // on (default) gives better accuracy for 'mouse hover' information display - bool GetCorrectTicks() const { return m_correct_ticks; } - void SetCorrectTicks( bool correct = true ) { m_correct_ticks = correct; } - - // get/set the width of a 1 pixel pen in mm for printing - double GetPrintingPenWidth(void) { return m_pen_print_width; } - void SetPrintingPenWidth(double width) { m_pen_print_width = width; } - - // ------------------------------------------------------------------------ - // Colours & Fonts for windows, labels, title... - // ------------------------------------------------------------------------ - - // Get/Set the background colour of all the plot windows, default white - wxColour GetBackgroundColour() const { return m_area->GetBackgroundColour(); } - virtual bool SetBackgroundColour( const wxColour &colour ); - - // Get/Set the colour of the grid lines in the plot area, default grey - wxColour GetGridColour() const { return m_area->GetForegroundColour(); } - void SetGridColour( const wxColour &colour ); - - // Get/Set the colour of the border around the plot area, default black - wxColour GetBorderColour() const { return m_borderColour; } - void SetBorderColour( const wxColour &colour ); - - // Get/Set the colour of the cursor marker, default green - wxColour GetCursorColour() const; - void SetCursorColour( const wxColour &colour ); - // Get/Set the cursor size, the size of the circle drawn for the cursor. - // set size to 0 to not have the cursor shown (default = 2) - int GetCursorSize() const; - void SetCursorSize(int size); - - // Get/Set the axis numbers font and colour, default normal & black - wxFont GetAxisFont() const; - wxColour GetAxisColour() const; - void SetAxisFont( const wxFont &font ); - void SetAxisColour( const wxColour &colour ); - - // Get/Set axis label fonts and colour, default swiss and black - wxFont GetAxisLabelFont() const; - wxColour GetAxisLabelColour() const; - void SetAxisLabelFont( const wxFont &font ); - void SetAxisLabelColour( const wxColour &colour ); - - // Get/Set the title font and colour, default swiss and black - wxFont GetPlotTitleFont() const { return m_titleFont; } - wxColour GetPlotTitleColour() const { return m_titleColour; } - void SetPlotTitleFont( const wxFont &font ); - void SetPlotTitleColour( const wxColour &colour ); - - // Get/Set the key font and colour - wxFont GetKeyFont() const; - wxColour GetKeyColour() const; - void SetKeyFont( const wxFont &font ); - void SetKeyColour( const wxColour & colour ); - - // ------------------------------------------------------------------------ - // Title, axis labels, and key values and visibility - // ------------------------------------------------------------------------ - - // Get/Set showing x and/or y axes - void SetShowXAxis(bool show) { m_show_xAxis = show; } - void SetShowYAxis(bool show) { m_show_yAxis = show; } - bool GetShowXAxis() { return m_show_xAxis; } - bool GetShowYAxis() { return m_show_yAxis; } - - // Get/Set and show/hide the axis labels - const wxString& GetXAxisLabel() const { return m_xLabel; } - const wxString& GetYAxisLabel() const { return m_yLabel; } - void SetXAxisLabel(const wxString &label); - void SetYAxisLabel(const wxString &label); - bool GetShowXAxisLabel() const { return m_show_xlabel; } - bool GetShowYAxisLabel() const { return m_show_ylabel; } - void SetShowXAxisLabel( bool show ) { m_show_xlabel = show; DoSize(); } - void SetShowYAxisLabel( bool show ) { m_show_ylabel = show; DoSize(); } - - // Get/Set and show/hide the title - const wxString& GetPlotTitle() const { return m_title; } - void SetPlotTitle(const wxString &title); - bool GetShowPlotTitle() const { return m_show_title; } - void SetShowPlotTitle( bool show ) { m_show_title = show; DoSize(); } - - // Show a key with the function/data names, pos is %width and %height (0-100) - const wxString& GetKeyString() const { return m_keyString; } - bool GetShowKey() const { return m_show_key; } - void SetShowKey(bool show) { m_show_key = show; Redraw(wxPLOT_REDRAW_PLOT); } - wxPoint GetKeyPosition() const; - bool GetKeyInside() const; - void SetKeyPosition(const wxPoint &pos, bool stay_inside = true); - - // used internally to update the key string from the curve names - virtual void CreateKeyString(); - - // set the minimum value to be displayed as an exponential on the axes - long GetMinExpValue() const { return m_min_exponential; } - void SetMinExpValue( long min ) { m_min_exponential = min; } - - // ------------------------------------------------------------------------ - // Title, axis label editor control - // ------------------------------------------------------------------------ - - enum wxPlotCtrlTextCtrl_Type - { - wxPLOT_EDIT_TITLE = 1, - wxPLOT_EDIT_XAXIS, - wxPLOT_EDIT_YAXIS, - }; - - // Sends the wxEVT_PLOT_BEGIN_TITLE_(X/Y_LABEL)_EDIT event if send_event - // which can be vetoed - void ShowTextCtrl(wxPlotCtrlTextCtrl_Type type, bool send_event = false); - // Sends the wxEVT_PLOT_END_TITLE_(X/Y_LABEL)_EDIT event if send_event - // which can be vetoed - void HideTextCtrl(bool save_value = true, bool send_event = false); - bool IsTextCtrlShown() const; - - // ------------------------------------------------------------------------ - // Event processing - // ------------------------------------------------------------------------ - - // EVT_MOUSE_EVENTS from the area and axis windows are passed to these functions - virtual void ProcessAreaEVT_MOUSE_EVENTS( wxMouseEvent &event ); - virtual void ProcessAxisEVT_MOUSE_EVENTS( wxMouseEvent &event ); - - // EVT_CHAR from the area and axis windows are passed to these functions - virtual void ProcessAreaEVT_CHAR( wxKeyEvent &event ) { OnChar(event); return; } - virtual void ProcessAreaEVT_KEY_DOWN( wxKeyEvent &event ); - virtual void ProcessAreaEVT_KEY_UP( wxKeyEvent &event ); - virtual void ProcessAxisEVT_CHAR( wxKeyEvent &event ) { OnChar(event); return; } - - void OnChar( wxKeyEvent &event ); - void OnScroll( wxScrollEvent& event ); - void OnPaint( wxPaintEvent &event ); - void OnEraseBackground( wxEraseEvent &event ) { event.Skip(false); } - void OnIdle( wxIdleEvent &event ); - void OnMouse( wxMouseEvent &event ); - void OnTextEnter( wxCommandEvent &event ); - - // ------------------------------------------------------------------------ - // Drawing functions - // ------------------------------------------------------------------------ - - // call BeginBatch to disable redrawing EndBatch to reenable and refresh - // when batchcount == 0, if !force_refresh then don't refresh when batch == 0 - void BeginBatch() { m_batch_count++; } - void EndBatch(bool force_refresh = true); - int GetBatchCount() const { return m_batch_count; } - - // Redraw parts of the plotctrl using combinations of wxPlot_Redraw_Type - void Redraw(int type); - // Get/Set the redraw type variable (this is for internal use, see Redraw()) - int GetRedrawType() const { return m_redraw_type; } - void SetRedrawType(int type) { m_redraw_type = type; } - - // Draw a marker in lower right signifying that this has the focus - virtual void DrawActiveBitmap( wxDC *dc ); - // Draw the wxPlotCtrl (this window) - virtual void DrawPlotCtrl( wxDC *dc ); - // Draw the area window - virtual void DrawAreaWindow( wxDC *dc, const wxRect& rect ); - // Draw a wxPlotData derived curve - virtual void DrawDataCurve( wxDC *dc, wxPlotData *curve, int curve_index, const wxRect &rect ); - // Draw a generic wxPlotCurve curve - virtual void DrawCurve( wxDC *dc, wxPlotCurve *curve, int curve_index, const wxRect &rect ); - // Draw the key - virtual void DrawKey( wxDC *dc ); - // Draw the left click drag marker, type is wxPlot_Marker_Type - virtual void DrawMouseMarker( wxDC *dc, int type, const wxRect &rect ); - // Draw a crosshair cursor at the point (mouse cursor) - virtual void DrawCrosshairCursor( wxDC *dc, const wxPoint &pos ); - // Draw the cursor marking a single point in a curve wxPlotCtrl::GetCursorPoint - virtual void DrawCurveCursor( wxDC *dc ); - // Draw the tick marks or grid lines - virtual void DrawTickMarks( wxDC *dc, const wxRect& rect ); - // Draw markers - virtual void DrawMarkers( wxDC *dc, const wxRect& rect ); - - // redraw this wxPlotData between these two indexes (for (de)select redraw) - virtual void RedrawDataCurve(int index, int min_index, int max_index); - // redraw this wxPlotCurve between these two values (for (de)select redraw) - virtual void RedrawCurve(int index, double min_x, double max_x); - - // Draw the X or Y axis onto the dc - virtual void DrawXAxis( wxDC *dc, bool refresh ); - virtual void DrawYAxis( wxDC *dc, bool refresh ); - - // Draw the plot axes and plotctrl on this wxDC for printing, sort of WYSIWYG - // the plot is drawn to fit inside the boundingRect (i.e. the margins) - void DrawWholePlot( wxDC *dc, const wxRect &boundingRect, int dpi = 72 ); - - // ------------------------------------------------------------------------ - // Axis tick calculations - // ------------------------------------------------------------------------ - - // find the optimal number of ticks, step size, and format string - void AutoCalcTicks() { AutoCalcXAxisTicks(); AutoCalcYAxisTicks(); } - void AutoCalcXAxisTicks() { DoAutoCalcTicks(true); } - void AutoCalcYAxisTicks() { DoAutoCalcTicks(false); } - virtual void DoAutoCalcTicks(bool x_axis); - // slightly correct the Zoom and origin to exactly match tick marks - // otherwise when the mouse is over '1' you may get 0.99999 or 1.000001 - void CorrectTicks() { CorrectXAxisTicks(); CorrectYAxisTicks(); } - void CorrectXAxisTicks(); - void CorrectYAxisTicks(); - // Find the correct dc coords for the tick marks and label strings, internal use - void CalcTickPositions() { CalcXAxisTickPositions(); CalcYAxisTickPositions(); } - virtual void CalcXAxisTickPositions(); - virtual void CalcYAxisTickPositions(); - - // ------------------------------------------------------------------------ - // Utilities - // ------------------------------------------------------------------------ - - // Find a curve at pt, in rect of size +- dxdyPt, starting with active curve - // return sucess, setting curve_index, data_index if data curve, and if - // curvePt fills the exact point in the curve. - bool FindCurve(const wxPoint2DDouble &pt, const wxPoint2DDouble &dxdyPt, - int &curve_index, int &data_index, wxPoint2DDouble *curvePt = NULL) const; - - // if n is !finite send wxEVT_PLOT_ERROR if msg is not empty - bool IsFinite(double n, const wxString &msg = wxEmptyString) const; - - // call this whenever you adjust the size of a data curve - // this necessary to know the default zoom to show them - void CalcBoundingPlotRect(); - - // Client (pixels) to/from plot (double) coords - inline double GetPlotCoordFromClientX( int clientx ) const - { return (clientx/m_zoom.m_x + m_viewRect.GetLeft()); } - inline double GetPlotCoordFromClientY( int clienty ) const - { return ((m_areaClientRect.height - clienty)/m_zoom.m_y + m_viewRect.GetTop());} - inline wxRect2DDouble GetPlotRectFromClientRect( const wxRect &clientRect ) const - { - return wxRect2DDouble( GetPlotCoordFromClientX(clientRect.x), - GetPlotCoordFromClientY(clientRect.GetBottom()), - clientRect.width/m_zoom.m_x, - clientRect.height/m_zoom.m_y ); - } - - inline int GetClientCoordFromPlotX( double plotx ) const - { double x = m_zoom.m_x*(plotx - m_viewRect.GetLeft()) + 0.5; return x < INT_MAX ? int(x) : INT_MAX; } - inline int GetClientCoordFromPlotY( double ploty ) const - { double y = m_areaClientRect.height - m_zoom.m_y*(ploty - m_viewRect.GetTop()) + 0.5; return y < INT_MAX ? int(y) : INT_MAX; } - inline wxRect GetClientRectFromPlotRect( const wxRect2DDouble &plotRect ) const - { - double w = plotRect.m_width*m_zoom.m_x + 0.5; - double h = plotRect.m_height*m_zoom.m_y + 0.5; - return wxRect( GetClientCoordFromPlotX(plotRect.m_x), - GetClientCoordFromPlotY(plotRect.GetBottom()), - w < INT_MAX ? int(w) : INT_MAX, - h < INT_MAX ? int(h) : INT_MAX ); - } - - // IDs for the children windows - enum - { - ID_PLOTCTRL_X_AXIS = 100, - ID_PLOTCTRL_Y_AXIS, - ID_PLOTCTRL_AREA, - ID_PLOTCTRL_X_SCROLLBAR, - ID_PLOTCTRL_Y_SCROLLBAR - }; - - // Get the windows - wxPlotArea* GetPlotArea() const { return m_area; } - wxPlotAxis* GetPlotXAxis() const { return m_xAxis; } - wxPlotAxis* GetPlotYAxis() const { return m_yAxis; } - - // internal use size adjustment - void AdjustScrollBars(); - void UpdateWindowSize(); - void DoSize(const wxRect &boundingRect = wxRect(0, 0, 0, 0)); - - // who's got the focus, if this then draw the bitmap to show it, internal - bool CheckFocus(); - - // send event returning true if it's allowed - bool DoSendEvent(wxPlotEvent &event) const; - - // Start the mouse timer with the win_id, stops old if for different id - enum mouseTimerIDs - { - ID_AREA_TIMER = 10, - ID_XAXIS_TIMER, - ID_YAXIS_TIMER - }; - void StartMouseTimer(wxWindowID win_id); - void StopMouseTimer(); - bool IsTimerRunning(); - void OnTimer( wxTimerEvent &event ); - - // A locker for the captured window, set to NULL to release - void SetCaptureWindow( wxWindow *win ); - wxWindow *GetCaptureWindow() const { return m_winCapture; } + wxPlotCtrl() : wxWindow() { Init(); } + + wxPlotCtrl(wxWindow *parent, wxWindowID win_id = wxID_ANY, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + wxPlotAxis_Type flags = wxPLOT_DEFAULT, const wxString &name = wxT("wxPlotCtrl")) + { + Init(); + (void)Create(parent, win_id, pos, size, flags, name); + } + + bool Create(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, wxPlotAxis_Type flags = wxPLOT_DEFAULT, + const wxString &name = wxT("wxPlotCtrl")); + + virtual ~wxPlotCtrl(); + + // ------------------------------------------------------------------------ + // Curve Accessors + // + // note: the curves are stored in an array casted to class wxPlotCurve + // in order to know the type and use it as a wxPlotFunction, wxPlotData + // or a class derived from one of these use + // wxPlotData *pd = wxDynamicCast( GetCurve(i), wxPlotData ); + // pd will be NULL if GetCurve isn't a wxPlotData (or derived from it) + // ------------------------------------------------------------------------ + + // Add a curve to the plot, takes ownership of the curve and deletes it + bool AddCurve(wxPlotCurve *curve, bool select = true, bool send_event = false); + // Add a curve to the plot, increases ref count + bool AddCurve(const wxPlotCurve &curve, bool select = true, bool send_event = false); + // Delete this curve + bool DeleteCurve(wxPlotCurve *curve, bool send_event = false); + // Delete this curve, if curve_index = -1, delete all curves + bool DeleteCurve(int curve_index, bool send_event = false); + + // Total number of curves associated with the plotctrl + int GetCurveCount() const { return m_curves.GetCount(); } + bool CurveIndexOk(int curve_index) const + { + return (curve_index >= 0) && (curve_index < int(m_curves.GetCount())); + } + + // Get the curve at this index + wxPlotCurve *GetCurve(int curve_index) const; + // returns NULL if curve_index is not wxPlotData or derived from it + wxPlotData *GetDataCurve(int curve_index) const + { + return wxDynamicCast(GetCurve(curve_index), wxPlotData); + } + // returns NULL if curve_index is not wxPlotFunction or derived from it + wxPlotFunction *GetFunctionCurve(int curve_index) const + { + return wxDynamicCast(GetCurve(curve_index), wxPlotFunction); + } + // returns true if the curve is a wxPlotData curve + bool IsDataCurve(int curve_index) const { return GetDataCurve(curve_index) != NULL; } + // returns true if the curve is a wxPlotFunction curve + bool IsFunctionCurve(int curve_index) const { return GetFunctionCurve(curve_index) != NULL; } + // Else the function must be some sort of subclassed wxPlotCurve + + // Sets the currently active curve, NULL for none active + void SetActiveCurve(wxPlotCurve *curve, bool send_event = false); + // Gets the currently active curve, NULL if none + wxPlotCurve *GetActiveCurve() const { return m_activeCurve; } + // Gets the currently active curve as a wxPlotFunction + // returns NULL if its not a wxPlotFunction, even if a curve is active + wxPlotFunction *GetActiveFuncCurve() const + { + return wxDynamicCast(m_activeCurve, wxPlotFunction); + } + // Gets the currently active curve as a wxPlotData + // returns NULL if its not a wxPlotData, even if a curve is active + wxPlotData *GetActiveDataCurve() const { return wxDynamicCast(m_activeCurve, wxPlotData); } + + // Set the curve_index curve active, use -1 to have none selected + void SetActiveIndex(int curve_index, bool send_event = false); + // Get the index of the active curve, returns -1 if none active + int GetActiveIndex() const { return m_active_index; } + + // Get an array of curve indexes that are of class wxPlotData, + // wxPlotFunction or derived from either + wxArrayInt GetPlotDataIndexes() const; + wxArrayInt GetPlotFunctionIndexes() const; + + //------------------------------------------------------------------------- + // Markers + //------------------------------------------------------------------------- + + // Add a marker to be displayed + int AddMarker(const wxPlotMarker &marker); + + void RemoveMarker(int marker); + void ClearMarkers(); + + wxPlotMarker GetMarker(int marker) const; + wxArrayPlotMarker &GetMarkerArray() { return m_plotMarkers; } + + //------------------------------------------------------------------------- + // Cursor position - a single selected point in a curve + //------------------------------------------------------------------------- + + // Hide the cursor + void InvalidateCursor(bool send_event = false); + // Does the cursor point to a valid curve and if a data curve a valid data index + bool IsCursorValid(); + // Get the index of the curve that the cursor is associated with, -1 if none + int GetCursorCurveIndex() const { return m_cursor_curve; } + // Get the index into the wxPlotData curve of the cursor, -1 if not on a data curve + int GetCursorDataIndex() const { return m_cursor_index; } + // Get the location of the cursor, valid for all curve types if cursor valid + wxPoint2DDouble GetCursorPoint(); + // Set the curve and the index into the wxPlotData of the cursor + // curve_index must point to a data curve and cursor_index valid in data + bool SetCursorDataIndex(int curve_index, int cursor_index, bool send_event = false); + // Set the curve and the x-value of the cursor, valid for all curve types + // if curve_index is a wxPlotData curve it finds nearest index + bool SetCursorXPoint(int curve_index, double x, bool send_event = false); + // The cursor must be valid, if center then it centers the plot on the cursor + // if !center then make the cursor just barely visible by shifting the view + void MakeCursorVisible(bool center, bool send_event = false); + + //------------------------------------------------------------------------- + // Selected points + //------------------------------------------------------------------------- + + // Is anything selected in a particular curve or any curve if index = -1 + bool HasSelection(int curve_index = -1) const; + + // double valued selections can be made for wxPlotCurves and wxPlotFunctions + // for curves that are wxPlotData, the selection is empty, see GetDataCurveSelections + const wxArrayRangeDoubleSelection &GetCurveSelections() const { return m_curveSelections; } + // Get the particluar selection for the curve at index curve_index + wxRangeDoubleSelection *GetCurveSelection(int curve_index) const; + + // the selections of wxPlotData curves are of the indexes of the data + // for curves that are wxPlotCurves or wxPlotFunctions the selection is empty + const wxArrayRangeIntSelection &GetDataCurveSelections() const { return m_dataSelections; } + // Get the particluar selection for the curve at index curve_index + wxRangeIntSelection *GetDataCurveSelection(int curve_index) const; + + // Get the number of individual selections of this curve + int GetSelectedRangeCount(int curve_index) const; + + // Selects points in a curve using a rectangular selection (see select range) + // this works for all plotcurve classes, for wxPlotData they're converted to the indexes + // however if there's nothing to select or already selected it returns false if curve_index == + // -1 then try to select points in all curves + bool SelectRectangle(int curve_index, const wxRect2DDouble &rect, bool send_event = false) + { + return DoSelectRectangle(curve_index, rect, true, send_event); + } + bool DeselectRectangle(int curve_index, const wxRect2DDouble &rect, bool send_event = false) + { + return DoSelectRectangle(curve_index, rect, false, send_event); + } + + // Select a single point wxRangeDouble(pt,pt) or a data range wxRangeDouble(pt1, pt2) + // this works for all plotcurve classes, for wxPlotData they're converted to the indexes + // however if there's nothing to select or already selected it returns false if curve_index == + // -1 then try to select points in all curves + bool SelectXRange(int curve_index, const wxRangeDouble &range, bool send_event = false) + { + return DoSelectRectangle( + curve_index, + wxRect2DDouble(range.m_min, -wxPlot_MAX_DBL, range.GetRange(), wxPlot_MAX_RANGE), true, + send_event); + } + bool DeselectXRange(int curve_index, const wxRangeDouble &range, bool send_event = false) + { + return DoSelectRectangle( + curve_index, + wxRect2DDouble(range.m_min, -wxPlot_MAX_DBL, range.GetRange(), wxPlot_MAX_RANGE), false, + send_event); + } + bool SelectYRange(int curve_index, const wxRangeDouble &range, bool send_event = false) + { + return DoSelectRectangle( + curve_index, + wxRect2DDouble(-wxPlot_MAX_DBL, range.m_min, wxPlot_MAX_RANGE, range.GetRange()), true, + send_event); + } + bool DeselectYRange(int curve_index, const wxRangeDouble &range, bool send_event = false) + { + return DoSelectRectangle( + curve_index, + wxRect2DDouble(-wxPlot_MAX_DBL, range.m_min, wxPlot_MAX_RANGE, range.GetRange()), false, + send_event); + } + + // Select a single point wxRangeInt(pt, pt) or a range of points wxRangeInt(pt1, pt2) + // if there's nothing to select or already selected it returns false, + // this ONLY works for wxPlotData curves + bool SelectDataRange(int curve_index, const wxRangeInt &range, bool send_event = false) + { + return DoSelectDataRange(curve_index, range, true, send_event); + } + bool DeselectDataRange(int curve_index, const wxRangeInt &range, bool send_event = false) + { + return DoSelectDataRange(curve_index, range, false, send_event); + } + + // Clear the ranges, if curve_index = -1 then clear them all + bool ClearSelectedRanges(int curve_index, bool send_event = false); + + // internal use, or not... + virtual bool DoSelectRectangle(int curve_index, const wxRect2DDouble &rect, bool select, + bool send_event = false); + virtual bool DoSelectDataRange(int curve_index, const wxRangeInt &range, bool select, + bool send_event = false); + // called from DoSelect... when selecting to ensure that the current selection + // matches the SetSelectionType by unselecting as appropriate + // The input curve_index implies that a selection will be made for that curve + // This is not called for a deselection event. + virtual bool UpdateSelectionState(int curve_index, bool send_event); + + // Set how the selections mechanism operates, see enum wxPlotSelection_Type + // You are responsible to clean up the selections if you change this, + // however it won't fail, but may be out of sync. + void SetSelectionType(wxPlotSelection_Type type) { m_selection_type = type; } + int GetSelectionType() const { return m_selection_type; } + + // ------------------------------------------------------------------------ + // Get/Set origin, size, and Zoom in/out of view, set scaling, size... + // ------------------------------------------------------------------------ + + // make this curve fully visible or -1 to make all curves visible + // uses wxPlotCurve::GetBoundingRect() + // data curves have known sizes, function curves use default rect, unless set + bool MakeCurveVisible(int curve_index, bool send_event = false); + + // Set the origin of the plot window + bool SetOrigin(double origin_x, double origin_y, bool send_event = false) + { + return SetZoom(m_zoom.m_x, m_zoom.m_y, origin_x, origin_y, send_event); + } + + // Get the bounds of the plot window view in plot coords + const wxRect2DDouble &GetViewRect() const { return m_viewRect; } + // Set the bounds of the plot window + bool SetViewRect(const wxRect2DDouble &view, bool send_event = false); + + // Get the zoom factor = (pixel size of window)/(GetViewRect().m_width or height) + const wxPoint2DDouble &GetZoom() const { return m_zoom; } + + // Zoom, if zoom_x or zoom_y <= 0 then fit that axis to window and center it + bool SetZoom(const wxPoint2DDouble &zoom, bool around_center = true, bool send_event = false); + virtual bool SetZoom(double zoom_x, double zoom_y, double origin_x, double origin_y, + bool send_event = false); + + // Zoom in client coordinates, window.[xy] is top left (unlike plot axis) + bool SetZoom(const wxRect &window, bool send_event = false); + + // Set/Get the default size the plot should take when either no curves are + // loaded or only plot(curves/functions) that have no bounds are loaded + // The width and the height must both be > 0 + void SetDefaultBoundingRect(const wxRect2DDouble &rect, bool send_event = false); + const wxRect2DDouble &GetDefaultBoundingRect() const { return m_defaultPlotRect; } + + // Get the bounding rect of all the curves, + // equals the default if no curves or no bounds on the curves + const wxRect2DDouble &GetCurveBoundingRect() const { return m_curveBoundingRect; } + + // Get client rect of the wxPlotArea window, 0, 0, client_width, client_height + const wxRect &GetPlotAreaRect() const { return m_areaClientRect; } + + // The history of mouse drag rects are saved (mouseFunc_zoom) + void NextHistoryView(bool foward, bool send_event = false); + int GetHistoryViewCount() const { return m_historyViews.GetCount(); } + int GetHistoryViewIndex() const { return m_history_views_index; } + + // Fix the aspect ratio of the x and y axes, if set then when the zoom is + // set the smaller of the two (x or y) zooms is multiplied by the ratio + // to calculate the other. + void SetFixAspectRatio(bool fix, double ratio = 1.0); + void FixAspectRatio(double *zoom_x, double *zoom_y, double *origin_x, double *origin_y); + + // ------------------------------------------------------------------------ + // Mouse Functions for the area window + // ------------------------------------------------------------------------ + + // The current (last) pixel position of the mouse in the plotArea + const wxPoint &GetAreaMouseCoord() const { return m_area->m_mousePt; } + + // The current plotArea position of the mouse cursor + wxPoint2DDouble GetAreaMousePoint() const + { + return wxPoint2DDouble(GetPlotCoordFromClientX(m_area->m_mousePt.x), + GetPlotCoordFromClientY(m_area->m_mousePt.y)); + } + + // Get the rect during dragging mouse, else 0 + const wxRect &GetAreaMouseMarkedRect() const { return m_area->m_mouseRect; } + + // Set what the mouse will do for different actions + void SetAreaMouseFunction(wxPlotMouse_Type func, bool send_event = false); + wxPlotMouse_Type GetAreaMouseFunction() const { return m_area_mouse_func; } + + // Set what sort of marker should be drawn when dragging mouse + void SetAreaMouseMarker(wxPlotMarker_Type type); + wxPlotMarker_Type GetAreaMouseMarker() const { return m_area_mouse_marker; } + + // Set the mouse cursor wxCURSOR_XXX + CURSOR_GRAB for the plot area + void SetAreaMouseCursor(wxStockCursor cursorid); + + // ------------------------------------------------------------------------ + // Options + // ------------------------------------------------------------------------ + + // Scroll the window only when the mouse button is released (for slow machines) + bool GetScrollOnThumbRelease() const { return m_scroll_on_thumb_release; } + void SetScrollOnThumbRelease(bool scrollOnThumbRelease = true) + { + m_scroll_on_thumb_release = scrollOnThumbRelease; + } + + // Use a full width/height crosshair as a cursor + bool GetCrossHairCursor() const { return m_crosshair_cursor; } + void SetCrossHairCursor(bool useCrosshairCursor = false) + { + m_crosshair_cursor = useCrosshairCursor; + m_area->m_mousePt = wxPoint(-1, -1); + Redraw(wxPLOT_REDRAW_PLOT); + } + + // Draw the data curve symbols on the plotctrl + bool GetDrawSymbols() const { return m_draw_symbols; } + void SetDrawSymbols(bool drawsymbols = true) + { + m_draw_symbols = drawsymbols; + Redraw(wxPLOT_REDRAW_PLOT); + } + + // Draw the interconnecting straight lines between data points + bool GetDrawLines() const { return m_draw_lines; } + void SetDrawLines(bool drawlines = true) + { + m_draw_lines = drawlines; + Redraw(wxPLOT_REDRAW_PLOT); + } + + // Draw the interconnecting splines between data points + bool GetDrawSpline() const { return m_draw_spline; } + void SetDrawSpline(bool drawspline = false) + { + m_draw_spline = drawspline; + Redraw(wxPLOT_REDRAW_PLOT); + } + + // Draw the plot grid over the whole window, else just tick marks at edge + bool GetDrawGrid() const { return m_draw_grid; } + void SetDrawGrid(bool drawgrid = true) + { + m_draw_grid = drawgrid; + Redraw(wxPLOT_REDRAW_PLOT); + } + + // Try to fit the window to show all curves when a new curve is added + bool GetFitPlotOnNewCurve() const { return m_fit_on_new_curve; } + void SetFitPlotOnNewCurve(bool fit = true) { m_fit_on_new_curve = fit; } + + // Set the focus to this window if the mouse enters it, otherwise you have to click + // sometimes convenient, but often this is annoying + bool GetGreedyFocus() const { return m_greedy_focus; } + void SetGreedyFocus(bool grab_focus = false) { m_greedy_focus = grab_focus; } + + // turn on or off the Correct Ticks functions. Turning this off allows a graph + // that scrolls to scroll smoothly in the direction expected. Turning this + // on (default) gives better accuracy for 'mouse hover' information display + bool GetCorrectTicks() const { return m_correct_ticks; } + void SetCorrectTicks(bool correct = true) { m_correct_ticks = correct; } + + // get/set the width of a 1 pixel pen in mm for printing + double GetPrintingPenWidth(void) { return m_pen_print_width; } + void SetPrintingPenWidth(double width) { m_pen_print_width = width; } + + // ------------------------------------------------------------------------ + // Colours & Fonts for windows, labels, title... + // ------------------------------------------------------------------------ + + // Get/Set the background colour of all the plot windows, default white + wxColour GetBackgroundColour() const { return m_area->GetBackgroundColour(); } + virtual bool SetBackgroundColour(const wxColour &colour); + + // Get/Set the colour of the grid lines in the plot area, default grey + wxColour GetGridColour() const { return m_area->GetForegroundColour(); } + void SetGridColour(const wxColour &colour); + + // Get/Set the colour of the border around the plot area, default black + wxColour GetBorderColour() const { return m_borderColour; } + void SetBorderColour(const wxColour &colour); + + // Get/Set the colour of the cursor marker, default green + wxColour GetCursorColour() const; + void SetCursorColour(const wxColour &colour); + // Get/Set the cursor size, the size of the circle drawn for the cursor. + // set size to 0 to not have the cursor shown (default = 2) + int GetCursorSize() const; + void SetCursorSize(int size); + + // Get/Set the axis numbers font and colour, default normal & black + wxFont GetAxisFont() const; + wxColour GetAxisColour() const; + void SetAxisFont(const wxFont &font); + void SetAxisColour(const wxColour &colour); + + // Get/Set axis label fonts and colour, default swiss and black + wxFont GetAxisLabelFont() const; + wxColour GetAxisLabelColour() const; + void SetAxisLabelFont(const wxFont &font); + void SetAxisLabelColour(const wxColour &colour); + + // Get/Set the title font and colour, default swiss and black + wxFont GetPlotTitleFont() const { return m_titleFont; } + wxColour GetPlotTitleColour() const { return m_titleColour; } + void SetPlotTitleFont(const wxFont &font); + void SetPlotTitleColour(const wxColour &colour); + + // Get/Set the key font and colour + wxFont GetKeyFont() const; + wxColour GetKeyColour() const; + void SetKeyFont(const wxFont &font); + void SetKeyColour(const wxColour &colour); + + // ------------------------------------------------------------------------ + // Title, axis labels, and key values and visibility + // ------------------------------------------------------------------------ + + // Get/Set showing x and/or y axes + void SetShowXAxis(bool show) { m_show_xAxis = show; } + void SetShowYAxis(bool show) { m_show_yAxis = show; } + bool GetShowXAxis() { return m_show_xAxis; } + bool GetShowYAxis() { return m_show_yAxis; } + + // Get/Set and show/hide the axis labels + const wxString &GetXAxisLabel() const { return m_xLabel; } + const wxString &GetYAxisLabel() const { return m_yLabel; } + void SetXAxisLabel(const wxString &label); + void SetYAxisLabel(const wxString &label); + bool GetShowXAxisLabel() const { return m_show_xlabel; } + bool GetShowYAxisLabel() const { return m_show_ylabel; } + void SetShowXAxisLabel(bool show) + { + m_show_xlabel = show; + DoSize(); + } + void SetShowYAxisLabel(bool show) + { + m_show_ylabel = show; + DoSize(); + } + + // Get/Set and show/hide the title + const wxString &GetPlotTitle() const { return m_title; } + void SetPlotTitle(const wxString &title); + bool GetShowPlotTitle() const { return m_show_title; } + void SetShowPlotTitle(bool show) + { + m_show_title = show; + DoSize(); + } + + // Show a key with the function/data names, pos is %width and %height (0-100) + const wxString &GetKeyString() const { return m_keyString; } + bool GetShowKey() const { return m_show_key; } + void SetShowKey(bool show) + { + m_show_key = show; + Redraw(wxPLOT_REDRAW_PLOT); + } + wxPoint GetKeyPosition() const; + bool GetKeyInside() const; + void SetKeyPosition(const wxPoint &pos, bool stay_inside = true); + + // used internally to update the key string from the curve names + virtual void CreateKeyString(); + + // set the minimum value to be displayed as an exponential on the axes + long GetMinExpValue() const { return m_min_exponential; } + void SetMinExpValue(long min) { m_min_exponential = min; } + + // ------------------------------------------------------------------------ + // Title, axis label editor control + // ------------------------------------------------------------------------ + + enum wxPlotCtrlTextCtrl_Type { + wxPLOT_EDIT_TITLE = 1, + wxPLOT_EDIT_XAXIS, + wxPLOT_EDIT_YAXIS, + }; + + // Sends the wxEVT_PLOT_BEGIN_TITLE_(X/Y_LABEL)_EDIT event if send_event + // which can be vetoed + void ShowTextCtrl(wxPlotCtrlTextCtrl_Type type, bool send_event = false); + // Sends the wxEVT_PLOT_END_TITLE_(X/Y_LABEL)_EDIT event if send_event + // which can be vetoed + void HideTextCtrl(bool save_value = true, bool send_event = false); + bool IsTextCtrlShown() const; + + // ------------------------------------------------------------------------ + // Event processing + // ------------------------------------------------------------------------ + + // EVT_MOUSE_EVENTS from the area and axis windows are passed to these functions + virtual void ProcessAreaEVT_MOUSE_EVENTS(wxMouseEvent &event); + virtual void ProcessAxisEVT_MOUSE_EVENTS(wxMouseEvent &event); + + // EVT_CHAR from the area and axis windows are passed to these functions + virtual void ProcessAreaEVT_CHAR(wxKeyEvent &event) + { + OnChar(event); + return; + } + virtual void ProcessAreaEVT_KEY_DOWN(wxKeyEvent &event); + virtual void ProcessAreaEVT_KEY_UP(wxKeyEvent &event); + virtual void ProcessAxisEVT_CHAR(wxKeyEvent &event) + { + OnChar(event); + return; + } + + void OnChar(wxKeyEvent &event); + void OnScroll(wxScrollEvent &event); + void OnPaint(wxPaintEvent &event); + void OnEraseBackground(wxEraseEvent &event) { event.Skip(false); } + void OnIdle(wxIdleEvent &event); + void OnMouse(wxMouseEvent &event); + void OnTextEnter(wxCommandEvent &event); + + // ------------------------------------------------------------------------ + // Drawing functions + // ------------------------------------------------------------------------ + + // call BeginBatch to disable redrawing EndBatch to reenable and refresh + // when batchcount == 0, if !force_refresh then don't refresh when batch == 0 + void BeginBatch() { m_batch_count++; } + void EndBatch(bool force_refresh = true); + int GetBatchCount() const { return m_batch_count; } + + // Redraw parts of the plotctrl using combinations of wxPlot_Redraw_Type + void Redraw(int type); + // Get/Set the redraw type variable (this is for internal use, see Redraw()) + int GetRedrawType() const { return m_redraw_type; } + void SetRedrawType(int type) { m_redraw_type = type; } + + // Draw a marker in lower right signifying that this has the focus + virtual void DrawActiveBitmap(wxDC *dc); + // Draw the wxPlotCtrl (this window) + virtual void DrawPlotCtrl(wxDC *dc); + // Draw the area window + virtual void DrawAreaWindow(wxDC *dc, const wxRect &rect); + // Draw a wxPlotData derived curve + virtual void DrawDataCurve(wxDC *dc, wxPlotData *curve, int curve_index, const wxRect &rect); + // Draw a generic wxPlotCurve curve + virtual void DrawCurve(wxDC *dc, wxPlotCurve *curve, int curve_index, const wxRect &rect); + // Draw the key + virtual void DrawKey(wxDC *dc); + // Draw the left click drag marker, type is wxPlot_Marker_Type + virtual void DrawMouseMarker(wxDC *dc, int type, const wxRect &rect); + // Draw a crosshair cursor at the point (mouse cursor) + virtual void DrawCrosshairCursor(wxDC *dc, const wxPoint &pos); + // Draw the cursor marking a single point in a curve wxPlotCtrl::GetCursorPoint + virtual void DrawCurveCursor(wxDC *dc); + // Draw the tick marks or grid lines + virtual void DrawTickMarks(wxDC *dc, const wxRect &rect); + // Draw markers + virtual void DrawMarkers(wxDC *dc, const wxRect &rect); + + // redraw this wxPlotData between these two indexes (for (de)select redraw) + virtual void RedrawDataCurve(int index, int min_index, int max_index); + // redraw this wxPlotCurve between these two values (for (de)select redraw) + virtual void RedrawCurve(int index, double min_x, double max_x); + + // Draw the X or Y axis onto the dc + virtual void DrawXAxis(wxDC *dc, bool refresh); + virtual void DrawYAxis(wxDC *dc, bool refresh); + + // Draw the plot axes and plotctrl on this wxDC for printing, sort of WYSIWYG + // the plot is drawn to fit inside the boundingRect (i.e. the margins) + void DrawWholePlot(wxDC *dc, const wxRect &boundingRect, int dpi = 72); + + // ------------------------------------------------------------------------ + // Axis tick calculations + // ------------------------------------------------------------------------ + + // find the optimal number of ticks, step size, and format string + void AutoCalcTicks() + { + AutoCalcXAxisTicks(); + AutoCalcYAxisTicks(); + } + void AutoCalcXAxisTicks() { DoAutoCalcTicks(true); } + void AutoCalcYAxisTicks() { DoAutoCalcTicks(false); } + virtual void DoAutoCalcTicks(bool x_axis); + // slightly correct the Zoom and origin to exactly match tick marks + // otherwise when the mouse is over '1' you may get 0.99999 or 1.000001 + void CorrectTicks() + { + CorrectXAxisTicks(); + CorrectYAxisTicks(); + } + void CorrectXAxisTicks(); + void CorrectYAxisTicks(); + // Find the correct dc coords for the tick marks and label strings, internal use + void CalcTickPositions() + { + CalcXAxisTickPositions(); + CalcYAxisTickPositions(); + } + virtual void CalcXAxisTickPositions(); + virtual void CalcYAxisTickPositions(); + + // ------------------------------------------------------------------------ + // Utilities + // ------------------------------------------------------------------------ + + // Find a curve at pt, in rect of size +- dxdyPt, starting with active curve + // return sucess, setting curve_index, data_index if data curve, and if + // curvePt fills the exact point in the curve. + bool FindCurve(const wxPoint2DDouble &pt, const wxPoint2DDouble &dxdyPt, int &curve_index, + int &data_index, wxPoint2DDouble *curvePt = NULL) const; + + // if n is !finite send wxEVT_PLOT_ERROR if msg is not empty + bool IsFinite(double n, const wxString &msg = wxEmptyString) const; + + // call this whenever you adjust the size of a data curve + // this necessary to know the default zoom to show them + void CalcBoundingPlotRect(); + + // Client (pixels) to/from plot (double) coords + inline double GetPlotCoordFromClientX(int clientx) const + { + return (clientx / m_zoom.m_x + m_viewRect.GetLeft()); + } + inline double GetPlotCoordFromClientY(int clienty) const + { + return ((m_areaClientRect.height - clienty) / m_zoom.m_y + m_viewRect.GetTop()); + } + inline wxRect2DDouble GetPlotRectFromClientRect(const wxRect &clientRect) const + { + return wxRect2DDouble(GetPlotCoordFromClientX(clientRect.x), + GetPlotCoordFromClientY(clientRect.GetBottom()), + clientRect.width / m_zoom.m_x, clientRect.height / m_zoom.m_y); + } + + inline int GetClientCoordFromPlotX(double plotx) const + { + double x = m_zoom.m_x * (plotx - m_viewRect.GetLeft()) + 0.5; + return x < INT_MAX ? int(x) : INT_MAX; + } + inline int GetClientCoordFromPlotY(double ploty) const + { + double y = m_areaClientRect.height - m_zoom.m_y * (ploty - m_viewRect.GetTop()) + 0.5; + return y < INT_MAX ? int(y) : INT_MAX; + } + inline wxRect GetClientRectFromPlotRect(const wxRect2DDouble &plotRect) const + { + double w = plotRect.m_width * m_zoom.m_x + 0.5; + double h = plotRect.m_height * m_zoom.m_y + 0.5; + return wxRect(GetClientCoordFromPlotX(plotRect.m_x), + GetClientCoordFromPlotY(plotRect.GetBottom()), w < INT_MAX ? int(w) : INT_MAX, + h < INT_MAX ? int(h) : INT_MAX); + } + + // IDs for the children windows + enum { + ID_PLOTCTRL_X_AXIS = 100, + ID_PLOTCTRL_Y_AXIS, + ID_PLOTCTRL_AREA, + ID_PLOTCTRL_X_SCROLLBAR, + ID_PLOTCTRL_Y_SCROLLBAR + }; + + // Get the windows + wxPlotArea *GetPlotArea() const { return m_area; } + wxPlotAxis *GetPlotXAxis() const { return m_xAxis; } + wxPlotAxis *GetPlotYAxis() const { return m_yAxis; } + + // internal use size adjustment + void AdjustScrollBars(); + void UpdateWindowSize(); + void DoSize(const wxRect &boundingRect = wxRect(0, 0, 0, 0)); + + // who's got the focus, if this then draw the bitmap to show it, internal + bool CheckFocus(); + + // send event returning true if it's allowed + bool DoSendEvent(wxPlotEvent &event) const; + + // Start the mouse timer with the win_id, stops old if for different id + enum mouseTimerIDs { ID_AREA_TIMER = 10, ID_XAXIS_TIMER, ID_YAXIS_TIMER }; + void StartMouseTimer(wxWindowID win_id); + void StopMouseTimer(); + bool IsTimerRunning(); + void OnTimer(wxTimerEvent &event); + + // A locker for the captured window, set to NULL to release + void SetCaptureWindow(wxWindow *win); + wxWindow *GetCaptureWindow() const { return m_winCapture; } protected: - void OnSize( wxSizeEvent& event ); - - wxArrayPlotCurve m_curves; // all the curves - wxPlotCurve* m_activeCurve; // currently active curve - int m_active_index; // index in array of currently active curve - - wxPlotMarker m_cursorMarker; // marker to draw for cursor - int m_cursor_curve; // index into plot curve array - int m_cursor_index; // if data curve, index in curve - - wxArrayRangeIntSelection m_dataSelections; // for wxPlotData - wxArrayRangeDoubleSelection m_curveSelections; // for wxPlotCurve, wxPlotFunction - int m_selection_type; - - wxArrayPlotMarker m_plotMarkers; // extra markers to draw - - bool m_show_key; // show the key - wxString m_keyString; // the key string - - // title and label - bool m_show_title; - wxString m_title; - bool m_show_xlabel, m_show_ylabel; - wxString m_xLabel, m_yLabel; - wxRect m_titleRect, m_xLabelRect, m_yLabelRect; - - // fonts and colours - wxFont m_titleFont; - wxColour m_titleColour; - wxColour m_borderColour; - - // option variables - bool m_scroll_on_thumb_release; - bool m_crosshair_cursor; - bool m_draw_symbols; - bool m_draw_lines; - bool m_draw_spline; - bool m_draw_grid; - bool m_fit_on_new_curve; - bool m_show_xAxis; - bool m_show_yAxis; - - // rects of the positions of each window - remember for DrawPlotCtrl - wxRect m_xAxisRect, m_yAxisRect, m_areaRect, m_clientRect; - - // zooms - wxPoint2DDouble m_zoom; - wxArrayRect2DDouble m_historyViews; - int m_history_views_index; - void AddHistoryView(); // maintains small list of views - - bool m_fix_aspectratio; - double m_aspectratio; - - // bounding rect, (GetLeft,GetTop) is lower left in screen coords - wxRect2DDouble m_viewRect; // part of the plot currently displayed - wxRect2DDouble m_curveBoundingRect; // total extent of the plot - CalcBoundingPlotRect - wxRect2DDouble m_defaultPlotRect; // default extent of the plot, fallback - wxRect m_areaClientRect; // rect of (wxPoint(0,0), PlotArea.GetClientSize()) - - wxArrayInt m_xAxisTicks, m_yAxisTicks; // pixel coordinates of the tic marks - wxArrayString m_xAxisTickLabels, m_yAxisTickLabels; // the tick labels - wxString m_xAxisTickFormat, m_yAxisTickFormat; // format %lg for example - double m_xAxisTick_step, m_yAxisTick_step; // step size between ticks - int m_xAxisTick_count, m_yAxisTick_count; // how many ticks fit? - bool m_correct_ticks; // tick correction - - // drawers - wxPlotDrawerArea *m_areaDrawer; - wxPlotDrawerXAxis *m_xAxisDrawer; - wxPlotDrawerYAxis *m_yAxisDrawer; - wxPlotDrawerKey *m_keyDrawer; - wxPlotDrawerCurve *m_curveDrawer; - wxPlotDrawerDataCurve *m_dataCurveDrawer; - wxPlotDrawerMarker *m_markerDrawer; - - // windows - wxPlotArea *m_area; - wxPlotAxis *m_xAxis, *m_yAxis; - wxScrollBar *m_xAxisScrollbar, *m_yAxisScrollbar; - - // textctrl for label/title editor, created and deleted as necessary - wxTextCtrl *m_textCtrl; - - // focusing and bitmap to display focus - wxBitmap *m_activeBitmap, *m_inactiveBitmap; - bool m_focused; - bool m_greedy_focus; - - // remember what needs to be repainted so unnecessary EVT_PAINTS are skipped - int m_redraw_type; - int m_batch_count; - - wxSize m_axisFontSize; // pixel size of the number '5' for axis font - int m_y_axis_text_width; // size of "-5e+005" for max y axis width - int m_area_border_width; // width of area border pen (default 1) - int m_border; // width of border between labels and axes - long m_min_exponential; // minimum number displayed as an exponential - double m_pen_print_width; // width of a 1 pixel pen in mm when printed - - wxTimer *m_timer; // don't use, see accessor functions - wxWindow *m_winCapture; // don't use, see accessor functions - - wxPlotMouse_Type m_area_mouse_func; - wxPlotMarker_Type m_area_mouse_marker; - wxStockCursor m_area_mouse_cursorid; - - void SetPlotWinMouseCursor(wxStockCursor cursorid); - wxStockCursor m_mouse_cursorid; + void OnSize(wxSizeEvent &event); + + wxArrayPlotCurve m_curves; // all the curves + wxPlotCurve *m_activeCurve; // currently active curve + int m_active_index; // index in array of currently active curve + + wxPlotMarker m_cursorMarker; // marker to draw for cursor + int m_cursor_curve; // index into plot curve array + int m_cursor_index; // if data curve, index in curve + + wxArrayRangeIntSelection m_dataSelections; // for wxPlotData + wxArrayRangeDoubleSelection m_curveSelections; // for wxPlotCurve, wxPlotFunction + int m_selection_type; + + wxArrayPlotMarker m_plotMarkers; // extra markers to draw + + bool m_show_key; // show the key + wxString m_keyString; // the key string + + // title and label + bool m_show_title; + wxString m_title; + bool m_show_xlabel, m_show_ylabel; + wxString m_xLabel, m_yLabel; + wxRect m_titleRect, m_xLabelRect, m_yLabelRect; + + // fonts and colours + wxFont m_titleFont; + wxColour m_titleColour; + wxColour m_borderColour; + + // option variables + bool m_scroll_on_thumb_release; + bool m_crosshair_cursor; + bool m_draw_symbols; + bool m_draw_lines; + bool m_draw_spline; + bool m_draw_grid; + bool m_fit_on_new_curve; + bool m_show_xAxis; + bool m_show_yAxis; + + // rects of the positions of each window - remember for DrawPlotCtrl + wxRect m_xAxisRect, m_yAxisRect, m_areaRect, m_clientRect; + + // zooms + wxPoint2DDouble m_zoom; + wxArrayRect2DDouble m_historyViews; + int m_history_views_index; + void AddHistoryView(); // maintains small list of views + + bool m_fix_aspectratio; + double m_aspectratio; + + // bounding rect, (GetLeft,GetTop) is lower left in screen coords + wxRect2DDouble m_viewRect; // part of the plot currently displayed + wxRect2DDouble m_curveBoundingRect; // total extent of the plot - CalcBoundingPlotRect + wxRect2DDouble m_defaultPlotRect; // default extent of the plot, fallback + wxRect m_areaClientRect; // rect of (wxPoint(0,0), PlotArea.GetClientSize()) + + wxArrayInt m_xAxisTicks, m_yAxisTicks; // pixel coordinates of the tic marks + wxArrayString m_xAxisTickLabels, m_yAxisTickLabels; // the tick labels + wxString m_xAxisTickFormat, m_yAxisTickFormat; // format %lg for example + double m_xAxisTick_step, m_yAxisTick_step; // step size between ticks + int m_xAxisTick_count, m_yAxisTick_count; // how many ticks fit? + bool m_correct_ticks; // tick correction + + // drawers + wxPlotDrawerArea *m_areaDrawer; + wxPlotDrawerXAxis *m_xAxisDrawer; + wxPlotDrawerYAxis *m_yAxisDrawer; + wxPlotDrawerKey *m_keyDrawer; + wxPlotDrawerCurve *m_curveDrawer; + wxPlotDrawerDataCurve *m_dataCurveDrawer; + wxPlotDrawerMarker *m_markerDrawer; + + // windows + wxPlotArea *m_area; + wxPlotAxis *m_xAxis, *m_yAxis; + wxScrollBar *m_xAxisScrollbar, *m_yAxisScrollbar; + + // textctrl for label/title editor, created and deleted as necessary + wxTextCtrl *m_textCtrl; + + // focusing and bitmap to display focus + wxBitmap *m_activeBitmap, *m_inactiveBitmap; + bool m_focused; + bool m_greedy_focus; + + // remember what needs to be repainted so unnecessary EVT_PAINTS are skipped + int m_redraw_type; + int m_batch_count; + + wxSize m_axisFontSize; // pixel size of the number '5' for axis font + int m_y_axis_text_width; // size of "-5e+005" for max y axis width + int m_area_border_width; // width of area border pen (default 1) + int m_border; // width of border between labels and axes + long m_min_exponential; // minimum number displayed as an exponential + double m_pen_print_width; // width of a 1 pixel pen in mm when printed + + wxTimer *m_timer; // don't use, see accessor functions + wxWindow *m_winCapture; // don't use, see accessor functions + + wxPlotMouse_Type m_area_mouse_func; + wxPlotMarker_Type m_area_mouse_marker; + wxStockCursor m_area_mouse_cursorid; + + void SetPlotWinMouseCursor(wxStockCursor cursorid); + wxStockCursor m_mouse_cursorid; private: - void Init(); - DECLARE_ABSTRACT_CLASS(wxPlotCtrl) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_ABSTRACT_CLASS(wxPlotCtrl) + DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // wxPlotEvent //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotEvent : public wxNotifyEvent -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotEvent : public wxNotifyEvent { public: - wxPlotEvent(wxEventType commandType = wxEVT_NULL, int id = wxID_ANY, - wxPlotCtrl *window = NULL); + wxPlotEvent(wxEventType commandType = wxEVT_NULL, int id = wxID_ANY, wxPlotCtrl *window = NULL); - wxPlotEvent(const wxPlotEvent &event) : wxNotifyEvent(event), - m_curve(event.m_curve), m_curveIndex(event.m_curveIndex), - m_curveData_index(event.m_curveData_index), m_x(event.m_x), m_y(event.m_y) {} + wxPlotEvent(const wxPlotEvent &event) + : wxNotifyEvent(event), m_curve(event.m_curve), m_curveIndex(event.m_curveIndex), + m_curveData_index(event.m_curveData_index), m_x(event.m_x), m_y(event.m_y) + { + } - // position of the mouse cursor, double click, single point selection or 1st selected point - double GetX() const { return m_x; } - double GetY() const { return m_y; } - void SetPosition( double x, double y ) { m_x = x; m_y = y; } + // position of the mouse cursor, double click, single point selection or 1st selected point + double GetX() const { return m_x; } + double GetY() const { return m_y; } + void SetPosition(double x, double y) + { + m_x = x; + m_y = y; + } - int GetCurveDataIndex() const { return m_curveData_index; } - void SetCurveDataIndex(int data_index) { m_curveData_index = data_index; } + int GetCurveDataIndex() const { return m_curveData_index; } + void SetCurveDataIndex(int data_index) { m_curveData_index = data_index; } - // pointer to the curve, NULL if not appropriate for the event type - wxPlotCurve *GetCurve() const { return m_curve; } - void SetCurve(wxPlotCurve *curve, int curve_index) - { m_curve = curve; m_curveIndex = curve_index; } + // pointer to the curve, NULL if not appropriate for the event type + wxPlotCurve *GetCurve() const { return m_curve; } + void SetCurve(wxPlotCurve *curve, int curve_index) + { + m_curve = curve; + m_curveIndex = curve_index; + } - // index of the curve in wxPlotCtrl::GetCurve(index) - int GetCurveIndex() const { return m_curveIndex; } - void SetCurveIndex( int curve_index ) { m_curveIndex = curve_index; } + // index of the curve in wxPlotCtrl::GetCurve(index) + int GetCurveIndex() const { return m_curveIndex; } + void SetCurveIndex(int curve_index) { m_curveIndex = curve_index; } - bool IsDataCurve() const { return wxDynamicCast(m_curve, wxPlotData) != NULL; } + bool IsDataCurve() const { return wxDynamicCast(m_curve, wxPlotData) != NULL; } - wxPlotCtrl *GetPlotCtrl() const - { return wxDynamicCast(GetEventObject(),wxPlotCtrl); } + wxPlotCtrl *GetPlotCtrl() const { return wxDynamicCast(GetEventObject(), wxPlotCtrl); } - int GetMouseFunction() const { return m_commandInt; } - void SetMouseFunction(int func) { m_commandInt = func; } + int GetMouseFunction() const { return m_commandInt; } + void SetMouseFunction(int func) { m_commandInt = func; } - // implementation - virtual wxEvent *Clone() const { return new wxPlotEvent(*this); } + // implementation + virtual wxEvent *Clone() const { return new wxPlotEvent(*this); } - wxPlotCurve *m_curve; - int m_curveIndex; - int m_curveData_index; - double m_x, m_y; + wxPlotCurve *m_curve; + int m_curveIndex; + int m_curveData_index; + double m_x, m_y; private: - DECLARE_ABSTRACT_CLASS(wxPlotEvent); + DECLARE_ABSTRACT_CLASS(wxPlotEvent); }; //----------------------------------------------------------------------------- // wxPlotEvent //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotSelectionEvent : public wxPlotEvent -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotSelectionEvent : public wxPlotEvent { public: - wxPlotSelectionEvent(wxEventType commandType = wxEVT_NULL, int id = wxID_ANY, - wxPlotCtrl *window = NULL); - - wxPlotSelectionEvent(const wxPlotSelectionEvent &event) : wxPlotEvent(event), - m_dataRange(event.m_dataRange), - m_curveRange(event.m_curveRange), - m_dataSelection(event.m_dataSelection), - m_selecting(event.m_selecting) {} - - // for SELection events the range specifies the new (de)selection range - // note : for unordered data sets an event is only sent after all selections are made - - // the data selection range is used for wxPlotData curves these are the indexes - // for wxPlotCurves and wxPlotFunctions these are the pixel locations - wxRangeInt GetDataSelectionRange() const { return m_dataRange; } - void SetDataSelectionRange( const wxRangeInt &range, bool selecting ) - { m_dataRange = range; m_selecting = selecting; } - - // the curve selection range is the double valued start and stop position of the selection - wxRangeDouble GetCurveSelectionRange() const { return m_curveRange; } - void SetCurveSelectionRange( const wxRangeDouble &range, bool selecting ) - { m_curveRange = range; m_selecting = selecting; } - - // for a wxPlotData this is filled with the (de)selected ranges. - // there will only be more than one for unordered wxPlotDatas - wxRangeIntSelection GetDataSelections() const { return m_dataSelection; } - void SetDataSelections(const wxRangeIntSelection &ranges) { m_dataSelection = ranges; } - - // range is selected as opposed to being deselected - bool IsSelecting() const { return m_selecting; } - - // implementation - virtual wxEvent *Clone() const { return new wxPlotSelectionEvent(*this); } - - wxRangeInt m_dataRange; - wxRangeDouble m_curveRange; - wxRangeIntSelection m_dataSelection; - bool m_selecting; + wxPlotSelectionEvent(wxEventType commandType = wxEVT_NULL, int id = wxID_ANY, + wxPlotCtrl *window = NULL); + + wxPlotSelectionEvent(const wxPlotSelectionEvent &event) + : wxPlotEvent(event), m_dataRange(event.m_dataRange), m_curveRange(event.m_curveRange), + m_dataSelection(event.m_dataSelection), m_selecting(event.m_selecting) + { + } + + // for SELection events the range specifies the new (de)selection range + // note : for unordered data sets an event is only sent after all selections are made + + // the data selection range is used for wxPlotData curves these are the indexes + // for wxPlotCurves and wxPlotFunctions these are the pixel locations + wxRangeInt GetDataSelectionRange() const { return m_dataRange; } + void SetDataSelectionRange(const wxRangeInt &range, bool selecting) + { + m_dataRange = range; + m_selecting = selecting; + } + + // the curve selection range is the double valued start and stop position of the selection + wxRangeDouble GetCurveSelectionRange() const { return m_curveRange; } + void SetCurveSelectionRange(const wxRangeDouble &range, bool selecting) + { + m_curveRange = range; + m_selecting = selecting; + } + + // for a wxPlotData this is filled with the (de)selected ranges. + // there will only be more than one for unordered wxPlotDatas + wxRangeIntSelection GetDataSelections() const { return m_dataSelection; } + void SetDataSelections(const wxRangeIntSelection &ranges) { m_dataSelection = ranges; } + + // range is selected as opposed to being deselected + bool IsSelecting() const { return m_selecting; } + + // implementation + virtual wxEvent *Clone() const { return new wxPlotSelectionEvent(*this); } + + wxRangeInt m_dataRange; + wxRangeDouble m_curveRange; + wxRangeIntSelection m_dataSelection; + bool m_selecting; private: - DECLARE_ABSTRACT_CLASS(wxPlotSelectionEvent); + DECLARE_ABSTRACT_CLASS(wxPlotSelectionEvent); }; // ---------------------------------------------------------------------------- @@ -1079,49 +1176,73 @@ class WXDLLIMPEXP_PLOTCTRL wxPlotSelectionEvent : public wxPlotEvent BEGIN_DECLARE_EVENT_TYPES() // wxPlotEvent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_ADD_CURVE, 0) // a curve has been added -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DELETING_CURVE, 0) // a curve is about to be deleted, event.Skip(false) to prevent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DELETED_CURVE, 0) // a curve has been deleted - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURVE_SEL_CHANGING, 0) // curve selection changing, event.Skip(false) to prevent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURVE_SEL_CHANGED, 0) // curve selection has changed - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_MOTION, 0) // mouse moved -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CLICKED, 0) // mouse left or right clicked -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DOUBLECLICKED, 0) // mouse left or right doubleclicked -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_POINT_CLICKED, 0) // clicked on a plot point (+-2pixels) -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_POINT_DOUBLECLICKED,0) // dclicked on a plot point (+-2pixels) - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CREATING, 0) // mouse left down and drag begin -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CHANGING, 0) // mouse left down and dragging -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CREATED, 0) // mouse left down and drag end - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VIEW_CHANGING, 0) // zoom or origin of plotctrl is about to change -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VIEW_CHANGED, 0) // zoom or origin of plotctrl has changed - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURSOR_CHANGING, 0) // cursor point/curve is about to change, event.Skip(false) to prevent - // if the cursor is invalidated since - // the curve is gone you cannot prevent it -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURSOR_CHANGED, 0) // cursor point/curve changed - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_ERROR, 0) // an error has occured, see event.GetString() - // usually nonfatal NaN overflow errors - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_TITLE_EDIT, 0) // title is about to be edited, event.Skip(false) to prevent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_TITLE_EDIT, 0) // title has been edited and changed, event.Skip(false) to prevent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_X_LABEL_EDIT, 0) // x label is about to be edited, event.Skip(false) to prevent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_X_LABEL_EDIT, 0) // x label has been edited and changed, event.Skip(false) to prevent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, 0) // y label is about to be edited, event.Skip(false) to prevent -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_Y_LABEL_EDIT, 0) // y label has been edited and changed, event.Skip(false) to prevent - -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_FUNC_CHANGING,0) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_ADD_CURVE, + 0) // a curve has been added +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DELETING_CURVE, + 0) // a curve is about to be deleted, event.Skip(false) to prevent +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DELETED_CURVE, + 0) // a curve has been deleted + +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURVE_SEL_CHANGING, + 0) // curve selection changing, event.Skip(false) to prevent +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURVE_SEL_CHANGED, + 0) // curve selection has changed + +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_MOTION, 0) // mouse moved +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CLICKED, + 0) // mouse left or right clicked +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_DOUBLECLICKED, + 0) // mouse left or right doubleclicked +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_POINT_CLICKED, + 0) // clicked on a plot point (+-2pixels) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_POINT_DOUBLECLICKED, + 0) // dclicked on a plot point (+-2pixels) + +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CREATING, + 0) // mouse left down and drag begin +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CHANGING, + 0) // mouse left down and dragging +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_AREA_SEL_CREATED, + 0) // mouse left down and drag end + +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VIEW_CHANGING, + 0) // zoom or origin of plotctrl is about to change +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_VIEW_CHANGED, + 0) // zoom or origin of plotctrl has changed + +DECLARE_EXPORTED_EVENT_TYPE( + WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURSOR_CHANGING, + 0) // cursor point/curve is about to change, event.Skip(false) to prevent + // if the cursor is invalidated since + // the curve is gone you cannot prevent it +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_CURSOR_CHANGED, + 0) // cursor point/curve changed + +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_ERROR, + 0) // an error has occured, see event.GetString() + // usually nonfatal NaN overflow errors + +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_TITLE_EDIT, + 0) // title is about to be edited, event.Skip(false) to prevent +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_TITLE_EDIT, + 0) // title has been edited and changed, event.Skip(false) to prevent +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_X_LABEL_EDIT, + 0) // x label is about to be edited, event.Skip(false) to prevent +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_X_LABEL_EDIT, + 0) // x label has been edited and changed, event.Skip(false) to prevent +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, + 0) // y label is about to be edited, event.Skip(false) to prevent +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_END_Y_LABEL_EDIT, + 0) // y label has been edited and changed, event.Skip(false) to prevent + +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_FUNC_CHANGING, 0) DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_MOUSE_FUNC_CHANGED, 0) // wxPlotSelectionEvent -//DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CREATING,0) -//DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CREATED, 0) -//DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CHANGING,0) -DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CHANGED, 0) +// DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CREATING,0) +// DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CREATED, 0) +// DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CHANGING,0) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PLOTCTRL, wxEVT_PLOT_RANGE_SEL_CHANGED, 0) // unused /* @@ -1136,62 +1257,87 @@ END_DECLARE_EVENT_TYPES() // wxPlotEvent macros // ---------------------------------------------------------------------------- -typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&); -#define wxPlotEventHandler(func) \ - (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxPlotEventFunction, &func) -#define wx__DECLARE_PLOTEVT(evt, id, fn) wx__DECLARE_EVT1( evt, id, wxPlotEventHandler(fn)) - -#define EVT_PLOT_ADD_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_ADD_CURVE, id, fn) -#define EVT_PLOT_DELETING_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DELETING_CURVE, id, fn) -#define EVT_PLOT_DELETED_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DELETED_CURVE, id, fn) - -#define EVT_PLOT_CURVE_SEL_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURVE_SEL_CHANGING, id, fn) -#define EVT_PLOT_CURVE_SEL_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURVE_SEL_CHANGED, id, fn) - -#define EVT_PLOT_MOUSE_MOTION(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_MOTION, id, fn) -#define EVT_PLOT_CLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CLICKED, id, fn) -#define EVT_PLOT_DOUBLECLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DOUBLECLICKED, id, fn) -#define EVT_PLOT_POINT_CLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_POINT_CLICKED, id, fn) -#define EVT_PLOT_POINT_DOUBLECLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_POINT_DOUBLECLICKED, id, fn) - -#define EVT_PLOT_AREA_SEL_CREATING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_AREA_SEL_CREATING, id, fn) -#define EVT_PLOT_AREA_SEL_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_AREA_SEL_CHANGING, id, fn) -#define EVT_PLOT_AREA_SEL_CREATED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CREATED, id, fn) - -#define EVT_PLOT_VIEW_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CHANGING, id, fn) -#define EVT_PLOT_VIEW_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CHANGED, id, fn) - -#define EVT_PLOT_CURSOR_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURSOR_CHANGING, id, fn) -#define EVT_PLOT_CURSOR_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURSOR_CHANGED, id, fn) - -#define EVT_PLOT_ERROR(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_ERROR, id, fn) - -#define EVT_PLOT_BEGIN_TITLE_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_TITLE_EDIT, id, fn) -#define EVT_PLOT_END_TITLE_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_TITLE_EDIT, id, fn) -#define EVT_PLOT_BEGIN_X_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_X_LABEL_EDIT, id, fn) -#define EVT_PLOT_END_X_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_X_LABEL_EDIT, id, fn) -#define EVT_PLOT_BEGIN_Y_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, id, fn) -#define EVT_PLOT_END_Y_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_Y_LABEL_EDIT, id, fn) - -#define EVT_PLOT_MOUSE_FUNC_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_FUNC_CHANGING, id, fn) -#define EVT_PLOT_MOUSE_FUNC_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_FUNC_CHANGED, id, fn) - -typedef void (wxEvtHandler::*wxPlotSelectionEventFunction)(wxPlotSelectionEvent&); -#define wxPlotSelectionEventHandler(func) \ - (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxPlotSelectionEventFunction, &func) -#define wx__DECLARE_PLOTSELECTIONEVT(evt, id, fn) wx__DECLARE_EVT1( evt, id, wxPlotSelectionEventHandler(fn)) - -//#define EVT_PLOT_RANGE_SEL_CREATING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CREATING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), -//#define EVT_PLOT_RANGE_SEL_CREATED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CREATED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), -//#define EVT_PLOT_RANGE_SEL_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), -#define EVT_PLOT_RANGE_SEL_CHANGED(id, fn) wx__DECLARE_PLOTSELECTIONEVT(wxEVT_PLOT_RANGE_SEL_CHANGED, id, fn) +typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent &); +#define wxPlotEventHandler(func) \ + (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent(wxPlotEventFunction, &func) +#define wx__DECLARE_PLOTEVT(evt, id, fn) wx__DECLARE_EVT1(evt, id, wxPlotEventHandler(fn)) + +#define EVT_PLOT_ADD_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_ADD_CURVE, id, fn) +#define EVT_PLOT_DELETING_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DELETING_CURVE, id, fn) +#define EVT_PLOT_DELETED_CURVE(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DELETED_CURVE, id, fn) + +#define EVT_PLOT_CURVE_SEL_CHANGING(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURVE_SEL_CHANGING, id, fn) +#define EVT_PLOT_CURVE_SEL_CHANGED(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURVE_SEL_CHANGED, id, fn) + +#define EVT_PLOT_MOUSE_MOTION(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_MOTION, id, fn) +#define EVT_PLOT_CLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CLICKED, id, fn) +#define EVT_PLOT_DOUBLECLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_DOUBLECLICKED, id, fn) +#define EVT_PLOT_POINT_CLICKED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_POINT_CLICKED, id, fn) +#define EVT_PLOT_POINT_DOUBLECLICKED(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_POINT_DOUBLECLICKED, id, fn) + +#define EVT_PLOT_AREA_SEL_CREATING(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_AREA_SEL_CREATING, id, fn) +#define EVT_PLOT_AREA_SEL_CHANGING(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_AREA_SEL_CHANGING, id, fn) +#define EVT_PLOT_AREA_SEL_CREATED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CREATED, id, fn) + +#define EVT_PLOT_VIEW_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CHANGING, id, fn) +#define EVT_PLOT_VIEW_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_VIEW_CHANGED, id, fn) + +#define EVT_PLOT_CURSOR_CHANGING(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURSOR_CHANGING, id, fn) +#define EVT_PLOT_CURSOR_CHANGED(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_CURSOR_CHANGED, id, fn) + +#define EVT_PLOT_ERROR(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_ERROR, id, fn) + +#define EVT_PLOT_BEGIN_TITLE_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_TITLE_EDIT, id, fn) +#define EVT_PLOT_END_TITLE_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_TITLE_EDIT, id, fn) +#define EVT_PLOT_BEGIN_X_LABEL_EDIT(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_X_LABEL_EDIT, id, fn) +#define EVT_PLOT_END_X_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_X_LABEL_EDIT, id, fn) +#define EVT_PLOT_BEGIN_Y_LABEL_EDIT(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, id, fn) +#define EVT_PLOT_END_Y_LABEL_EDIT(id, fn) wx__DECLARE_PLOTEVT(wxEVT_PLOT_END_Y_LABEL_EDIT, id, fn) + +#define EVT_PLOT_MOUSE_FUNC_CHANGING(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_FUNC_CHANGING, id, fn) +#define EVT_PLOT_MOUSE_FUNC_CHANGED(id, fn) \ + wx__DECLARE_PLOTEVT(wxEVT_PLOT_MOUSE_FUNC_CHANGED, id, fn) + +typedef void (wxEvtHandler::*wxPlotSelectionEventFunction)(wxPlotSelectionEvent &); +#define wxPlotSelectionEventHandler(func) \ + (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent(wxPlotSelectionEventFunction, &func) +#define wx__DECLARE_PLOTSELECTIONEVT(evt, id, fn) \ + wx__DECLARE_EVT1(evt, id, wxPlotSelectionEventHandler(fn)) + +// #define EVT_PLOT_RANGE_SEL_CREATING(id, fn) +// DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CREATING, id, wxID_ANY, (wxObjectEventFunction) +// (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), +// #define EVT_PLOT_RANGE_SEL_CREATED(id, fn) +// DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CREATED, id, wxID_ANY, (wxObjectEventFunction) +// (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), +// #define EVT_PLOT_RANGE_SEL_CHANGING(id, fn) +// DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_RANGE_SEL_CHANGING, id, wxID_ANY, (wxObjectEventFunction) +// (wxEventFunction) wxStaticCastEvent( wxPlotSelectionEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PLOT_RANGE_SEL_CHANGED(id, fn) \ + wx__DECLARE_PLOTSELECTIONEVT(wxEVT_PLOT_RANGE_SEL_CHANGED, id, fn) /* -#define EVT_PLOT_VALUE_SEL_CREATING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CREATING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), -#define EVT_PLOT_VALUE_SEL_CREATED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CREATED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), -#define EVT_PLOT_VALUE_SEL_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), -#define EVT_PLOT_VALUE_SEL_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), -#define EVT_PLOT_AREA_SEL_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_AREA_SEL_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PLOT_VALUE_SEL_CREATING(id, fn) +DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CREATING, id, wxID_ANY, (wxObjectEventFunction) +(wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), #define +EVT_PLOT_VALUE_SEL_CREATED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CREATED, id, +wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), +(wxObject *) NULL ), #define EVT_PLOT_VALUE_SEL_CHANGING(id, fn) +DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CHANGING, id, wxID_ANY, (wxObjectEventFunction) +(wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), #define +EVT_PLOT_VALUE_SEL_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_VALUE_SEL_CHANGED, id, +wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), +(wxObject *) NULL ), #define EVT_PLOT_AREA_SEL_CHANGED(id, fn) +DECLARE_EVENT_TABLE_ENTRY(wxEVT_PLOT_AREA_SEL_CHANGED, id, wxID_ANY, (wxObjectEventFunction) +(wxEventFunction) wxStaticCastEvent( wxPlotEventFunction, & fn ), (wxObject *) NULL ), */ #endif // _WX_PLOTCTRL_H_ diff --git a/src/labenski/include/wx/plotctrl/plotcurv.h b/src/labenski/include/wx/plotctrl/plotcurv.h index 997011e8f..d255ee030 100644 --- a/src/labenski/include/wx/plotctrl/plotcurv.h +++ b/src/labenski/include/wx/plotctrl/plotcurv.h @@ -18,28 +18,24 @@ #include "wx/wxthings/genergdi.h" #include "wx/plotctrl/plotdefs.h" -#ifdef GetYValue // Visual Studio 7 defines this - #undef GetYValue +#ifdef GetYValue // Visual Studio 7 defines this +#undef GetYValue #endif //----------------------------------------------------------------------------- // Utility functions //----------------------------------------------------------------------------- // Find y at point x along the line from (x0,y0)-(x1,y1), x0 must != x1 -extern double LinearInterpolateY( double x0, double y0, - double x1, double y1, - double x ); +extern double LinearInterpolateY(double x0, double y0, double x1, double y1, double x); // Find x at point y along the line from (x0,y0)-(x1,y1), y0 must != y1 -extern double LinearInterpolateX( double x0, double y0, - double x1, double y1, - double y ); +extern double LinearInterpolateX(double x0, double y0, double x1, double y1, double y); //---------------------------------------------------------------------------- // Constants //---------------------------------------------------------------------------- // defines wxArrayDouble for use as necessary -#if !wxCHECK_VERSION(2,7,0) +#if !wxCHECK_VERSION(2, 7, 0) WX_DEFINE_USER_EXPORTED_ARRAY_DOUBLE(double, wxArrayDouble, class WXDLLIMPEXP_PLOTCTRL); #endif @@ -50,32 +46,25 @@ extern wxBitmap wxPlotSymbolNormal; extern wxBitmap wxPlotSymbolActive; extern wxBitmap wxPlotSymbolSelected; -enum wxPlotSymbol_Type -{ - wxPLOTSYMBOL_ELLIPSE, - wxPLOTSYMBOL_RECTANGLE, - wxPLOTSYMBOL_CROSS, - wxPLOTSYMBOL_PLUS, - wxPLOTSYMBOL_MAXTYPE +enum wxPlotSymbol_Type { + wxPLOTSYMBOL_ELLIPSE, + wxPLOTSYMBOL_RECTANGLE, + wxPLOTSYMBOL_CROSS, + wxPLOTSYMBOL_PLUS, + wxPLOTSYMBOL_MAXTYPE }; -enum wxPlotPen_Type -{ - wxPLOTPEN_NORMAL, - wxPLOTPEN_ACTIVE, - wxPLOTPEN_SELECTED, - wxPLOTPEN_MAXTYPE -}; +enum wxPlotPen_Type { wxPLOTPEN_NORMAL, wxPLOTPEN_ACTIVE, wxPLOTPEN_SELECTED, wxPLOTPEN_MAXTYPE }; -#define wxPLOTCURVE_OPTION_FILENAME wxT("File.Name") -#define wxPLOTCURVE_OPTION_EOLMODE wxT("EOL.Mode") -#define wxPLOTCURVE_OPTION_MODIFIED wxT("Modified") -#define wxPLOTCURVE_OPTION_HEADER wxT("Header") +#define wxPLOTCURVE_OPTION_FILENAME wxT("File.Name") +#define wxPLOTCURVE_OPTION_EOLMODE wxT("EOL.Mode") +#define wxPLOTCURVE_OPTION_MODIFIED wxT("Modified") +#define wxPLOTCURVE_OPTION_HEADER wxT("Header") #define wxPLOTCURVE_OPTION_DATASEPARATOR wxT("Data.Separator") #define wxPLOTCURVE_DATASEPARATOR_SPACE wxT(" ") #define wxPLOTCURVE_DATASEPARATOR_COMMA wxT(",") -#define wxPLOTCURVE_DATASEPARATOR_TAB wxT("\t") +#define wxPLOTCURVE_DATASEPARATOR_TAB wxT("\t") //---------------------------------------------------------------------------- // wxPlotCurveRefData - the wxObject::m_refData used for wxPlotCurves @@ -85,23 +74,23 @@ enum wxPlotPen_Type // attach arbitrary data to it //---------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotCurveRefData : public wxObjectRefData, public wxClientDataContainer -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotCurveRefData : public wxObjectRefData, + public wxClientDataContainer { public: - wxPlotCurveRefData(); - wxPlotCurveRefData(const wxPlotCurveRefData& data); - virtual ~wxPlotCurveRefData() {} + wxPlotCurveRefData(); + wxPlotCurveRefData(const wxPlotCurveRefData &data); + virtual ~wxPlotCurveRefData() {} - void Copy(const wxPlotCurveRefData &source); + void Copy(const wxPlotCurveRefData &source); - wxRect2DDouble m_boundingRect; // bounds the curve or part to draw - // if width or height <= 0 then no bounds + wxRect2DDouble m_boundingRect; // bounds the curve or part to draw + // if width or height <= 0 then no bounds - wxArrayGenericPen m_pens; - static wxArrayGenericPen sm_defaultPens; + wxArrayGenericPen m_pens; + static wxArrayGenericPen sm_defaultPens; - wxSortedArrayString m_optionNames; - wxArrayString m_optionValues; + wxSortedArrayString m_optionNames; + wxArrayString m_optionValues; }; //----------------------------------------------------------------------------- @@ -109,96 +98,94 @@ class WXDLLIMPEXP_PLOTCTRL wxPlotCurveRefData : public wxObjectRefData, public w // // GetY must be overridden as it "is" the curve //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotCurve: public wxObject -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotCurve : public wxObject { public: - // see the remmed out code in this function if you subclass it - wxPlotCurve(); - virtual ~wxPlotCurve() {} - - // override as necessary so that Ok means that GetY works - virtual bool Ok() const; - - // This *is* the output of the curve y = f(x) - virtual double GetY( double WXUNUSED(x) ) { return 0.0; } - - // Bounding rect used for drawing the curve and... - // if the width or height <= 0 then there's no bounds (or unknown) - // wxPlotCurve/Function : may be unknown and should probably be (0,0,0,0) - // you can limit the extent by setting to a smaller rect - // wxPlotData : calculated from CalcBoundingRect and is well defined - // DON'T call SetBoundingRect unless you know what you're doing - virtual wxRect2DDouble GetBoundingRect() const; - virtual void SetBoundingRect( const wxRect2DDouble &rect ); - - // Get/Set Pens for Normal, Active, Selected drawing - // if these are not set it resorts to the defaults - wxGenericPen GetPen(wxPlotPen_Type colour_type) const; - void SetPen(wxPlotPen_Type colour_type, const wxGenericPen &pen); - - // Get/Set Default Pens for Normal, Active, Selected drawing for all curves - // these are the pens that are used when a wxPlotCurve/Function/Data is created - // default: Normal(0,0,0,1,wxSOLID), Active(0,0,255,1,wxSOLID), Selected(255,0,0,1,wxSOLID) - static wxGenericPen GetDefaultPen(wxPlotPen_Type colour_type); - static void SetDefaultPen(wxPlotPen_Type colour_type, const wxGenericPen &pen); - - //------------------------------------------------------------------------- - // Get/Set Option names/values - //------------------------------------------------------------------------- - - // Get the number of options set - size_t GetOptionCount() const; - // return the index of the option or wxNOT_FOUND (-1) - int HasOption(const wxString& name) const; - // Get the name/value at the index position - wxString GetOptionName( size_t index ) const; - wxString GetOptionValue( size_t index ) const; - // Set an option, if update=true then force it, else only set it if not found - // returns the index of the option - int SetOption(const wxString& name, const wxString& value, bool update=true); - int SetOption(const wxString& name, int option, bool update=true); - // Get an option returns the index if found - // returns wxNOT_FOUND (-1) if it doesn't exist and value isn't changed - int GetOption(const wxString& name, wxString& value) const; - // returns wxEmptyString if not found - wxString GetOption(const wxString& name) const; - // returns 0 if not found - int GetOptionInt(const wxString& name) const; - // get the arrays of option values - wxSortedArrayString GetOptionNames() const; - wxArrayString GetOptionValues() const; - - //------------------------------------------------------------------------- - // Get/Set the ClientData in the ref data - see wxClientDataContainer - // You can store any extra info here. - //------------------------------------------------------------------------- - - void SetClientObject( wxClientData *data ); - wxClientData *GetClientObject() const; - - void SetClientData( void *data ); - void *GetClientData() const; - - //------------------------------------------------------------------------- - // operators - bool operator == (const wxPlotCurve& plotCurve) const - { return m_refData == plotCurve.m_refData; } - bool operator != (const wxPlotCurve& plotCurve) const - { return m_refData != plotCurve.m_refData; } - - wxPlotCurve& operator = (const wxPlotCurve& plotCurve) - { - if ( (*this) != plotCurve ) - Ref(plotCurve); - return *this; + // see the remmed out code in this function if you subclass it + wxPlotCurve(); + virtual ~wxPlotCurve() {} + + // override as necessary so that Ok means that GetY works + virtual bool Ok() const; + + // This *is* the output of the curve y = f(x) + virtual double GetY(double WXUNUSED(x)) { return 0.0; } + + // Bounding rect used for drawing the curve and... + // if the width or height <= 0 then there's no bounds (or unknown) + // wxPlotCurve/Function : may be unknown and should probably be (0,0,0,0) + // you can limit the extent by setting to a smaller rect + // wxPlotData : calculated from CalcBoundingRect and is well defined + // DON'T call SetBoundingRect unless you know what you're doing + virtual wxRect2DDouble GetBoundingRect() const; + virtual void SetBoundingRect(const wxRect2DDouble &rect); + + // Get/Set Pens for Normal, Active, Selected drawing + // if these are not set it resorts to the defaults + wxGenericPen GetPen(wxPlotPen_Type colour_type) const; + void SetPen(wxPlotPen_Type colour_type, const wxGenericPen &pen); + + // Get/Set Default Pens for Normal, Active, Selected drawing for all curves + // these are the pens that are used when a wxPlotCurve/Function/Data is created + // default: Normal(0,0,0,1,wxSOLID), Active(0,0,255,1,wxSOLID), Selected(255,0,0,1,wxSOLID) + static wxGenericPen GetDefaultPen(wxPlotPen_Type colour_type); + static void SetDefaultPen(wxPlotPen_Type colour_type, const wxGenericPen &pen); + + //------------------------------------------------------------------------- + // Get/Set Option names/values + //------------------------------------------------------------------------- + + // Get the number of options set + size_t GetOptionCount() const; + // return the index of the option or wxNOT_FOUND (-1) + int HasOption(const wxString &name) const; + // Get the name/value at the index position + wxString GetOptionName(size_t index) const; + wxString GetOptionValue(size_t index) const; + // Set an option, if update=true then force it, else only set it if not found + // returns the index of the option + int SetOption(const wxString &name, const wxString &value, bool update = true); + int SetOption(const wxString &name, int option, bool update = true); + // Get an option returns the index if found + // returns wxNOT_FOUND (-1) if it doesn't exist and value isn't changed + int GetOption(const wxString &name, wxString &value) const; + // returns wxEmptyString if not found + wxString GetOption(const wxString &name) const; + // returns 0 if not found + int GetOptionInt(const wxString &name) const; + // get the arrays of option values + wxSortedArrayString GetOptionNames() const; + wxArrayString GetOptionValues() const; + + //------------------------------------------------------------------------- + // Get/Set the ClientData in the ref data - see wxClientDataContainer + // You can store any extra info here. + //------------------------------------------------------------------------- + + void SetClientObject(wxClientData *data); + wxClientData *GetClientObject() const; + + void SetClientData(void *data); + void *GetClientData() const; + + //------------------------------------------------------------------------- + // operators + bool operator==(const wxPlotCurve &plotCurve) const { return m_refData == plotCurve.m_refData; } + bool operator!=(const wxPlotCurve &plotCurve) const { return m_refData != plotCurve.m_refData; } + + wxPlotCurve &operator=(const wxPlotCurve &plotCurve) + { + if ((*this) != plotCurve) { + Ref(plotCurve); } + return *this; + } -private : - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; +private: + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxPlotCurve); + DECLARE_DYNAMIC_CLASS(wxPlotCurve); }; #endif // _WX_PLOTCURVE_H_ diff --git a/src/labenski/include/wx/plotctrl/plotdata.h b/src/labenski/include/wx/plotctrl/plotdata.h index de88ecd55..fd914a239 100644 --- a/src/labenski/include/wx/plotctrl/plotdata.h +++ b/src/labenski/include/wx/plotctrl/plotdata.h @@ -11,7 +11,7 @@ #ifndef _WX_PLOTDATA_H_ #define _WX_PLOTDATA_H_ -#include "wx/txtstrm.h" // for wxEOL +#include "wx/txtstrm.h" // for wxEOL #include "wx/plotctrl/plotcurv.h" #include "wx/plotctrl/plotfunc.h" @@ -24,16 +24,16 @@ class WXDLLIMPEXP_THINGS wxRangeIntSelection; // arbitray reasonable max size to avoid malloc errors #define wxPLOTDATA_MAX_SIZE 10000000 -enum wxPlotDataLoad_Type -{ -// store the header, ie. any #comment lines BEFORE the first line w/ valid data -// use Get(Set)Header() to retrieve it - wxPLOTDATA_LOAD_HEADER = 0x0001, -// stop loading datafile if there is a blank line, will continue if a line is merely #commented out -// ignores any blank lines before first line w/ data however - wxPLOTDATA_LOAD_BREAKONBLANKLINE = 0x0010, -// defaults used for loading a data file - wxPLOTDATA_LOAD_DEFAULT = wxPLOTDATA_LOAD_HEADER | wxPLOTDATA_LOAD_BREAKONBLANKLINE +enum wxPlotDataLoad_Type { + // store the header, ie. any #comment lines BEFORE the first line w/ valid data + // use Get(Set)Header() to retrieve it + wxPLOTDATA_LOAD_HEADER = 0x0001, + // stop loading datafile if there is a blank line, will continue if a line is merely #commented + // out + // ignores any blank lines before first line w/ data however + wxPLOTDATA_LOAD_BREAKONBLANKLINE = 0x0010, + // defaults used for loading a data file + wxPLOTDATA_LOAD_DEFAULT = wxPLOTDATA_LOAD_HEADER | wxPLOTDATA_LOAD_BREAKONBLANKLINE }; //----------------------------------------------------------------------------- @@ -45,348 +45,339 @@ enum wxPlotDataLoad_Type // //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotData : public wxPlotCurve -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotData : public wxPlotCurve { public: - wxPlotData() : wxPlotCurve() {} - wxPlotData( const wxPlotData& plotData ):wxPlotCurve() { Create(plotData); } - - wxPlotData( int points, bool zero = true ):wxPlotCurve() { Create(points, zero); } - wxPlotData( double *x_data, double *y_data, int points, bool static_data = false ):wxPlotCurve() - { Create( x_data, y_data, points, static_data ); } - wxPlotData( const wxString &filename, int x_col, int y_col, int options = wxPLOTDATA_LOAD_DEFAULT ):wxPlotCurve() - { LoadFile( filename, x_col, y_col, options ); } - wxPlotData( const wxPlotFunction &plotFunc, double x_start, double dx, int points ):wxPlotCurve() - { Create( plotFunc, x_start, dx, points ); } - - virtual ~wxPlotData() {} - - // Ref the source plotdata - bool Create( const wxPlotData& plotData ); - // Create from a wxPlotFunction - // starting at x-start, with dx increment, for number of points - bool Create( const wxPlotFunction &plotFunc, double x_start, double dx, int points ); - // Allocate memory for given number of points, if zero then init to zeroes - // don't use uninitialized data, trying to plot it will cause problems - bool Create( int points, bool zero = true ); - // Load plotdata from a file, see Loadfile - bool Create( const wxString &filename, int x_col, int y_col, int options = wxPLOTDATA_LOAD_DEFAULT ) - { return LoadFile( filename, x_col, y_col, options ); } - // Assign the malloc(ed) data sets to this plotdata, - // if !static_data they'll be free(ed) on destruction - bool Create( double *x_data, double *y_data, int points, bool static_data = false ); - - // Make true (not refed) copy of this, - // if copy_all = true then copy header, filename, pens, etc - bool Copy( const wxPlotData &source, bool copy_all = false ); - // Only copy the header, filename, pens, etc... from the source - bool CopyExtra( const wxPlotData &source ); - - // Resize the data by appending or cropping points to/from the end - // if zero then zero any added new points - bool Resize( int new_size, bool zero = true ); - // Resize the data by appending or cropping points to/from the end. - // Sets created values with x starting from last point + dx in steps of - // dx with a value of y. - bool Resize( int new_size, double dx, double y ); - - // Append the source curve to the end, Yi data is copied only if both have it. - wxPlotData Append(const wxPlotData &source) const; - // Insert a the source curve at data index, Yi data is copied only if both have it. - wxPlotData Insert(const wxPlotData &source, int index) const; - // Delete a number of points in the curve, if count < 0 then delete to end - // do not delete from 0 to end, it will assert, Destroy the data instead - wxPlotData Remove(int index, int count = -1) const; - // Get a sub-section of this curve from index of size count points. - // if count < 0 then get data from index to end - wxPlotData GetSubPlotData(int index, int count = -1) const; - - // Unref the data - void Destroy(); - - // Is there data, has it been properly constructed? - bool Ok() const; - - // Get the number of points in the data set - int GetCount() const; - - // calc BoundingRect of the data and determine if X is ordered - // ALWAYS call CalcBoundingRect after externally modifying the data, - // especially if reording X quantities and using the wxPlotCtrl - virtual void CalcBoundingRect(); - - // are consecutive x points always > than the previous ones - bool GetIsXOrdered() const; - - //------------------------------------------------------------------------- - // Load/Save, Filename, file header, saving options - //------------------------------------------------------------------------- - - // Load a data file use # for comments and spaces, tabs, commas for column separators - // if x_col or y_col is < 0 then if more than two cols pop-up a dialog to select - // otherwise use col 1 and 2 or if only 1 col then - // fill x with 0,1,2,3... - // if x_col == y_col then fill y_col with data and x_col with 0,1,2,3... - bool LoadFile( const wxString &filename, int x_col = -1, int y_col = -1, - int options = wxPLOTDATA_LOAD_DEFAULT ); - // Save a data file - bool SaveFile( const wxString &filename, bool save_header = false, - const wxString &format=wxT("%g") ); - - // Get/Set the filename was used for LoadFile or a previous SetFilename (if any) - wxString GetFilename() const; - void SetFilename( const wxString &filename ); - // Get/Set the Header that from LoadFile or a previous call to SetHeader (if any) - wxString GetHeader() const; - void SetHeader( const wxString &header ); - // Get/Set the EOL mode from LoadFile or a previous call to SetEOLMode (if any) - wxEOL GetEOLMode() const; - void SetEOLMode( wxEOL eol = wxEOL_NATIVE ); - // Get/Set the column separator to use when loading or saving the data - wxString GetDataColumnSeparator() const; - void SetDataColumnSeparator(const wxString &separator = wxPLOTCURVE_DATASEPARATOR_SPACE); - - //------------------------------------------------------------------------- - // Get/Set data values - //------------------------------------------------------------------------- - - // Get a pointer to the data (call CalcBoundingRect afterwards if changing values) - double *GetXData() const; - double *GetYData() const; - - // imaginary Y data, not normally created, but if !NULL then it will be free()ed, see FFT - double *GetYiData() const; - // use (double*)malloc(sizeof(double)*GetCount()) to create - // it'll be free()ed if the PlotData was NOT Created with existing arrays and static=true - void SetYiData( double *yi_data ); - - // Get the point's value at this data index - double GetXValue( int index ) const; - double GetYValue( int index ) const; - wxPoint2DDouble GetPoint( int index ) const; - // Interpolate if necessary to get the y value at this point, - // doesn't fail just returns ends if out of bounds - double GetY( double x ); - - // Set the point at this data index, don't need to call CalcBoundingRect after - void SetXValue( int index, double x ); - void SetYValue( int index, double y ); - void SetValue(int index, double x, double y); - void SetPoint(int index, const wxPoint2DDouble &pt) { SetValue(index, pt.m_x, pt.m_y); } - - // Set a range of values starting at start_index for count points. - // If count = -1 go to end of data - void SetXValues( int start_index, int count = -1, double x = 0.0 ); - void SetYValues( int start_index, int count = -1, double y = 0.0 ); - - // Set a range of values to be steps starting at x_start with dx increment - // starts at start_index for count points, if count = -1 go to end - void SetXStepValues( int start_index, int count = -1, - double x_start = 0.0, double dx = 1.0 ); - void SetYStepValues( int start_index, int count = -1, - double y_start = 0.0, double dy = 1.0 ); - - enum Index_Type - { - index_round, - index_floor, - index_ceil - }; - - // find the first occurance of an index whose value is closest (index_round), - // or the next lower (index_floor), or next higher (index_ceil), to the given value - // always returns a valid index - int GetIndexFromX( double x, wxPlotData::Index_Type type = index_round ) const; - int GetIndexFromY( double y, wxPlotData::Index_Type type = index_round ) const; - // find the first occurance of an index whose value is closest to x,y - // if x_range != 0 then limit search between +- x_range (useful for x-ordered data) - int GetIndexFromXY( double x, double y, double x_range=0 ) const; - - // Find the average of the data starting at start_index for number of count points - // if count < 0 then to to last point - double GetAverage( int start_index = 0, int count = -1 ) const; - - // Get the minimum, maximum, and average x,y values for the ranges including - // the indexes where the min/maxes occurred. - // returns the number of points used. - int GetMinMaxAve( const wxRangeIntSelection& rangeSel, - wxPoint2DDouble* minXY, wxPoint2DDouble* maxXY, - wxPoint2DDouble* ave, - int *x_min_index, int *x_max_index, - int *y_min_index, int *y_max_index ) const; - - // Returns array of indicies of nearest points where the data crosses the point y - wxArrayInt GetCrossing( double y_value ) const; - - // Get the index of the first point with the min/max index value - // if count == -1 then go to end of dataset - int GetMinYIndex(int start_index = 0, int end_index = -1) const; - int GetMaxYIndex(int start_index = 0, int end_index = -1) const; - - //------------------------------------------------------------------------- - // Data processing functions - //------------------------------------------------------------------------- - - // Add this offset to each data point (data += offset) - void OffsetX( double offset, int start_index = 0, int end_index = -1 ); - void OffsetY( double offset, int start_index = 0, int end_index = -1 ); - void OffsetXY( double offsetX, double offsetY, int start_index = 0, int end_index = -1 ); - - // Scale the data, multiply by scale around offset value (data = (data-offset)*scale+offset) - void ScaleX( double scale, double offset = 0.0, int start_index = 0, int end_index = -1 ); - void ScaleY( double scale, double offset = 0.0, int start_index = 0, int end_index = -1 ); - void ScaleXY( double scaleX, double scaleY, double offsetX = 0.0, double offsetY = 0.0, - int start_index = 0, int end_index = -1 ); - - // Raise the data to the power - void PowerX( double power, int start_index = 0, int end_index = -1 ); - void PowerY( double power, int start_index = 0, int end_index = -1 ); - void PowerXY( double powerX, double powerY, int start_index = 0, int end_index = -1 ); - - enum FuncModify_Type - { - add_x, - add_y, - mult_x, - mult_y, - add_yi, - mult_yi - }; - - wxPlotData Resample( double start_x, double dx, int points ) const; - - // Take the x values of the curve and resample this curve's x values to match - // interpolates if necessary. Only for x ordered curves. - // returns empty plotdata if ranges don't match - wxPlotData Resample( const wxPlotData &source ) const; - - // Take the y-values of the wxPlotFunction curve at this curve's x-values - // add_x adds function's y-values to this curve's x-values - // add_y adds function's y-values to this curve's y-values - // mult_x multiplies function's y-values to this curve's x-values - // mult_y multiplies function's y-values to this curve's y-values - wxPlotData Modify( const wxPlotFunction &func, FuncModify_Type type ) const; - - // Add y values of curves 1 (this) and 2, after multiplying each curve by their factors - // interpolating between points if necessary, but outlying points are ignored - // if factor1,2 are both 1.0 then strictly add them - // if factor1 = -1 and factor2 = 1 then subtract this curve (1) from 2... - wxPlotData Add( const wxPlotData &curve2, double factor1 = 1.0, double factor2 = 1.0 ) const; - - // Runaverage the data using a window of width number of points - // use odd number, it'll make it odd anyway - // points closer then width/2 to ends are not changed - // averaging is performed between start_index for count # points, if count < 0 to end - wxPlotData RunAverage( int width, int start_index=0, int count = -1 ) const; - - // Simple function that does fabs(y) on the data - wxPlotData Abs() const; - - // Linearize the y-points (straight line) from start_index for count points - // x-values are not changed - wxPlotData LinearizeY(int start_index, int count = -1) const; - - // Simple derivitive y_(n+1) - y_(n) - wxPlotData Derivitive() const; - - // Variance = SumOverN(sqrt(E(yn-)^2))/N - double Variance(int start_index = 0, int count = -1) const; - - // returns a curve that is the variance at each point in a window of width - wxPlotData VarianceCurve(int width) const; - - // Deviation = sqrt(E(y-y1)^2), don't divide by max-min+1 since - double Deviation( const wxPlotData &other, int min=0, int max=-1 ) const; - double CrossCorrelation( const wxPlotData &other, int runave=0, int min=0, int max=-1 ) const; - - // Tries to line up these two curves by shifting the other along the x-axis - // it returns the x shift that gives the minimum deviation - double MinShiftX( const wxPlotData &other ) const; - - // Fast Fourier Transform the data, forward = true for forward xform - // note that the data size will be expanded to the smallest 2^n size that contains the data - // the last point is replicated to fill it. - // Since there are typically real and imaginary parts GetYiData() is now valid - wxPlotData FFT( bool forward ); - // Return the power spectrum of the FFT of the data - wxPlotData PowerSpectrum(); - - enum FFTFilter_Type - { - FilterStep, - FilterButterworth, - FilterGaussian, - FilterFermi - }; - - // String representation of the equations of the FFT transform filters - static wxString FFTHiPassFilterFormat( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); - static wxString FFTLoPassFilterFormat( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); - static wxString FFTNotchFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); - static wxString FFTBandPassFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); - - // Use FFT to make either a high or a low pass filter, at fc = cutoff freq - // The cutoff function is of type FFTFilter_Type - // n is unused for FilterStep and FilterGaussian - // the n for FilterButterworth & FilterFermi is typically an int > 1 - // Butterworth filter 1.0/(1.0 + (f/fc)^2n) [n=1,2,3...] - // where at fc the amplitude is 1/2 and n (order) determines the cutoff slope - wxPlotData FFTHiPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); - wxPlotData FFTLoPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n = 5 ); - // Use FFT to make either a Notch filter (remove frequencies between low and high) or - // a Band Pass (allow frequencies between low and high) filter - // the cutoff can either be a step function, - // or follow that of a Butterworth filter 1.0/(1.0 + (f/fc)^2n) [n=1,2,3...] - wxPlotData FFTNotchFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); - wxPlotData FFTBandPassFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5 ); - - // After FFT this curve, apply the filter (mult y points at each x) and transform back - wxPlotData FFTCustomFilter( const wxPlotFunction &func ); - - // Sorts the points by their x-values starting from the min to max - bool SortByX(); - // Sorts the points by their y-values starting from the min to max - bool SortByY(); - - //------------------------------------------------------------------------- - // Get/Set Symbols to use for plotting - CreateSymbol is untested - // note: in MSW drawing bitmaps is sloooow! <-- so I haven't bothered finishing - //------------------------------------------------------------------------- - - // Get the symbol used for marking data points - wxBitmap GetSymbol(wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL) const; - // Set the symbol to some arbitray bitmap, make size odd so it can be centered - void SetSymbol( const wxBitmap &bitmap, wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL ); - // Set the symbol from of the available types, using default colours if pen and brush are NULL - void SetSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL, - int width = 5, int height = 5, - const wxPen *pen = NULL, const wxBrush *brush = NULL); - // Get a copy of the symbol thats created for SetSymbol - wxBitmap CreateSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type=wxPLOTPEN_NORMAL, - int width = 5, int height = 5, - const wxPen *pen = NULL, const wxBrush *brush = NULL); - - //----------------------------------------------------------------------- - // Operators - - bool operator == (const wxPlotData& plotData) const - { return m_refData == plotData.m_refData; } - bool operator != (const wxPlotData& plotData) const - { return m_refData != plotData.m_refData; } - - wxPlotData& operator = (const wxPlotData& plotData) - { - if ( (*this) != plotData ) - Ref(plotData); - return *this; + wxPlotData() : wxPlotCurve() {} + wxPlotData(const wxPlotData &plotData) : wxPlotCurve() { Create(plotData); } + + wxPlotData(int points, bool zero = true) : wxPlotCurve() { Create(points, zero); } + wxPlotData(double *x_data, double *y_data, int points, bool static_data = false) : wxPlotCurve() + { + Create(x_data, y_data, points, static_data); + } + wxPlotData(const wxString &filename, int x_col, int y_col, int options = wxPLOTDATA_LOAD_DEFAULT) + : wxPlotCurve() + { + LoadFile(filename, x_col, y_col, options); + } + wxPlotData(const wxPlotFunction &plotFunc, double x_start, double dx, int points) : wxPlotCurve() + { + Create(plotFunc, x_start, dx, points); + } + + virtual ~wxPlotData() {} + + // Ref the source plotdata + bool Create(const wxPlotData &plotData); + // Create from a wxPlotFunction + // starting at x-start, with dx increment, for number of points + bool Create(const wxPlotFunction &plotFunc, double x_start, double dx, int points); + // Allocate memory for given number of points, if zero then init to zeroes + // don't use uninitialized data, trying to plot it will cause problems + bool Create(int points, bool zero = true); + // Load plotdata from a file, see Loadfile + bool Create(const wxString &filename, int x_col, int y_col, + int options = wxPLOTDATA_LOAD_DEFAULT) + { + return LoadFile(filename, x_col, y_col, options); + } + // Assign the malloc(ed) data sets to this plotdata, + // if !static_data they'll be free(ed) on destruction + bool Create(double *x_data, double *y_data, int points, bool static_data = false); + + // Make true (not refed) copy of this, + // if copy_all = true then copy header, filename, pens, etc + bool Copy(const wxPlotData &source, bool copy_all = false); + // Only copy the header, filename, pens, etc... from the source + bool CopyExtra(const wxPlotData &source); + + // Resize the data by appending or cropping points to/from the end + // if zero then zero any added new points + bool Resize(int new_size, bool zero = true); + // Resize the data by appending or cropping points to/from the end. + // Sets created values with x starting from last point + dx in steps of + // dx with a value of y. + bool Resize(int new_size, double dx, double y); + + // Append the source curve to the end, Yi data is copied only if both have it. + wxPlotData Append(const wxPlotData &source) const; + // Insert a the source curve at data index, Yi data is copied only if both have it. + wxPlotData Insert(const wxPlotData &source, int index) const; + // Delete a number of points in the curve, if count < 0 then delete to end + // do not delete from 0 to end, it will assert, Destroy the data instead + wxPlotData Remove(int index, int count = -1) const; + // Get a sub-section of this curve from index of size count points. + // if count < 0 then get data from index to end + wxPlotData GetSubPlotData(int index, int count = -1) const; + + // Unref the data + void Destroy(); + + // Is there data, has it been properly constructed? + bool Ok() const; + + // Get the number of points in the data set + int GetCount() const; + + // calc BoundingRect of the data and determine if X is ordered + // ALWAYS call CalcBoundingRect after externally modifying the data, + // especially if reording X quantities and using the wxPlotCtrl + virtual void CalcBoundingRect(); + + // are consecutive x points always > than the previous ones + bool GetIsXOrdered() const; + + //------------------------------------------------------------------------- + // Load/Save, Filename, file header, saving options + //------------------------------------------------------------------------- + + // Load a data file use # for comments and spaces, tabs, commas for column separators + // if x_col or y_col is < 0 then if more than two cols pop-up a dialog to select + // otherwise use col 1 and 2 or if only 1 col then + // fill x with 0,1,2,3... + // if x_col == y_col then fill y_col with data and x_col with 0,1,2,3... + bool LoadFile(const wxString &filename, int x_col = -1, int y_col = -1, + int options = wxPLOTDATA_LOAD_DEFAULT); + // Save a data file + bool SaveFile(const wxString &filename, bool save_header = false, + const wxString &format = wxT("%g")); + + // Get/Set the filename was used for LoadFile or a previous SetFilename (if any) + wxString GetFilename() const; + void SetFilename(const wxString &filename); + // Get/Set the Header that from LoadFile or a previous call to SetHeader (if any) + wxString GetHeader() const; + void SetHeader(const wxString &header); + // Get/Set the EOL mode from LoadFile or a previous call to SetEOLMode (if any) + wxEOL GetEOLMode() const; + void SetEOLMode(wxEOL eol = wxEOL_NATIVE); + // Get/Set the column separator to use when loading or saving the data + wxString GetDataColumnSeparator() const; + void SetDataColumnSeparator(const wxString &separator = wxPLOTCURVE_DATASEPARATOR_SPACE); + + //------------------------------------------------------------------------- + // Get/Set data values + //------------------------------------------------------------------------- + + // Get a pointer to the data (call CalcBoundingRect afterwards if changing values) + double *GetXData() const; + double *GetYData() const; + + // imaginary Y data, not normally created, but if !NULL then it will be free()ed, see FFT + double *GetYiData() const; + // use (double*)malloc(sizeof(double)*GetCount()) to create + // it'll be free()ed if the PlotData was NOT Created with existing arrays and static=true + void SetYiData(double *yi_data); + + // Get the point's value at this data index + double GetXValue(int index) const; + double GetYValue(int index) const; + wxPoint2DDouble GetPoint(int index) const; + // Interpolate if necessary to get the y value at this point, + // doesn't fail just returns ends if out of bounds + double GetY(double x); + + // Set the point at this data index, don't need to call CalcBoundingRect after + void SetXValue(int index, double x); + void SetYValue(int index, double y); + void SetValue(int index, double x, double y); + void SetPoint(int index, const wxPoint2DDouble &pt) { SetValue(index, pt.m_x, pt.m_y); } + + // Set a range of values starting at start_index for count points. + // If count = -1 go to end of data + void SetXValues(int start_index, int count = -1, double x = 0.0); + void SetYValues(int start_index, int count = -1, double y = 0.0); + + // Set a range of values to be steps starting at x_start with dx increment + // starts at start_index for count points, if count = -1 go to end + void SetXStepValues(int start_index, int count = -1, double x_start = 0.0, double dx = 1.0); + void SetYStepValues(int start_index, int count = -1, double y_start = 0.0, double dy = 1.0); + + enum Index_Type { index_round, index_floor, index_ceil }; + + // find the first occurance of an index whose value is closest (index_round), + // or the next lower (index_floor), or next higher (index_ceil), to the given value + // always returns a valid index + int GetIndexFromX(double x, wxPlotData::Index_Type type = index_round) const; + int GetIndexFromY(double y, wxPlotData::Index_Type type = index_round) const; + // find the first occurance of an index whose value is closest to x,y + // if x_range != 0 then limit search between +- x_range (useful for x-ordered data) + int GetIndexFromXY(double x, double y, double x_range = 0) const; + + // Find the average of the data starting at start_index for number of count points + // if count < 0 then to to last point + double GetAverage(int start_index = 0, int count = -1) const; + + // Get the minimum, maximum, and average x,y values for the ranges including + // the indexes where the min/maxes occurred. + // returns the number of points used. + int GetMinMaxAve(const wxRangeIntSelection &rangeSel, wxPoint2DDouble *minXY, + wxPoint2DDouble *maxXY, wxPoint2DDouble *ave, int *x_min_index, + int *x_max_index, int *y_min_index, int *y_max_index) const; + + // Returns array of indicies of nearest points where the data crosses the point y + wxArrayInt GetCrossing(double y_value) const; + + // Get the index of the first point with the min/max index value + // if count == -1 then go to end of dataset + int GetMinYIndex(int start_index = 0, int end_index = -1) const; + int GetMaxYIndex(int start_index = 0, int end_index = -1) const; + + //------------------------------------------------------------------------- + // Data processing functions + //------------------------------------------------------------------------- + + // Add this offset to each data point (data += offset) + void OffsetX(double offset, int start_index = 0, int end_index = -1); + void OffsetY(double offset, int start_index = 0, int end_index = -1); + void OffsetXY(double offsetX, double offsetY, int start_index = 0, int end_index = -1); + + // Scale the data, multiply by scale around offset value (data = (data-offset)*scale+offset) + void ScaleX(double scale, double offset = 0.0, int start_index = 0, int end_index = -1); + void ScaleY(double scale, double offset = 0.0, int start_index = 0, int end_index = -1); + void ScaleXY(double scaleX, double scaleY, double offsetX = 0.0, double offsetY = 0.0, + int start_index = 0, int end_index = -1); + + // Raise the data to the power + void PowerX(double power, int start_index = 0, int end_index = -1); + void PowerY(double power, int start_index = 0, int end_index = -1); + void PowerXY(double powerX, double powerY, int start_index = 0, int end_index = -1); + + enum FuncModify_Type { add_x, add_y, mult_x, mult_y, add_yi, mult_yi }; + + wxPlotData Resample(double start_x, double dx, int points) const; + + // Take the x values of the curve and resample this curve's x values to match + // interpolates if necessary. Only for x ordered curves. + // returns empty plotdata if ranges don't match + wxPlotData Resample(const wxPlotData &source) const; + + // Take the y-values of the wxPlotFunction curve at this curve's x-values + // add_x adds function's y-values to this curve's x-values + // add_y adds function's y-values to this curve's y-values + // mult_x multiplies function's y-values to this curve's x-values + // mult_y multiplies function's y-values to this curve's y-values + wxPlotData Modify(const wxPlotFunction &func, FuncModify_Type type) const; + + // Add y values of curves 1 (this) and 2, after multiplying each curve by their factors + // interpolating between points if necessary, but outlying points are ignored + // if factor1,2 are both 1.0 then strictly add them + // if factor1 = -1 and factor2 = 1 then subtract this curve (1) from 2... + wxPlotData Add(const wxPlotData &curve2, double factor1 = 1.0, double factor2 = 1.0) const; + + // Runaverage the data using a window of width number of points + // use odd number, it'll make it odd anyway + // points closer then width/2 to ends are not changed + // averaging is performed between start_index for count # points, if count < 0 to end + wxPlotData RunAverage(int width, int start_index = 0, int count = -1) const; + + // Simple function that does fabs(y) on the data + wxPlotData Abs() const; + + // Linearize the y-points (straight line) from start_index for count points + // x-values are not changed + wxPlotData LinearizeY(int start_index, int count = -1) const; + + // Simple derivitive y_(n+1) - y_(n) + wxPlotData Derivitive() const; + + // Variance = SumOverN(sqrt(E(yn-)^2))/N + double Variance(int start_index = 0, int count = -1) const; + + // returns a curve that is the variance at each point in a window of width + wxPlotData VarianceCurve(int width) const; + + // Deviation = sqrt(E(y-y1)^2), don't divide by max-min+1 since + double Deviation(const wxPlotData &other, int min = 0, int max = -1) const; + double CrossCorrelation(const wxPlotData &other, int runave = 0, int min = 0, + int max = -1) const; + + // Tries to line up these two curves by shifting the other along the x-axis + // it returns the x shift that gives the minimum deviation + double MinShiftX(const wxPlotData &other) const; + + // Fast Fourier Transform the data, forward = true for forward xform + // note that the data size will be expanded to the smallest 2^n size that contains the data + // the last point is replicated to fill it. + // Since there are typically real and imaginary parts GetYiData() is now valid + wxPlotData FFT(bool forward); + // Return the power spectrum of the FFT of the data + wxPlotData PowerSpectrum(); + + enum FFTFilter_Type { FilterStep, FilterButterworth, FilterGaussian, FilterFermi }; + + // String representation of the equations of the FFT transform filters + static wxString FFTHiPassFilterFormat(double fc, wxPlotData::FFTFilter_Type filter, + double n = 5); + static wxString FFTLoPassFilterFormat(double fc, wxPlotData::FFTFilter_Type filter, + double n = 5); + static wxString FFTNotchFilterFormat(double lo, double hi, wxPlotData::FFTFilter_Type filter, + double n = 5); + static wxString FFTBandPassFilterFormat(double lo, double hi, wxPlotData::FFTFilter_Type filter, + double n = 5); + + // Use FFT to make either a high or a low pass filter, at fc = cutoff freq + // The cutoff function is of type FFTFilter_Type + // n is unused for FilterStep and FilterGaussian + // the n for FilterButterworth & FilterFermi is typically an int > 1 + // Butterworth filter 1.0/(1.0 + (f/fc)^2n) [n=1,2,3...] + // where at fc the amplitude is 1/2 and n (order) determines the cutoff slope + wxPlotData FFTHiPassFilter(double fc, wxPlotData::FFTFilter_Type filter, double n = 5); + wxPlotData FFTLoPassFilter(double fc, wxPlotData::FFTFilter_Type filter, double n = 5); + // Use FFT to make either a Notch filter (remove frequencies between low and high) or + // a Band Pass (allow frequencies between low and high) filter + // the cutoff can either be a step function, + // or follow that of a Butterworth filter 1.0/(1.0 + (f/fc)^2n) [n=1,2,3...] + wxPlotData FFTNotchFilter(double lo, double hi, wxPlotData::FFTFilter_Type filter, double n = 5); + wxPlotData FFTBandPassFilter(double lo, double hi, wxPlotData::FFTFilter_Type filter, + double n = 5); + + // After FFT this curve, apply the filter (mult y points at each x) and transform back + wxPlotData FFTCustomFilter(const wxPlotFunction &func); + + // Sorts the points by their x-values starting from the min to max + bool SortByX(); + // Sorts the points by their y-values starting from the min to max + bool SortByY(); + + //------------------------------------------------------------------------- + // Get/Set Symbols to use for plotting - CreateSymbol is untested + // note: in MSW drawing bitmaps is sloooow! <-- so I haven't bothered finishing + //------------------------------------------------------------------------- + + // Get the symbol used for marking data points + wxBitmap GetSymbol(wxPlotPen_Type colour_type = wxPLOTPEN_NORMAL) const; + // Set the symbol to some arbitray bitmap, make size odd so it can be centered + void SetSymbol(const wxBitmap &bitmap, wxPlotPen_Type colour_type = wxPLOTPEN_NORMAL); + // Set the symbol from of the available types, using default colours if pen and brush are NULL + void SetSymbol(wxPlotSymbol_Type type, wxPlotPen_Type colour_type = wxPLOTPEN_NORMAL, + int width = 5, int height = 5, const wxPen *pen = NULL, + const wxBrush *brush = NULL); + // Get a copy of the symbol thats created for SetSymbol + wxBitmap CreateSymbol(wxPlotSymbol_Type type, wxPlotPen_Type colour_type = wxPLOTPEN_NORMAL, + int width = 5, int height = 5, const wxPen *pen = NULL, + const wxBrush *brush = NULL); + + //----------------------------------------------------------------------- + // Operators + + bool operator==(const wxPlotData &plotData) const { return m_refData == plotData.m_refData; } + bool operator!=(const wxPlotData &plotData) const { return m_refData != plotData.m_refData; } + + wxPlotData &operator=(const wxPlotData &plotData) + { + if ((*this) != plotData) { + Ref(plotData); } + return *this; + } private: - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxPlotData) + DECLARE_DYNAMIC_CLASS(wxPlotData) }; // ---------------------------------------------------------------------------- @@ -401,24 +392,23 @@ wxPlotData wxClipboardGetPlotData(); // wxPlotDataObject which is a string containing wxNow. The plotdata is not // actually copied to the clipboard since no other program could use it anyway. // returns sucess -bool wxClipboardSetPlotData(const wxPlotData& plotData); +bool wxClipboardSetPlotData(const wxPlotData &plotData); // ---------------------------------------------------------------------------- // wxPlotDataObject - a wxClipboard object // ---------------------------------------------------------------------------- #include "wx/dataobj.h" -//#define wxDF_wxPlotData (wxDF_MAX+1010) // works w/ GTK 1.2 non unicode -extern const wxChar* wxDF_wxPlotData; // wxT("wxDF_wxPlotData"); +// #define wxDF_wxPlotData (wxDF_MAX+1010) // works w/ GTK 1.2 non unicode +extern const wxChar *wxDF_wxPlotData; // wxT("wxDF_wxPlotData"); -class WXDLLIMPEXP_PLOTCTRL wxPlotDataObject : public wxTextDataObject -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotDataObject : public wxTextDataObject { public: - wxPlotDataObject(); - wxPlotDataObject(const wxPlotData& plotData); + wxPlotDataObject(); + wxPlotDataObject(const wxPlotData &plotData); - wxPlotData GetPlotData() const; - void SetPlotData(const wxPlotData& plotData); + wxPlotData GetPlotData() const; + void SetPlotData(const wxPlotData &plotData); }; #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD diff --git a/src/labenski/include/wx/plotctrl/plotdefs.h b/src/labenski/include/wx/plotctrl/plotdefs.h index 8f520ce09..f8c0cc216 100644 --- a/src/labenski/include/wx/plotctrl/plotdefs.h +++ b/src/labenski/include/wx/plotctrl/plotdefs.h @@ -28,8 +28,8 @@ #define WXDLLIMPEXP_DATA_PLOTCTRL(type) WXIMPORT type #else // not making nor using DLL */ - #define WXDLLIMPEXP_PLOTCTRL - #define WXDLLIMPEXP_DATA_PLOTCTRL(type) type +#define WXDLLIMPEXP_PLOTCTRL +#define WXDLLIMPEXP_DATA_PLOTCTRL(type) type /* #endif */ @@ -39,10 +39,10 @@ // ---------------------------------------------------------------------------- // Check if value is >= min_val and <= max_val -#define wxPCHECK_MINMAX_RET(val, min_val, max_val, msg) \ - wxCHECK_RET((int(val)>=int(min_val))&&(int(val)<=int(max_val)), msg) +#define wxPCHECK_MINMAX_RET(val, min_val, max_val, msg) \ + wxCHECK_RET((int(val) >= int(min_val)) && (int(val) <= int(max_val)), msg) -#define wxPCHECK_MINMAX_MSG(val, min_val, max_val, ret, msg) \ - wxCHECK_MSG((int(val)>=int(min_val))&&(int(val)<=int(max_val)), ret, msg) +#define wxPCHECK_MINMAX_MSG(val, min_val, max_val, ret, msg) \ + wxCHECK_MSG((int(val) >= int(min_val)) && (int(val) <= int(max_val)), ret, msg) -#endif // __WX_PLOTDEF_H__ +#endif // __WX_PLOTDEF_H__ diff --git a/src/labenski/include/wx/plotctrl/plotdraw.h b/src/labenski/include/wx/plotctrl/plotdraw.h index c6480d3a2..28505fce5 100644 --- a/src/labenski/include/wx/plotctrl/plotdraw.h +++ b/src/labenski/include/wx/plotctrl/plotdraw.h @@ -38,209 +38,201 @@ class WXDLLIMPEXP_PLOTCTRL wxPlotMarker; // wxPlotDrawerBase //----------------------------------------------------------------------------- -class wxPlotDrawerBase : public wxObject -{ +class wxPlotDrawerBase : public wxObject { public: - wxPlotDrawerBase(wxPlotCtrl* owner) : wxObject(), - m_owner(owner), m_pen_scale(1), m_font_scale(1) {} + wxPlotDrawerBase(wxPlotCtrl *owner) : wxObject(), m_owner(owner), m_pen_scale(1), m_font_scale(1) + { + } - virtual void Draw(wxDC* dc, bool refresh) = 0; + virtual void Draw(wxDC *dc, bool refresh) = 0; - // Get/Set the owner plotctrl - wxPlotCtrl* GetOwner() const { return m_owner; } - void SetOwner(wxPlotCtrl* owner) { m_owner = owner; } + // Get/Set the owner plotctrl + wxPlotCtrl *GetOwner() const { return m_owner; } + void SetOwner(wxPlotCtrl *owner) { m_owner = owner; } - // Get/Get the rect in the DC to draw on - void SetDCRect(const wxRect& rect) { m_dcRect = rect; } - const wxRect& GetDCRect() const { return m_dcRect; } + // Get/Get the rect in the DC to draw on + void SetDCRect(const wxRect &rect) { m_dcRect = rect; } + const wxRect &GetDCRect() const { return m_dcRect; } - // Get/Set the rect of the visible area in the plot window - void SetPlotViewRect(const wxRect2DDouble& rect) { m_plotViewRect = rect; } - const wxRect2DDouble& GetPlotViewRect() const { return m_plotViewRect; } + // Get/Set the rect of the visible area in the plot window + void SetPlotViewRect(const wxRect2DDouble &rect) { m_plotViewRect = rect; } + const wxRect2DDouble &GetPlotViewRect() const { return m_plotViewRect; } - // Get/Set the scaling for drawing, fonts, pens, etc are scaled - void SetPenScale(double scale) { m_pen_scale = scale; } - double GetPenScale() const { return m_pen_scale; } - void SetFontScale(double scale) { m_font_scale = scale; } - double GetFontScale() const { return m_font_scale; } + // Get/Set the scaling for drawing, fonts, pens, etc are scaled + void SetPenScale(double scale) { m_pen_scale = scale; } + double GetPenScale() const { return m_pen_scale; } + void SetFontScale(double scale) { m_font_scale = scale; } + double GetFontScale() const { return m_font_scale; } protected: - wxPlotCtrl* m_owner; - wxRect m_dcRect; - wxRect2DDouble m_plotViewRect; - double m_pen_scale; // width scaling factor for pens - double m_font_scale; // scaling factor for font sizes + wxPlotCtrl *m_owner; + wxRect m_dcRect; + wxRect2DDouble m_plotViewRect; + double m_pen_scale; // width scaling factor for pens + double m_font_scale; // scaling factor for font sizes private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerBase); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerBase); }; //----------------------------------------------------------------------------- // wxPlotDrawerArea //----------------------------------------------------------------------------- -class wxPlotDrawerArea : public wxPlotDrawerBase -{ +class wxPlotDrawerArea : public wxPlotDrawerBase { public: - wxPlotDrawerArea(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} + wxPlotDrawerArea(wxPlotCtrl *owner) : wxPlotDrawerBase(owner) {} - virtual void Draw(wxDC *dc, bool refresh); + virtual void Draw(wxDC *dc, bool refresh); private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerArea); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerArea); }; //----------------------------------------------------------------------------- // wxPlotDrawerAxisBase //----------------------------------------------------------------------------- -class wxPlotDrawerAxisBase : public wxPlotDrawerBase -{ +class wxPlotDrawerAxisBase : public wxPlotDrawerBase { public: - wxPlotDrawerAxisBase(wxPlotCtrl* owner); + wxPlotDrawerAxisBase(wxPlotCtrl *owner); - virtual void Draw(wxDC *dc, bool refresh) = 0; + virtual void Draw(wxDC *dc, bool refresh) = 0; - void SetTickFont( const wxFont& font ) { m_tickFont = font; } - void SetLabelFont( const wxFont& font ) { m_labelFont = font; } + void SetTickFont(const wxFont &font) { m_tickFont = font; } + void SetLabelFont(const wxFont &font) { m_labelFont = font; } - void SetTickColour( const wxGenericColour& colour ) { m_tickColour = colour; } - void SetLabelColour( const wxGenericColour& colour ) { m_labelColour = colour; } + void SetTickColour(const wxGenericColour &colour) { m_tickColour = colour; } + void SetLabelColour(const wxGenericColour &colour) { m_labelColour = colour; } - void SetTickPen( const wxGenericPen& pen ) { m_tickPen = pen; } - void SetBackgroundBrush( const wxGenericBrush& brush ) { m_backgroundBrush = brush; } + void SetTickPen(const wxGenericPen &pen) { m_tickPen = pen; } + void SetBackgroundBrush(const wxGenericBrush &brush) { m_backgroundBrush = brush; } - void SetTickPositions( const wxArrayInt& pos ) { m_tickPositions = pos; } - void SetTickLabels( const wxArrayString& labels ) { m_tickLabels = labels; } + void SetTickPositions(const wxArrayInt &pos) { m_tickPositions = pos; } + void SetTickLabels(const wxArrayString &labels) { m_tickLabels = labels; } - void SetLabel( const wxString& label ) { m_label = label; } + void SetLabel(const wxString &label) { m_label = label; } - // implementation - wxArrayInt m_tickPositions; - wxArrayString m_tickLabels; + // implementation + wxArrayInt m_tickPositions; + wxArrayString m_tickLabels; - wxString m_label; + wxString m_label; - wxFont m_tickFont; - wxFont m_labelFont; - wxGenericColour m_tickColour; - wxGenericColour m_labelColour; + wxFont m_tickFont; + wxFont m_labelFont; + wxGenericColour m_tickColour; + wxGenericColour m_labelColour; - wxGenericPen m_tickPen; - wxGenericBrush m_backgroundBrush; + wxGenericPen m_tickPen; + wxGenericBrush m_backgroundBrush; private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerAxisBase); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerAxisBase); }; //----------------------------------------------------------------------------- // wxPlotDrawerXAxis //----------------------------------------------------------------------------- -class wxPlotDrawerXAxis : public wxPlotDrawerAxisBase -{ +class wxPlotDrawerXAxis : public wxPlotDrawerAxisBase { public: - wxPlotDrawerXAxis(wxPlotCtrl* owner) : wxPlotDrawerAxisBase(owner) {} + wxPlotDrawerXAxis(wxPlotCtrl *owner) : wxPlotDrawerAxisBase(owner) {} - virtual void Draw(wxDC *dc, bool refresh); + virtual void Draw(wxDC *dc, bool refresh); private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerXAxis); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerXAxis); }; //----------------------------------------------------------------------------- // wxPlotDrawerYAxis //----------------------------------------------------------------------------- -class wxPlotDrawerYAxis : public wxPlotDrawerAxisBase -{ +class wxPlotDrawerYAxis : public wxPlotDrawerAxisBase { public: - wxPlotDrawerYAxis(wxPlotCtrl* owner) : wxPlotDrawerAxisBase(owner) {} + wxPlotDrawerYAxis(wxPlotCtrl *owner) : wxPlotDrawerAxisBase(owner) {} - virtual void Draw(wxDC *dc, bool refresh); + virtual void Draw(wxDC *dc, bool refresh); private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerYAxis); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerYAxis); }; //----------------------------------------------------------------------------- // wxPlotDrawerKey //----------------------------------------------------------------------------- -class wxPlotDrawerKey : public wxPlotDrawerBase -{ +class wxPlotDrawerKey : public wxPlotDrawerBase { public: - wxPlotDrawerKey(wxPlotCtrl* owner); + wxPlotDrawerKey(wxPlotCtrl *owner); - virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused - virtual void Draw(wxDC *dc, const wxString& keyString); + virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused + virtual void Draw(wxDC *dc, const wxString &keyString); - void SetFont(const wxFont& font) { m_font = font; } - void SetFontColour(const wxGenericColour& colour) { m_fontColour = colour; } + void SetFont(const wxFont &font) { m_font = font; } + void SetFontColour(const wxGenericColour &colour) { m_fontColour = colour; } - void SetKeyPosition(const wxPoint& pos) { m_keyPosition = pos; } + void SetKeyPosition(const wxPoint &pos) { m_keyPosition = pos; } - // implementation - wxFont m_font; - wxGenericColour m_fontColour; + // implementation + wxFont m_font; + wxGenericColour m_fontColour; - wxPoint m_keyPosition; - bool m_key_inside; - int m_border; - int m_key_line_width; // length of line to draw for curve - int m_key_line_margin; // margin between line and key text + wxPoint m_keyPosition; + bool m_key_inside; + int m_border; + int m_key_line_width; // length of line to draw for curve + int m_key_line_margin; // margin between line and key text private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerKey); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerKey); }; //----------------------------------------------------------------------------- // wxPlotDrawerCurve //----------------------------------------------------------------------------- -class wxPlotDrawerCurve : public wxPlotDrawerBase -{ +class wxPlotDrawerCurve : public wxPlotDrawerBase { public: - wxPlotDrawerCurve(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} + wxPlotDrawerCurve(wxPlotCtrl *owner) : wxPlotDrawerBase(owner) {} - virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused - virtual void Draw(wxDC *dc, wxPlotCurve *curve, int curve_index); + virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused + virtual void Draw(wxDC *dc, wxPlotCurve *curve, int curve_index); private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerCurve); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerCurve); }; //----------------------------------------------------------------------------- // wxPlotDrawerDataCurve //----------------------------------------------------------------------------- -class wxPlotDrawerDataCurve : public wxPlotDrawerBase -{ +class wxPlotDrawerDataCurve : public wxPlotDrawerBase { public: - wxPlotDrawerDataCurve(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} + wxPlotDrawerDataCurve(wxPlotCtrl *owner) : wxPlotDrawerBase(owner) {} - virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused - virtual void Draw(wxDC *dc, wxPlotData* plotData, int curve_index); + virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused + virtual void Draw(wxDC *dc, wxPlotData *plotData, int curve_index); private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerDataCurve); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerDataCurve); }; //----------------------------------------------------------------------------- // wxPlotDrawerMarkers //----------------------------------------------------------------------------- -class wxPlotDrawerMarker : public wxPlotDrawerBase -{ +class wxPlotDrawerMarker : public wxPlotDrawerBase { public: - wxPlotDrawerMarker(wxPlotCtrl* owner) : wxPlotDrawerBase(owner) {} + wxPlotDrawerMarker(wxPlotCtrl *owner) : wxPlotDrawerBase(owner) {} - virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused - virtual void Draw(wxDC *dc, const wxArrayPlotMarker& markers); - virtual void Draw(wxDC *dc, const wxPlotMarker& marker); + virtual void Draw(wxDC *WXUNUSED(dc), bool WXUNUSED(refresh)) {} // unused + virtual void Draw(wxDC *dc, const wxArrayPlotMarker &markers); + virtual void Draw(wxDC *dc, const wxPlotMarker &marker); private: - DECLARE_ABSTRACT_CLASS(wxPlotDrawerMarker); + DECLARE_ABSTRACT_CLASS(wxPlotDrawerMarker); }; #endif // _WX_PLOTDRAW_H_ diff --git a/src/labenski/include/wx/plotctrl/plotfunc.h b/src/labenski/include/wx/plotctrl/plotfunc.h index 73f19638f..8abbe68fa 100644 --- a/src/labenski/include/wx/plotctrl/plotfunc.h +++ b/src/labenski/include/wx/plotctrl/plotfunc.h @@ -20,76 +20,74 @@ // vars is "x" or "x,y" where x and y are the vars used in the function string // //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotFunction: public wxPlotCurve -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotFunction : public wxPlotCurve { public: - wxPlotFunction() : wxPlotCurve() {} - wxPlotFunction(const wxPlotFunction &curve) : wxPlotCurve() { Create(curve); } - wxPlotFunction(const wxString &function, const wxString &vars = wxT("x"), - bool useDegrees = false) : wxPlotCurve() - { Create(function, vars, useDegrees); } - - virtual ~wxPlotFunction() {} - - // Initialize curve, returns -1 on sucess and errormsg is wxEmptyString. - // On error, the errormsg contains a message and the character location - // in the 'function' string where the error occurred is returned. - // Check if errormsg != wxEmptyString, or curve.Ok() not the returned int - // vars is a comma delimited list of variables used in the function "x,y,z" - // vars can be wxEmptyString, see GetValue(NULL), the function is a constant - int Create( const wxString &function, const wxString &vars = wxT("x"), - bool useDegrees = false ); - // Make a copy of the other plotFunction - bool Create( const wxPlotFunction &curve ); - - bool Ok() const; - void Destroy(); - - // Parse and use the function, see Create, does not destroy refdata - int Parse( const wxString &function, const wxString &vars = wxT("x"), - bool useDegrees = false ); - - // Get the strings sent to Create - wxString GetFunctionString() const; // the function string "a*(b+3)/2 + c" - wxString GetVariableString() const; // the variable string "a,b,c" - wxString GetVariableName(size_t n) const; // a single variable name n=0="a" - int GetNumberVariables() const; - bool GetUseDegrees() const; // was this created to use degrees? - - // Get an error message (if any) if Create does not return -1 false - wxString GetErrorMsg() const; - - // Get the f(x) value from the function parser, use this if only have x variable - double GetY( double x ); - // Get the f(x,y...) using an arbitrary number of vars - // you absolutely MUST pass double x[GetNumberVariables()] - // if you sent in a wxEmptyString for the vars then use NULL - double GetValue( double *x ); - - // add a constant to use - bool AddConstant(const wxString& name, double value); - - bool operator == (const wxPlotFunction& plotFunc) const - { return m_refData == plotFunc.m_refData; } - bool operator != (const wxPlotFunction& plotFunc) const - { return m_refData != plotFunc.m_refData; } - - wxPlotFunction& operator = (const wxPlotFunction& plotFunc) - { - if ( (*this) != plotFunc ) - Ref(plotFunc); - return *this; + wxPlotFunction() : wxPlotCurve() {} + wxPlotFunction(const wxPlotFunction &curve) : wxPlotCurve() { Create(curve); } + wxPlotFunction(const wxString &function, const wxString &vars = wxT("x"), + bool useDegrees = false) + : wxPlotCurve() + { + Create(function, vars, useDegrees); + } + + virtual ~wxPlotFunction() {} + + // Initialize curve, returns -1 on sucess and errormsg is wxEmptyString. + // On error, the errormsg contains a message and the character location + // in the 'function' string where the error occurred is returned. + // Check if errormsg != wxEmptyString, or curve.Ok() not the returned int + // vars is a comma delimited list of variables used in the function "x,y,z" + // vars can be wxEmptyString, see GetValue(NULL), the function is a constant + int Create(const wxString &function, const wxString &vars = wxT("x"), bool useDegrees = false); + // Make a copy of the other plotFunction + bool Create(const wxPlotFunction &curve); + + bool Ok() const; + void Destroy(); + + // Parse and use the function, see Create, does not destroy refdata + int Parse(const wxString &function, const wxString &vars = wxT("x"), bool useDegrees = false); + + // Get the strings sent to Create + wxString GetFunctionString() const; // the function string "a*(b+3)/2 + c" + wxString GetVariableString() const; // the variable string "a,b,c" + wxString GetVariableName(size_t n) const; // a single variable name n=0="a" + int GetNumberVariables() const; + bool GetUseDegrees() const; // was this created to use degrees? + + // Get an error message (if any) if Create does not return -1 false + wxString GetErrorMsg() const; + + // Get the f(x) value from the function parser, use this if only have x variable + double GetY(double x); + // Get the f(x,y...) using an arbitrary number of vars + // you absolutely MUST pass double x[GetNumberVariables()] + // if you sent in a wxEmptyString for the vars then use NULL + double GetValue(double *x); + + // add a constant to use + bool AddConstant(const wxString &name, double value); + + bool operator==(const wxPlotFunction &plotFunc) const { return m_refData == plotFunc.m_refData; } + bool operator!=(const wxPlotFunction &plotFunc) const { return m_refData != plotFunc.m_refData; } + + wxPlotFunction &operator=(const wxPlotFunction &plotFunc) + { + if ((*this) != plotFunc) { + Ref(plotFunc); } + return *this; + } -private : - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; +private: + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxPlotFunction); + DECLARE_DYNAMIC_CLASS(wxPlotFunction); }; - //----------------------------------------------------------------------------- // Functions for getting/setting a wxPlotFunction to/from the wxClipboard //----------------------------------------------------------------------------- @@ -101,8 +99,7 @@ wxPlotFunction wxClipboardGetPlotFunction(); // Set the plot function curve into the clipboard. Copies function and vars string // separated by a ';' as a text object, use wxString::Before/AfterLast(wxT(';')). // returns sucess -bool wxClipboardSetPlotFunction(const wxPlotFunction& plotFunction); - +bool wxClipboardSetPlotFunction(const wxPlotFunction &plotFunction); #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD diff --git a/src/labenski/include/wx/plotctrl/plotmark.h b/src/labenski/include/wx/plotctrl/plotmark.h index c30e9c111..bb76ed363 100644 --- a/src/labenski/include/wx/plotctrl/plotmark.h +++ b/src/labenski/include/wx/plotctrl/plotmark.h @@ -29,158 +29,165 @@ WX_DECLARE_OBJARRAY_WITH_DECL(wxPlotMarker, wxArrayPlotMarker, class WXDLLIMPEXP // wxPlotMarker marker; marker.CreateXXX(...) //----------------------------------------------------------------------------- -enum wxPlotMarkerType -{ - wxPLOTMARKER_NONE, // invalid, don't draw it - wxPLOTMARKER_POINT, // single pixel point, only position & pen used - // size, brush, bitmap unused - wxPLOTMARKER_LINE, // line from upper left to lower right of rect - // rect may be inverted to draw at any angle - // size, brush, bitmap unused - wxPLOTMARKER_HORIZ_LINE,// horizontal line, full width - // only vert position and pen used - // size, brush, bitmap unused - wxPLOTMARKER_VERT_LINE, // vertical line, full height - // only horiz position and pen used - // size, brush, bitmap unused - wxPLOTMARKER_CROSS, // vertical and horizontal line, full height & width - // position used for center of cross - // size, brush, bitmap unused - wxPLOTMARKER_RECT, // rectangle - see plot rect conditions - // pen draws outline and brush fills (if set) - // bitmap unused - // rect drawn centered on position - // size is size of the rect - wxPLOTMARKER_ELLIPSE, // ellipse - see plot rect conditions - wxPLOTMARKER_BITMAP // the bitmap is drawn at the position +enum wxPlotMarkerType { + wxPLOTMARKER_NONE, // invalid, don't draw it + wxPLOTMARKER_POINT, // single pixel point, only position & pen used + // size, brush, bitmap unused + wxPLOTMARKER_LINE, // line from upper left to lower right of rect + // rect may be inverted to draw at any angle + // size, brush, bitmap unused + wxPLOTMARKER_HORIZ_LINE, // horizontal line, full width + // only vert position and pen used + // size, brush, bitmap unused + wxPLOTMARKER_VERT_LINE, // vertical line, full height + // only horiz position and pen used + // size, brush, bitmap unused + wxPLOTMARKER_CROSS, // vertical and horizontal line, full height & width + // position used for center of cross + // size, brush, bitmap unused + wxPLOTMARKER_RECT, // rectangle - see plot rect conditions + // pen draws outline and brush fills (if set) + // bitmap unused + // rect drawn centered on position + // size is size of the rect + wxPLOTMARKER_ELLIPSE, // ellipse - see plot rect conditions + wxPLOTMARKER_BITMAP // the bitmap is drawn at the position }; -class WXDLLIMPEXP_PLOTCTRL wxPlotMarker : public wxObject -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotMarker : public wxObject { public: - wxPlotMarker() : wxObject() {} - // Create a full marker (see CreateXXX functions) - wxPlotMarker(int marker_type, - const wxRect2DDouble& rect, - const wxSize& size, - const wxGenericPen& pen, - const wxGenericBrush& brush = wxNullGenericBrush, - const wxBitmap& bitmap = wxNullBitmap) : wxObject() - { Create(marker_type, rect, size, pen, brush, bitmap); } - // Create a shape marker to be drawn at the point with the given size - // in pixels - wxPlotMarker(int marker_type, - const wxPoint2DDouble& pt, - const wxSize& size, - const wxGenericPen& pen, - const wxGenericBrush& brush = wxNullGenericBrush) : wxObject() - { Create(marker_type, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); } - // Create a bitmap marker - wxPlotMarker(const wxPoint2DDouble& pt, - const wxBitmap& bitmap) : wxObject() - { CreateBitmapMarker(pt, bitmap); } - - virtual ~wxPlotMarker() {} - - // is the marker created - bool Ok() const { return m_refData != NULL; } - - // Generic create function - void Create(int marker_type, const wxRect2DDouble& rect, - const wxSize& size, const wxGenericPen& pen, - const wxGenericBrush& brush = wxNullGenericBrush, - const wxBitmap& bitmap = wxNullBitmap); - - // Simplified methods (use these) - void CreatePointMarker(const wxPoint2DDouble& pt, - const wxGenericPen& pen) - { Create(wxPLOTMARKER_POINT, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), wxSize(-1, -1), pen); } - void CreateLineMarker(const wxRect2DDouble& rect, const wxGenericPen& pen) - { Create(wxPLOTMARKER_LINE, rect, wxSize(-1, -1), pen); } - void CreateHorizLineMarker(double y, const wxGenericPen& pen) - { Create(wxPLOTMARKER_HORIZ_LINE, wxRect2DDouble(0, y, -1, 0), wxSize(-1, -1), pen); } - void CreateVertLineMarker(double x, const wxGenericPen& pen) - { Create(wxPLOTMARKER_VERT_LINE, wxRect2DDouble(x, 0, 0, -1), wxSize(-1, -1), pen); } - void CreateRectMarker(const wxRect2DDouble& rect, - const wxGenericPen& pen, - const wxGenericBrush& brush = wxNullGenericBrush) - { Create(wxPLOTMARKER_RECT, rect, wxSize(-1, -1), pen, brush); } - void CreateRectMarker(const wxPoint2DDouble& pt, - const wxSize& size, - const wxGenericPen& pen, - const wxGenericBrush& brush = wxNullGenericBrush) - { Create(wxPLOTMARKER_RECT, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); } -// void CreateEllipseMarker(const wxRect2DDouble& rect, -// const wxGenericPen& pen, -// const wxGenericBrush& brush = wxNullGenericBrush) -// { Create(wxPLOTMARKER_ELLIPSE, rect, wxSize(-1, -1), pen, brush); } - void CreateEllipseMarker(const wxPoint2DDouble& pt, - const wxSize& size, - const wxGenericPen& pen, - const wxGenericBrush& brush = wxNullGenericBrush) - { Create(wxPLOTMARKER_ELLIPSE, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); } - void CreateBitmapMarker(const wxPoint2DDouble& pt, - const wxBitmap& bitmap) - { Create(wxPLOTMARKER_BITMAP, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), wxSize(-1, -1), wxNullGenericPen, wxNullGenericBrush, bitmap); } - - // Get/Set the marker type - int GetMarkerType() const; - void SetMarkerType(int type); - - // Get/Set the rect to draw the marker into - // The meaning of the rect is different for each marker type - // - // Bitmap markers - // Drawn centered at upper left if width = height = 0 - // Drawn into the rect and scaled if width & height != 0 - // - // Shape markers - // Draws a full rect/ellipse if width & height > 0 - // Draws a point if width & height = 0 - // Draws a vertical line if width = 0 & height != 0 - // Draws a horizontal line if height = 0 & width != 0 - // Draws the full width if width < 0 - // Draws the full height if height < 0 - wxRect2DDouble GetPlotRect() const; - wxRect2DDouble& GetPlotRect(); - void SetPlotRect(const wxRect2DDouble& rect); - - wxPoint2DDouble GetPlotPosition() const; - void SetPlotPosition(const wxPoint2DDouble& pos); - - // for rect/ellipse markers you can set the size in pixels - wxSize GetSize() const; - void SetSize(const wxSize& size); - - // Get/Set the pen to draw the lines with - wxGenericPen GetPen() const; - void SetPen(const wxGenericPen& pen); - // Get/Set the brush to fill the area with (null for none) - wxGenericBrush GetBrush() const; - void SetBrush(const wxGenericBrush& brush); - // Get/Set the bitmap to draw (null for none, ignored if not wxPLOTMARKER_BITMAP) - wxBitmap GetBitmap() const; - void SetBitmap(const wxBitmap& bitmap); - - // operators - bool operator == (const wxPlotMarker& pm) const - { return m_refData == pm.m_refData; } - bool operator != (const wxPlotMarker& pm) const - { return m_refData != pm.m_refData; } - - wxPlotMarker& operator = (const wxPlotMarker& pm) - { - if ( (*this) != pm ) - Ref(pm); - return *this; + wxPlotMarker() : wxObject() {} + // Create a full marker (see CreateXXX functions) + wxPlotMarker(int marker_type, const wxRect2DDouble &rect, const wxSize &size, + const wxGenericPen &pen, const wxGenericBrush &brush = wxNullGenericBrush, + const wxBitmap &bitmap = wxNullBitmap) + : wxObject() + { + Create(marker_type, rect, size, pen, brush, bitmap); + } + // Create a shape marker to be drawn at the point with the given size + // in pixels + wxPlotMarker(int marker_type, const wxPoint2DDouble &pt, const wxSize &size, + const wxGenericPen &pen, const wxGenericBrush &brush = wxNullGenericBrush) + : wxObject() + { + Create(marker_type, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); + } + // Create a bitmap marker + wxPlotMarker(const wxPoint2DDouble &pt, const wxBitmap &bitmap) : wxObject() + { + CreateBitmapMarker(pt, bitmap); + } + + virtual ~wxPlotMarker() {} + + // is the marker created + bool Ok() const { return m_refData != NULL; } + + // Generic create function + void Create(int marker_type, const wxRect2DDouble &rect, const wxSize &size, + const wxGenericPen &pen, const wxGenericBrush &brush = wxNullGenericBrush, + const wxBitmap &bitmap = wxNullBitmap); + + // Simplified methods (use these) + void CreatePointMarker(const wxPoint2DDouble &pt, const wxGenericPen &pen) + { + Create(wxPLOTMARKER_POINT, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), wxSize(-1, -1), pen); + } + void CreateLineMarker(const wxRect2DDouble &rect, const wxGenericPen &pen) + { + Create(wxPLOTMARKER_LINE, rect, wxSize(-1, -1), pen); + } + void CreateHorizLineMarker(double y, const wxGenericPen &pen) + { + Create(wxPLOTMARKER_HORIZ_LINE, wxRect2DDouble(0, y, -1, 0), wxSize(-1, -1), pen); + } + void CreateVertLineMarker(double x, const wxGenericPen &pen) + { + Create(wxPLOTMARKER_VERT_LINE, wxRect2DDouble(x, 0, 0, -1), wxSize(-1, -1), pen); + } + void CreateRectMarker(const wxRect2DDouble &rect, const wxGenericPen &pen, + const wxGenericBrush &brush = wxNullGenericBrush) + { + Create(wxPLOTMARKER_RECT, rect, wxSize(-1, -1), pen, brush); + } + void CreateRectMarker(const wxPoint2DDouble &pt, const wxSize &size, const wxGenericPen &pen, + const wxGenericBrush &brush = wxNullGenericBrush) + { + Create(wxPLOTMARKER_RECT, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); + } + // void CreateEllipseMarker(const wxRect2DDouble& rect, + // const wxGenericPen& pen, + // const wxGenericBrush& brush = wxNullGenericBrush) + // { Create(wxPLOTMARKER_ELLIPSE, rect, wxSize(-1, -1), pen, brush); } + void CreateEllipseMarker(const wxPoint2DDouble &pt, const wxSize &size, const wxGenericPen &pen, + const wxGenericBrush &brush = wxNullGenericBrush) + { + Create(wxPLOTMARKER_ELLIPSE, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), size, pen, brush); + } + void CreateBitmapMarker(const wxPoint2DDouble &pt, const wxBitmap &bitmap) + { + Create(wxPLOTMARKER_BITMAP, wxRect2DDouble(pt.m_x, pt.m_y, 0, 0), wxSize(-1, -1), + wxNullGenericPen, wxNullGenericBrush, bitmap); + } + + // Get/Set the marker type + int GetMarkerType() const; + void SetMarkerType(int type); + + // Get/Set the rect to draw the marker into + // The meaning of the rect is different for each marker type + // + // Bitmap markers + // Drawn centered at upper left if width = height = 0 + // Drawn into the rect and scaled if width & height != 0 + // + // Shape markers + // Draws a full rect/ellipse if width & height > 0 + // Draws a point if width & height = 0 + // Draws a vertical line if width = 0 & height != 0 + // Draws a horizontal line if height = 0 & width != 0 + // Draws the full width if width < 0 + // Draws the full height if height < 0 + wxRect2DDouble GetPlotRect() const; + wxRect2DDouble &GetPlotRect(); + void SetPlotRect(const wxRect2DDouble &rect); + + wxPoint2DDouble GetPlotPosition() const; + void SetPlotPosition(const wxPoint2DDouble &pos); + + // for rect/ellipse markers you can set the size in pixels + wxSize GetSize() const; + void SetSize(const wxSize &size); + + // Get/Set the pen to draw the lines with + wxGenericPen GetPen() const; + void SetPen(const wxGenericPen &pen); + // Get/Set the brush to fill the area with (null for none) + wxGenericBrush GetBrush() const; + void SetBrush(const wxGenericBrush &brush); + // Get/Set the bitmap to draw (null for none, ignored if not wxPLOTMARKER_BITMAP) + wxBitmap GetBitmap() const; + void SetBitmap(const wxBitmap &bitmap); + + // operators + bool operator==(const wxPlotMarker &pm) const { return m_refData == pm.m_refData; } + bool operator!=(const wxPlotMarker &pm) const { return m_refData != pm.m_refData; } + + wxPlotMarker &operator=(const wxPlotMarker &pm) + { + if ((*this) != pm) { + Ref(pm); } + return *this; + } private: - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxPlotMarker); + DECLARE_DYNAMIC_CLASS(wxPlotMarker); }; #endif // _WX_PLOTMARK_H_ diff --git a/src/labenski/include/wx/plotctrl/plotprnt.h b/src/labenski/include/wx/plotctrl/plotprnt.h index 650620964..78a25af32 100644 --- a/src/labenski/include/wx/plotctrl/plotprnt.h +++ b/src/labenski/include/wx/plotctrl/plotprnt.h @@ -21,54 +21,61 @@ class WXDLLIMPEXP_PLOTCTRL wxPlotCtrl; // on a single page //----------------------------------------------------------------------------- -class WXDLLIMPEXP_PLOTCTRL wxPlotPrintout : public wxPrintout -{ +class WXDLLIMPEXP_PLOTCTRL wxPlotPrintout : public wxPrintout { public: - wxPlotPrintout(wxPlotCtrl* plotWin, const wxString &title = wxEmptyString); - bool OnPrintPage(int page); - bool HasPage(int page) { return page == 1; } - bool OnBeginDocument(int startPage, int endPage); + wxPlotPrintout(wxPlotCtrl *plotWin, const wxString &title = wxEmptyString); + bool OnPrintPage(int page); + bool HasPage(int page) { return page == 1; } + bool OnBeginDocument(int startPage, int endPage); - void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) - { - if (minPage) *minPage = 1; - if (maxPage) *maxPage = 1; - if (selPageFrom) *selPageFrom = 1; - if (selPageTo) *selPageTo = 1; + void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) + { + if (minPage) { + *minPage = 1; } + if (maxPage) { + *maxPage = 1; + } + if (selPageFrom) { + *selPageFrom = 1; + } + if (selPageTo) { + *selPageTo = 1; + } + } - // Simplified methods to show the standard print dialogs - bool ShowPrintDialog(); - bool ShowPrintPreviewDialog(const wxString& frameTitle = wxT("Plot print preview")); - bool ShowPrintSetupDialog(); - bool ShowPrintPageSetupDialog(); + // Simplified methods to show the standard print dialogs + bool ShowPrintDialog(); + bool ShowPrintPreviewDialog(const wxString &frameTitle = wxT("Plot print preview")); + bool ShowPrintSetupDialog(); + bool ShowPrintPageSetupDialog(); - wxPlotCtrl *GetPlotCtrl() const { return m_plotWin; } + wxPlotCtrl *GetPlotCtrl() const { return m_plotWin; } - // Get/Set the wxPrintData/wxPageSetupData that will be used - // if NULL then one will be created on first use and deleted when the - // program exits. It may make sense to create a single instance of your - // printdata in the wxApp for all your program's printing needs and use - // SetPrintData/PageSetupData to share it with this. - static wxPrintData *GetPrintData(bool create_on_demand = false); - static wxPageSetupData *GetPageSetupData(bool create_on_demand = false); - static bool GetPrintDataStatic(); - static bool GetPageSetupDataStatic(); - // Set the wxPrintData/PageSetupData, if !is_static then it will be deleted - // when the program exits - static void SetPrintData( wxPrintData *printData, bool is_static ); - static void SetPageSetupData( wxPageSetupData *pageSetupData, bool is_static ); + // Get/Set the wxPrintData/wxPageSetupData that will be used + // if NULL then one will be created on first use and deleted when the + // program exits. It may make sense to create a single instance of your + // printdata in the wxApp for all your program's printing needs and use + // SetPrintData/PageSetupData to share it with this. + static wxPrintData *GetPrintData(bool create_on_demand = false); + static wxPageSetupData *GetPageSetupData(bool create_on_demand = false); + static bool GetPrintDataStatic(); + static bool GetPageSetupDataStatic(); + // Set the wxPrintData/PageSetupData, if !is_static then it will be deleted + // when the program exits + static void SetPrintData(wxPrintData *printData, bool is_static); + static void SetPageSetupData(wxPageSetupData *pageSetupData, bool is_static); protected: - wxPlotCtrl *m_plotWin; + wxPlotCtrl *m_plotWin; - static wxPrintData *s_wxPlotPrintData; - static wxPageSetupData *s_wxPlotPageSetupData; - static bool s_wxPlotPrintdata_static; - static bool s_wxPlotPagesetupdata_static; + static wxPrintData *s_wxPlotPrintData; + static wxPageSetupData *s_wxPlotPageSetupData; + static bool s_wxPlotPrintdata_static; + static bool s_wxPlotPagesetupdata_static; private: - DECLARE_ABSTRACT_CLASS(wxPlotPrintout) + DECLARE_ABSTRACT_CLASS(wxPlotPrintout) }; #endif // _WX_PLOTPRINT_H_ diff --git a/src/labenski/include/wx/sheet/pairarr.h b/src/labenski/include/wx/sheet/pairarr.h index 6f0177b8f..33d96b16f 100644 --- a/src/labenski/include/wx/sheet/pairarr.h +++ b/src/labenski/include/wx/sheet/pairarr.h @@ -117,175 +117,230 @@ // // ============================================================================ -#define DECLARE_PAIRED_DATA_ARRAYS_BASE(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ -\ -classexp name \ -{ \ -public: \ - name() {} \ - name(const Tval& defaultVal) : m_defaultValue(defaultVal) {} \ - name(const name& other) { Copy(other); } \ - name(const Tkey& key, const Tval& val) { m_keys.Add(key); m_values.Add(val); } \ - int GetCount() const { return m_keys.GetCount(); } \ - int FindIndex(const Tkey& key) const; \ - size_t FindInsertIndex(const Tkey& pos) const; \ - bool HasKey(const Tkey& key) const { return FindIndex(key) != wxNOT_FOUND; } \ - const Tval& GetValue(const Tkey& key) const; \ - Tval& GetValue(const Tkey& key); \ - Tval& GetOrCreateValue(const Tkey& key); \ - void SetValue(const Tkey& key, const Tval& value); \ - bool RemoveValue(const Tkey& key); \ - void Clear() { m_keys.Clear(); m_values.Clear(); } \ - const Tval& GetItemValue(size_t index) const { return m_values[index]; } \ - const Tkey& GetItemKey(size_t index) const { return m_keys[index]; } \ - Tval& GetItemValue(size_t index) { return m_values[index]; } \ - Tkey& GetItemKey(size_t index) { return m_keys[index]; } \ - void RemoveAt(size_t index) { m_keys.RemoveAt(index); m_values.RemoveAt(index); } \ - const TvalArray& GetValues() const { return m_values; } \ - const TkeyArray& GetKeys() const { return m_keys; } \ - TvalArray& GetValues() { return m_values; } \ - TkeyArray& GetKeys() { return m_keys; } \ - const Tval& GetDefaultValue() const { return m_defaultValue; } \ - void SetDefaultValue(const Tval& val) { m_defaultValue = val; } \ - void Copy(const name& other); \ - void Sort() { if (GetCount() > 1) q_sort(0, GetCount()-1); } \ - name& operator=(const name& other) { Copy(other); return *this; } \ -protected : \ - void q_sort(int left, int right); \ - TkeyArray m_keys; \ - TvalArray m_values; \ +#define DECLARE_PAIRED_DATA_ARRAYS_BASE(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ + \ + classexp name \ + { \ + public: \ + name() {} \ + name(const Tval &defaultVal) : m_defaultValue(defaultVal) {} \ + name(const name &other) { Copy(other); } \ + name(const Tkey &key, const Tval &val) \ + { \ + m_keys.Add(key); \ + m_values.Add(val); \ + } \ + int GetCount() const { return m_keys.GetCount(); } \ + int FindIndex(const Tkey &key) const; \ + size_t FindInsertIndex(const Tkey &pos) const; \ + bool HasKey(const Tkey &key) const { return FindIndex(key) != wxNOT_FOUND; } \ + const Tval &GetValue(const Tkey &key) const; \ + Tval &GetValue(const Tkey &key); \ + Tval &GetOrCreateValue(const Tkey &key); \ + void SetValue(const Tkey &key, const Tval &value); \ + bool RemoveValue(const Tkey &key); \ + void Clear() \ + { \ + m_keys.Clear(); \ + m_values.Clear(); \ + } \ + const Tval &GetItemValue(size_t index) const { return m_values[index]; } \ + const Tkey &GetItemKey(size_t index) const { return m_keys[index]; } \ + Tval &GetItemValue(size_t index) { return m_values[index]; } \ + Tkey &GetItemKey(size_t index) { return m_keys[index]; } \ + void RemoveAt(size_t index) \ + { \ + m_keys.RemoveAt(index); \ + m_values.RemoveAt(index); \ + } \ + const TvalArray &GetValues() const { return m_values; } \ + const TkeyArray &GetKeys() const { return m_keys; } \ + TvalArray &GetValues() { return m_values; } \ + TkeyArray &GetKeys() { return m_keys; } \ + const Tval &GetDefaultValue() const { return m_defaultValue; } \ + void SetDefaultValue(const Tval &val) { m_defaultValue = val; } \ + void Copy(const name &other); \ + void Sort() \ + { \ + if (GetCount() > 1) \ + q_sort(0, GetCount() - 1); \ + } \ + name &operator=(const name &other) \ + { \ + Copy(other); \ + return *this; \ + } \ + \ + protected: \ + void q_sort(int left, int right); \ + TkeyArray m_keys; \ + TvalArray m_values; \ Tval m_defaultValue; // ---------------------------------------------------------------------------- // Note: The above macros is incomplete to allow you to extend the class. -#define DECLARE_PAIRED_DATA_ARRAYS(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ -DECLARE_PAIRED_DATA_ARRAYS_BASE(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ -}; +#define DECLARE_PAIRED_DATA_ARRAYS(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ + DECLARE_PAIRED_DATA_ARRAYS_BASE(Tkey, TkeyArray, Tval, TvalArray, name, classexp) \ + } \ + ; -#define DECLARE_PAIRED_INT_DATA_ARRAYS_BASE(Tval, TvalArray, name, classexp) \ -DECLARE_PAIRED_DATA_ARRAYS_BASE(int, wxArrayInt, Tval, TvalArray, name, classexp) \ -public: \ - bool UpdatePos( int pos, int numPos ); +#define DECLARE_PAIRED_INT_DATA_ARRAYS_BASE(Tval, TvalArray, name, classexp) \ + DECLARE_PAIRED_DATA_ARRAYS_BASE(int, wxArrayInt, Tval, TvalArray, name, classexp) \ +public: \ + bool UpdatePos(int pos, int numPos); -#define DECLARE_PAIRED_INT_DATA_ARRAYS(Tval, TvalArray, name, classexp) \ -DECLARE_PAIRED_INT_DATA_ARRAYS_BASE(Tval, TvalArray, name, classexp) \ -}; +#define DECLARE_PAIRED_INT_DATA_ARRAYS(Tval, TvalArray, name, classexp) \ + DECLARE_PAIRED_INT_DATA_ARRAYS_BASE(Tval, TvalArray, name, classexp) \ + } \ + ; // ============================================================================ -#define DEFINE_PAIRED_DATA_ARRAYS(Tkey, Tval, name) \ -\ -const Tval& name::GetValue(const Tkey& key) const \ -{ \ - const int n = FindIndex(key); \ - if (n != wxNOT_FOUND) return m_values[n]; \ - return m_defaultValue; \ -} \ -Tval& name::GetValue(const Tkey& key) \ -{ \ - const int n = FindIndex(key); \ - if (n != wxNOT_FOUND) return m_values[n]; \ - return m_defaultValue; \ -} \ -Tval& name::GetOrCreateValue(const Tkey& key) \ -{ \ - const size_t n = FindInsertIndex(key); \ - if (n == m_keys.GetCount()) \ - { m_keys.Add(key); m_values.Add(Tval(m_defaultValue)); } \ - else if (key != m_keys[n]) \ - { m_keys.Insert(key, n); m_values.Insert(Tval(m_defaultValue), n); } \ - return m_values[n]; \ -} \ -void name::SetValue(const Tkey& key, const Tval& value) \ -{ \ - const size_t n = FindInsertIndex(key); \ - if (n == m_keys.GetCount()) \ - { m_keys.Add(key); m_values.Add(value); } \ - else if (key == m_keys[n]) \ - m_values[n] = value; \ - else \ - { m_keys.Insert(key, n); m_values.Insert(value, n); } \ -} \ -bool name::RemoveValue(const Tkey& key) \ -{ \ - const int n = FindIndex(key); \ - if (n != wxNOT_FOUND) { RemoveAt(n); return true; } \ - return false; \ -} \ -int name::FindIndex(const Tkey& key) const \ -{ \ - size_t n, lo = 0, hi = m_keys.GetCount(); \ - while ( lo < hi ) \ - { \ - n = (lo + hi)/2; \ - const Tkey &tmp = m_keys[n]; \ - if (tmp == key) return n; \ - if (tmp > key) hi = n; \ - else lo = n + 1; \ - } \ - return wxNOT_FOUND; \ -} \ -size_t name::FindInsertIndex(const Tkey& key) const \ -{ \ - size_t n, lo = 0, hi = m_keys.GetCount(); \ - while ( lo < hi ) \ - { \ - n = (lo + hi)/2; \ - const Tkey &tmp = m_keys[n]; \ - if (tmp == key) return n; \ - if (tmp > key) hi = n; \ - else lo = n + 1; \ - } \ - return lo; \ -} \ -void name::Copy(const name& other) \ -{ \ - m_keys = other.GetKeys(); \ - m_values = other.GetValues(); \ - m_defaultValue = other.GetDefaultValue(); \ -} \ -void name::q_sort(int left, int right) \ -{ \ - int l_hold = left, r_hold = right; \ - Tkey pivot = m_keys[left]; Tval pivotVal = m_values[left]; \ - while (left < right) \ - { \ - while ((m_keys[right] >= pivot) && (left < right)) right--; \ - if (left != right) { m_keys[left] = m_keys[right]; \ - m_values[left] = m_values[right]; left++; } \ - while ((m_keys[left] <= pivot) && (left < right)) left++; \ - if (left != right) { m_keys[right] = m_keys[left]; \ - m_values[right] = m_values[left]; right--; } \ - } \ - m_keys[left] = pivot; m_values[left] = pivotVal; \ - if (l_hold < left) q_sort(l_hold, left-1); \ - if (r_hold > left) q_sort(left+1, r_hold); \ -} +#define DEFINE_PAIRED_DATA_ARRAYS(Tkey, Tval, name) \ + \ + const Tval &name::GetValue(const Tkey &key) const \ + { \ + const int n = FindIndex(key); \ + if (n != wxNOT_FOUND) \ + return m_values[n]; \ + return m_defaultValue; \ + } \ + Tval &name::GetValue(const Tkey &key) \ + { \ + const int n = FindIndex(key); \ + if (n != wxNOT_FOUND) \ + return m_values[n]; \ + return m_defaultValue; \ + } \ + Tval &name::GetOrCreateValue(const Tkey &key) \ + { \ + const size_t n = FindInsertIndex(key); \ + if (n == m_keys.GetCount()) { \ + m_keys.Add(key); \ + m_values.Add(Tval(m_defaultValue)); \ + } \ + else if (key != m_keys[n]) { \ + m_keys.Insert(key, n); \ + m_values.Insert(Tval(m_defaultValue), n); \ + } \ + return m_values[n]; \ + } \ + void name::SetValue(const Tkey &key, const Tval &value) \ + { \ + const size_t n = FindInsertIndex(key); \ + if (n == m_keys.GetCount()) { \ + m_keys.Add(key); \ + m_values.Add(value); \ + } \ + else if (key == m_keys[n]) \ + m_values[n] = value; \ + else { \ + m_keys.Insert(key, n); \ + m_values.Insert(value, n); \ + } \ + } \ + bool name::RemoveValue(const Tkey &key) \ + { \ + const int n = FindIndex(key); \ + if (n != wxNOT_FOUND) { \ + RemoveAt(n); \ + return true; \ + } \ + return false; \ + } \ + int name::FindIndex(const Tkey &key) const \ + { \ + size_t n, lo = 0, hi = m_keys.GetCount(); \ + while (lo < hi) { \ + n = (lo + hi) / 2; \ + const Tkey &tmp = m_keys[n]; \ + if (tmp == key) \ + return n; \ + if (tmp > key) \ + hi = n; \ + else \ + lo = n + 1; \ + } \ + return wxNOT_FOUND; \ + } \ + size_t name::FindInsertIndex(const Tkey &key) const \ + { \ + size_t n, lo = 0, hi = m_keys.GetCount(); \ + while (lo < hi) { \ + n = (lo + hi) / 2; \ + const Tkey &tmp = m_keys[n]; \ + if (tmp == key) \ + return n; \ + if (tmp > key) \ + hi = n; \ + else \ + lo = n + 1; \ + } \ + return lo; \ + } \ + void name::Copy(const name &other) \ + { \ + m_keys = other.GetKeys(); \ + m_values = other.GetValues(); \ + m_defaultValue = other.GetDefaultValue(); \ + } \ + void name::q_sort(int left, int right) \ + { \ + int l_hold = left, r_hold = right; \ + Tkey pivot = m_keys[left]; \ + Tval pivotVal = m_values[left]; \ + while (left < right) { \ + while ((m_keys[right] >= pivot) && (left < right)) \ + right--; \ + if (left != right) { \ + m_keys[left] = m_keys[right]; \ + m_values[left] = m_values[right]; \ + left++; \ + } \ + while ((m_keys[left] <= pivot) && (left < right)) \ + left++; \ + if (left != right) { \ + m_keys[right] = m_keys[left]; \ + m_values[right] = m_values[left]; \ + right--; \ + } \ + } \ + m_keys[left] = pivot; \ + m_values[left] = pivotVal; \ + if (l_hold < left) \ + q_sort(l_hold, left - 1); \ + if (r_hold > left) \ + q_sort(left + 1, r_hold); \ + } // ---------------------------------------------------------------------------- -#define DEFINE_PAIRED_INT_DATA_ARRAYS(Tval, name) \ -DEFINE_PAIRED_DATA_ARRAYS(int, Tval, name) \ -bool name::UpdatePos( int pos, int numPos ) \ -{ \ - int n, count = m_keys.GetCount(), start_pos = FindInsertIndex(pos); \ - if ((numPos == 0) || (start_pos >= count)) return false; \ - if ( numPos > 0 ) \ - { \ - for (n=start_pos; n= pos_right) { k += numPos; } \ - } \ - } \ - return true; \ -} +#define DEFINE_PAIRED_INT_DATA_ARRAYS(Tval, name) \ + DEFINE_PAIRED_DATA_ARRAYS(int, Tval, name) \ + bool name::UpdatePos(int pos, int numPos) \ + { \ + int n, count = m_keys.GetCount(), start_pos = FindInsertIndex(pos); \ + if ((numPos == 0) || (start_pos >= count)) \ + return false; \ + if (numPos > 0) { \ + for (n = start_pos; n < count; n++) \ + m_keys[n] += numPos; \ + } \ + else if (numPos < 0) { \ + int pos_right = pos - numPos; \ + for (n = start_pos; n < count; n++) { \ + int &k = m_keys[n]; \ + if (k < pos_right) { \ + RemoveAt(n); \ + n--; \ + count--; \ + } \ + else if (k >= pos_right) { \ + k += numPos; \ + } \ + } \ + } \ + return true; \ + } -#endif // __WX_PAIRARR_H__ +#endif // __WX_PAIRARR_H__ diff --git a/src/labenski/include/wx/sheet/sheet.h b/src/labenski/include/wx/sheet/sheet.h index 3dce8a0cc..97ba94120 100644 --- a/src/labenski/include/wx/sheet/sheet.h +++ b/src/labenski/include/wx/sheet/sheet.h @@ -29,31 +29,30 @@ class /* WXDLLEXPORT */ wxTimerEvent; // ---------------------------------------------------------------------------- // wxSheetChildWindow - a child window of the wxSheet, forwards events to sheet // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetChildWindow : public wxWindow -{ +class WXDLLIMPEXP_SHEET wxSheetChildWindow : public wxWindow { public: - wxSheetChildWindow( wxSheet *parent, wxWindowID id = wxID_ANY, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - long style = wxWANTS_CHARS|wxBORDER_NONE|wxCLIP_CHILDREN, //|wxFULL_REPAINT_ON_RESIZE ) // FIXME - const wxString& name = wxT("wxSheetChildWindow") ); + wxSheetChildWindow(wxSheet *parent, wxWindowID id = wxID_ANY, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + long style = wxWANTS_CHARS | wxBORDER_NONE | + wxCLIP_CHILDREN, //|wxFULL_REPAINT_ON_RESIZE ) // FIXME + const wxString &name = wxT("wxSheetChildWindow")); - // implementation - void OnPaint( wxPaintEvent& event ); - void OnMouse( wxMouseEvent& event ); - void OnKeyAndChar( wxKeyEvent& event ); - void OnFocus( wxFocusEvent& event ); - void OnEraseBackground( wxEraseEvent& ); + // implementation + void OnPaint(wxPaintEvent &event); + void OnMouse(wxMouseEvent &event); + void OnKeyAndChar(wxKeyEvent &event); + void OnFocus(wxFocusEvent &event); + void OnEraseBackground(wxEraseEvent &); - wxSheet* GetOwner() const { return m_owner; } + wxSheet *GetOwner() const { return m_owner; } - wxSheet *m_owner; - int m_mouseCursor; // remember the last cursor set for this window + wxSheet *m_owner; + int m_mouseCursor; // remember the last cursor set for this window private: - DECLARE_ABSTRACT_CLASS(wxSheetChildWindow) - DECLARE_EVENT_TABLE() - DECLARE_NO_COPY_CLASS(wxSheetChildWindow) + DECLARE_ABSTRACT_CLASS(wxSheetChildWindow) + DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxSheetChildWindow) }; //----------------------------------------------------------------------------- @@ -70,1292 +69,1536 @@ class WXDLLIMPEXP_SHEET wxSheetChildWindow : public wxWindow // subclassed refdata then in your wxSheet constructor (or Create) function call // UnRef to delete the original and m_refData=new MySheetRefData to set the new. //----------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetRefData : public wxObjectRefData -{ +class WXDLLIMPEXP_SHEET wxSheetRefData : public wxObjectRefData { public: - wxSheetRefData(); - virtual ~wxSheetRefData(); - // Find/Add/Remove sheets that share this data - used for wxSheetSplitter - int FindSheet(wxSheet* sheet) const; - bool HasSheet(wxSheet* sheet) const { return FindSheet(sheet) != wxNOT_FOUND; } - void AddSheet(wxSheet* sheet); - void RemoveSheet(wxSheet* sheet); - wxSheet *GetSheet(size_t n) const { return (wxSheet*)m_sheets.Item(n); } - size_t GetSheetCount() const { return m_sheets.GetCount(); } + wxSheetRefData(); + virtual ~wxSheetRefData(); + // Find/Add/Remove sheets that share this data - used for wxSheetSplitter + int FindSheet(wxSheet *sheet) const; + bool HasSheet(wxSheet *sheet) const { return FindSheet(sheet) != wxNOT_FOUND; } + void AddSheet(wxSheet *sheet); + void RemoveSheet(wxSheet *sheet); + wxSheet *GetSheet(size_t n) const { return (wxSheet *)m_sheets.Item(n); } + size_t GetSheetCount() const { return m_sheets.GetCount(); } - // implementation --------------------------------------------------------- + // implementation --------------------------------------------------------- - wxArrayPtrVoid m_sheets; // list of sheets sharing this data + wxArrayPtrVoid m_sheets; // list of sheets sharing this data - wxSheetTable *m_table; // the table that stores the values - bool m_ownTable; + wxSheetTable *m_table; // the table that stores the values + bool m_ownTable; - wxSheetTypeRegistry* m_typeRegistry; // editor/renderer registry + wxSheetTypeRegistry *m_typeRegistry; // editor/renderer registry - wxSheetArrayEdge m_rowEdges; // calculates edge positions and - wxSheetArrayEdge m_colEdges; // stores num rows/cols + wxSheetArrayEdge m_rowEdges; // calculates edge positions and + wxSheetArrayEdge m_colEdges; // stores num rows/cols - // width of row labels and height of col labels - int m_rowLabelWidth; - int m_colLabelHeight; + // width of row labels and height of col labels + int m_rowLabelWidth; + int m_colLabelHeight; - // the size of the margin to the right and bottom of the cell area - wxSize m_marginSize; + // the size of the margin to the right and bottom of the cell area + wxSize m_marginSize; - int m_equal_col_widths; + int m_equal_col_widths; - wxColour m_gridLineColour; - int m_gridLinesEnabled; - wxColour m_cursorCellHighlightColour; - int m_cursorCellHighlightPenWidth; - int m_cursorCellHighlightROPenWidth; - wxColour m_labelOutlineColour; + wxColour m_gridLineColour; + int m_gridLinesEnabled; + wxColour m_cursorCellHighlightColour; + int m_cursorCellHighlightPenWidth; + int m_cursorCellHighlightROPenWidth; + wxColour m_labelOutlineColour; - wxCursor m_rowResizeCursor; - wxCursor m_colResizeCursor; + wxCursor m_rowResizeCursor; + wxCursor m_colResizeCursor; - bool m_editable; // applies to whole grid - brute force readonly + bool m_editable; // applies to whole grid - brute force readonly - int m_canDrag; // enum wxSheetDragCellSize_Type + int m_canDrag; // enum wxSheetDragCellSize_Type - wxSheetCoords m_cursorCoords; + wxSheetCoords m_cursorCoords; - wxSheetBlock m_selectingBlock; // during selection !Empty - wxSheetCoords m_selectingAnchor; // corner of active selection, other is usually cursor - wxSheetSelection* m_selection; - int m_selectionMode; // wxSheetSelectionMode_Type - wxColour m_selectionBackground; - wxColour m_selectionForeground; + wxSheetBlock m_selectingBlock; // during selection !Empty + wxSheetCoords m_selectingAnchor; // corner of active selection, other is usually cursor + wxSheetSelection *m_selection; + int m_selectionMode; // wxSheetSelectionMode_Type + wxColour m_selectionBackground; + wxColour m_selectionForeground; - // the default cell attr objects for cells that don't have their own - wxSheetCellAttr m_defaultGridCellAttr; - wxSheetCellAttr m_defaultRowLabelAttr; - wxSheetCellAttr m_defaultColLabelAttr; - wxSheetCellAttr m_defaultCornerLabelAttr; + // the default cell attr objects for cells that don't have their own + wxSheetCellAttr m_defaultGridCellAttr; + wxSheetCellAttr m_defaultRowLabelAttr; + wxSheetCellAttr m_defaultColLabelAttr; + wxSheetCellAttr m_defaultCornerLabelAttr; - wxSheetCellEditor m_cellEditor; // valid only when editing - wxSheetCoords m_cellEditorCoords; + wxSheetCellEditor m_cellEditor; // valid only when editing + wxSheetCoords m_cellEditorCoords; - wxSheetValueProviderSparseString m_copiedData; - bool m_pasting; + wxSheetValueProviderSparseString m_copiedData; + bool m_pasting; }; // ---------------------------------------------------------------------------- // wxSheet // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheet : public wxWindow -{ +class WXDLLIMPEXP_SHEET wxSheet : public wxWindow { public: - wxSheet() : wxWindow(), m_gridWin(NULL) { Init(); } - - wxSheet( wxWindow *parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxWANTS_CHARS, - const wxString& name = wxT("wxSheet") ) : wxWindow(), m_gridWin(NULL) - { - Init(); - Create(parent, id, pos, size, style, name); + wxSheet() : wxWindow(), m_gridWin(NULL) { Init(); } + + wxSheet(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, long style = wxWANTS_CHARS, + const wxString &name = wxT("wxSheet")) + : wxWindow(), m_gridWin(NULL) + { + Init(); + Create(parent, id, pos, size, style, name); + } + + bool Create(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, long style = wxWANTS_CHARS, + const wxString &name = wxT("wxSheet")); + + virtual ~wxSheet(); + virtual bool Destroy(); + + // ref another wxSheet's ref data - see usage in wxSheetSplitter + void RefSheet(wxSheet *otherSheet); + // Create a new wxSheet with same parent, used for wxSheetSplitter. + // override this so that the top left sheet in the splitter can return + // a "new MySheet" for the other sheets as necessary + // This is one of the few ways for the splitter to create new sheets. + virtual wxSheet *Clone(wxWindowID id = wxID_ANY); + + // override wxWindow::Enable to ensure proper refresh + virtual bool Enable(bool enable = true); + + // ------------------------------------------------------------------------ + // Create/Set/Get wxSheetTable - the underlying data to be displayed + + wxSheetTable *GetTable() const { return GetSheetRefData()->m_table; } + // Set your own table derived from wxSheetTable, if takeOwnership the + // the table will be deleted when this window is destroyed + bool SetTable(wxSheetTable *table, bool takeOwnership); + + // Create a wxSheetTable using string data containers to use + // see this function to see how to setup the table and use SetTable + // for the case where you want to customize things + // This function exists to show how to create and assign tables + bool CreateGrid(int numRows, int numCols, int options = 0); + + // ------------------------------------------------------------------------ + // Dimensions of the number of cells on the sheet and helper cell functions + + int GetNumberRows() const { return GetSheetRefData()->m_rowEdges.GetCount(); } + int GetNumberCols() const { return GetSheetRefData()->m_colEdges.GetCount(); } + + // Is the coords anywhere in labels or grid, -1 to GetNumberRows/Cols()-1 + bool ContainsCell(const wxSheetCoords &coords) const + { + return (coords.m_row >= -1) && (coords.m_col >= -1) && (coords.m_row < GetNumberRows()) && + (coords.m_col < GetNumberCols()); + } + + // returns true if the coords are within the grid cells of the sheet + bool ContainsGridRow(int row) const { return (row >= 0) && (row < GetNumberRows()); } + bool ContainsGridCol(int col) const { return (col >= 0) && (col < GetNumberCols()); } + bool ContainsGridCell(const wxSheetCoords &coords) const + { + return ContainsGridRow(coords.m_row) && ContainsGridCol(coords.m_col); + } + + // returns true if the coords are within the row/col label cells + bool ContainsRowLabelCell(const wxSheetCoords &coords) const + { + return (coords.m_col == -1) && ContainsGridRow(coords.m_row); + } + bool ContainsColLabelCell(const wxSheetCoords &coords) const + { + return (coords.m_row == -1) && ContainsGridCol(coords.m_col); + } + + // static helper functions to determine what type of cell it is, not check validity + + static bool IsGridCell(const wxSheetCoords &coords) + { + return (coords.m_row >= 0) && (coords.m_col >= 0); + } + static bool IsLabelCell(const wxSheetCoords &coords) + { + return (coords.m_row >= -1) && (coords.m_col >= -1) && + ((coords.m_row == -1) || (coords.m_col == -1)); + } + static bool IsRowLabelCell(const wxSheetCoords &coords) + { + return (coords.m_row >= 0) && (coords.m_col == -1); + } + static bool IsColLabelCell(const wxSheetCoords &coords) + { + return (coords.m_row == -1) && (coords.m_col >= 0); + } + static bool IsCornerLabelCell(const wxSheetCoords &coords) + { + return (coords.m_row == -1) && (coords.m_col == -1); + } + + // Get an enum value of what window the coords are meant for + static wxSheetCell_Type GetCellCoordsType(const wxSheetCoords &coords); + + // "clear" the contents of the grid (depends on table's Clear() function) + // the string implementations clear the cell values, not the # rows/cols + void ClearValues(int update = wxSHEET_UpdateValues); + + // Insert/Add/DeleteRows/Cols to the grid cells + // update contains or'ed values of enum wxSheetUpdate_Type. + // you proabably want UpdateAll unless you ensure that no problems will occur + // or you will update some other way + bool InsertRows(size_t row, size_t numRows, int update = wxSHEET_UpdateAll) + { + return UpdateRows(row, numRows, update); + } + bool AppendRows(size_t numRows, int update = wxSHEET_UpdateAll) + { + return UpdateRows(GetNumberRows(), numRows, update); + } + bool DeleteRows(size_t row, size_t numRows, int update = wxSHEET_UpdateAll) + { + return UpdateRows(row, -int(numRows), update); + } + + bool InsertCols(size_t col, size_t numCols, int update = wxSHEET_UpdateAll) + { + return UpdateCols(col, numCols, update); + } + bool AppendCols(size_t numCols, int update = wxSHEET_UpdateAll) + { + return UpdateCols(GetNumberCols(), numCols, update); + } + bool DeleteCols(size_t col, size_t numCols, int update = wxSHEET_UpdateAll) + { + return UpdateCols(col, -int(numCols), update); + } + + // Set exactly the number of rows or cols, these functions Append or + // Delete rows/cols to/from the end. If you are setting attributes for + // particular cells/rows/cols you probably won't want to use these + bool SetNumberRows(size_t rows, int update = wxSHEET_UpdateAll); + bool SetNumberCols(size_t cols, int update = wxSHEET_UpdateAll); + bool SetNumberCells(size_t rows, size_t cols, int update = wxSHEET_UpdateAll) + { + return SetNumberRows(rows, update) || SetNumberCols(cols, update); + } + + // Inserting/Appending/Deleting rows/cols functions are forwarded here + // and then sent to the wxSheetTable::UpdateRows/Cols functions + // numRows/Cols > 0 : InsertRows/Cols at row/col else if < 0 delete + // row/col == GetNumberRows/Cols && numRows/Cols > 0 to append to end + virtual bool UpdateRows(size_t row, int numRows, int update = wxSHEET_UpdateAll); + virtual bool UpdateCols(size_t col, int numCols, int update = wxSHEET_UpdateAll); + + // ------------------------------------------------------------------------ + // Dimensions of the row and column sizes + + // Get/Set the default height/width of newly created rows/cols + // if resizeExisting then resize all to match the newly set default + int GetDefaultRowHeight() const { return GetSheetRefData()->m_rowEdges.GetDefaultSize(); } + int GetDefaultColWidth() const { return GetSheetRefData()->m_colEdges.GetDefaultSize(); } + void SetDefaultRowHeight(int height, bool resizeExistingRows = false); + void SetDefaultColWidth(int width, bool resizeExistingCols = false); + + // Get/Set the absolute min row/col width/height, 0 for no min size + // Call during grid creation, existing rows/cols are not resized + // This value is used when dragging cell size with the mouse if no + // particular min size for a row/col has been set + int GetMinimalAcceptableRowHeight() const + { + return GetSheetRefData()->m_rowEdges.GetMinAllowedSize(); + } + int GetMinimalAcceptableColWidth() const + { + return GetSheetRefData()->m_colEdges.GetMinAllowedSize(); + } + void SetMinimalAcceptableRowHeight(int height) + { + GetSheetRefData()->m_rowEdges.SetMinAllowedSize(height); + } + void SetMinimalAcceptableColWidth(int width) + { + GetSheetRefData()->m_colEdges.SetMinAllowedSize(width); + } + + // Don't allow specific rows/cols to be resized smaller than this + // Call during grid creation, existing rows/cols are not resized + // The setting is cleared to default val if width/height is < min acceptable + int GetMinimalRowHeight(int row) const { return GetSheetRefData()->m_rowEdges.GetMinSize(row); } + int GetMinimalColWidth(int col) const { return GetSheetRefData()->m_colEdges.GetMinSize(col); } + void SetMinimalRowHeight(int row, int height) + { + GetSheetRefData()->m_rowEdges.SetMinSize(row, height); + } + void SetMinimalColWidth(int col, int width) + { + GetSheetRefData()->m_colEdges.SetMinSize(col, width); + } + + // Set the height of a row or width of a col, -1 notation for labels + // use height/width = -1 to autosize from the row/col labels + void SetRowHeight(int row, int height); + void SetColWidth(int col, int width); + + // Get the height/top/bottom for rows, uses -1 notation + int GetRowHeight(int row) const; + int GetRowTop(int row) const; + int GetRowBottom(int row) const; + // Get the width/left/right for cols, uses -1 notation + int GetColWidth(int col) const; + int GetColLeft(int col) const; + int GetColRight(int col) const; + // Get the width, height of a cell as a wxSize, -1 notation + // this does not include spanned cells + wxSize GetCellSize(const wxSheetCoords &coords) const; + + // does the cell have a non-zero width and height, may not be visible, -1 notation + bool IsCellShown(const wxSheetCoords &coords) const; + + // grid may occupy more space than needed for its rows/columns, this + // function allows to set how big this margin space is + void SetMargins(int width, int height) + { + GetSheetRefData()->m_marginSize.x = wxMax(0, width); + GetSheetRefData()->m_marginSize.y = wxMax(0, height); + } + + // Get the renderer's best size for the cell, uses -1 notation + wxSize GetCellBestSize(const wxSheetCoords &coords, wxDC *dc = NULL) const; + // Get the best height of a row or the best width of a col using the + // renderer's best size + int GetRowBestHeight(int row) const; + int GetColBestWidth(int col) const; + + // ------------------------------------------------------------------------ + // Row/Col label size + + // Get the fixed initial size of the width of row labels or height of col labels + int GetDefaultRowLabelWidth() const { return WXSHEET_DEFAULT_ROW_LABEL_WIDTH; } + int GetDefaultColLabelHeight() const { return WXSHEET_DEFAULT_COL_LABEL_HEIGHT; } + + // Get/Set the row/col label widths, + // if zero_not_shown and row/col & corner not shown return 0 + int GetRowLabelWidth(bool zero_not_shown = true) const; + int GetColLabelHeight(bool zero_not_shown = true) const; + void SetRowLabelWidth(int width); + void SetColLabelHeight(int height); + + // ------------------------------------------------------------------------ + // Auto sizing of the row/col widths/heights + + // automatically size the col/row to fit to its contents, if setAsMin, + // this optimal width will also be set as minimal width for this column + // returns the width or height used. + int AutoSizeRow(int row, bool setAsMin = true); + int AutoSizeCol(int col, bool setAsMin = true); + + // auto size all columns (very ineffective for big grids!) + void AutoSizeRows(bool setAsMin = true); + void AutoSizeCols(bool setAsMin = true); + + // auto size the grid, that is make the columns/rows of the "right" size + // and also set the grid size to just fit its contents + void AutoSize(bool setAsMin = true); + + // autosize row height depending on label text + void AutoSizeRowLabelHeight(int row); + // autosize column width depending on label text + void AutoSizeColLabelWidth(int col); + + // Force the col widths to be of equal size so that they fit within the + // the window size. This is maintained even when the window is resized. + // The col widths will not be sized less than min_width in pixels. + // Use this if you know that the window will be of a reasonable size to + // fit the cols, but you don't want to track the EVT_SIZE yourself. + // use a min_width <= 0 to turn it off + void SetEqualColWidths(int min_width); + + // ------------------------------------------------------------------------ + // Row/Col drag resizing enabled or disabled + // + // if CanDragRow/ColSize the rows/cols can be resized by the mouse + // if CanDragGridSize you can resize the rows/cols in the grid window + // else you resize in the label windows (if CanDragRow/ColSize is true) + + void EnableDragRowSize(bool enable = true) + { + SetDragCellSize(wxSHEET_DragLabelRowHeight, enable); + } + void EnableDragColSize(bool enable = true) + { + SetDragCellSize(wxSHEET_DragLabelColWidth, enable); + } + void EnableDragGridSize(bool enable = true) + { + SetDragCellSize(wxSHEET_DragGridCellSize, enable); + } + void DisableDragRowSize() { EnableDragRowSize(false); } + void DisableDragColSize() { EnableDragColSize(false); } + void DisableDragGridSize() { EnableDragGridSize(false); } + bool CanDragRowSize() const { return (GetDragCellSize() & wxSHEET_DragLabelRowHeight) != 0; } + bool CanDragColSize() const { return (GetDragCellSize() & wxSHEET_DragLabelColWidth) != 0; } + bool CanDragGridSize() const { return (GetDragCellSize() & wxSHEET_DragGridCellSize) != 0; } + + // Directly set the dragging of the cell size use wxSheetDragCellSize_Type enums + void SetDragCellSize(int type) { GetSheetRefData()->m_canDrag = type; } + void SetDragCellSize(int type, bool enable) + { + SetDragCellSize(enable ? (GetDragCellSize() | type) : (GetDragCellSize() & (~type))); + } + int GetDragCellSize() const { return GetSheetRefData()->m_canDrag; } + + // ------------------------------------------------------------------------ + // Grid line, cell highlight, selection colouring + + // Draw the grid lines, wxHORIZONAL | wxVERTICAL (wxBOTH), 0 for none + void EnableGridLines(int dir = wxBOTH); + int GridLinesEnabled() const { return GetSheetRefData()->m_gridLinesEnabled; } + + const wxColour &GetGridLineColour() const { return GetSheetRefData()->m_gridLineColour; } + void SetGridLineColour(const wxColour &colour); + + const wxColour &GetCursorCellHighlightColour() const + { + return GetSheetRefData()->m_cursorCellHighlightColour; + } + int GetCursorCellHighlightPenWidth() const + { + return GetSheetRefData()->m_cursorCellHighlightPenWidth; + } + int GetCursorCellHighlightROPenWidth() const + { + return GetSheetRefData()->m_cursorCellHighlightROPenWidth; + } + void SetCursorCellHighlightColour(const wxColour &colour); + void SetCursorCellHighlightPenWidth(int width); + void SetCursorCellHighlightROPenWidth(int width); + + // get/set the colour bounding the labels to give 3-D effect + const wxColour &GetLabelOutlineColour() const { return GetSheetRefData()->m_labelOutlineColour; } + void SetLabelOutlineColour(const wxColour &colour); + + const wxColour &GetSelectionBackground() const + { + return GetSheetRefData()->m_selectionBackground; + } + const wxColour &GetSelectionForeground() const + { + return GetSheetRefData()->m_selectionForeground; + } + void SetSelectionBackground(const wxColour &c) { GetSheetRefData()->m_selectionBackground = c; } + void SetSelectionForeground(const wxColour &c) { GetSheetRefData()->m_selectionForeground = c; } + + // ------------------------------------------------------------------------ + // Span, cells can span across multiple cells, hiding cells below + // + // Normally cells are of size 1x1, but they can be larger. + // The other cells can still have values and attributes, but they + // will not be used since GetCellOwner is used for most coord operations + // so that the underlying cell values and attributes are ignored. + // The span for the owner cell is 1x1 or larger, the span for other + // cells contained within the spanned block have a cell span of <= 0, such + // that coords + GetCellSpan() = the owner cell + // + // You can completely override this functionality if you provide + // HasSpannedCells, GetCellBlock, SetCellSpan + + // Are there any spanned cells at all? + virtual bool HasSpannedCells() const; + + // if cell is part of a spanning cell, return owner's coords else input coords + wxSheetCoords GetCellOwner(const wxSheetCoords &coords) const; + // Get a block of the cell, unless a spanned cell it's of size 1,1 + // note: the top left of block is the owner cell of coords + virtual wxSheetBlock GetCellBlock(const wxSheetCoords &coords) const; + // Get the span of a cell, the owner (top right) cell always has a span of + // (1, 1) or greater. The other cells in a spanned block will have a span + // (<1, <1) such that, coords + coordsSpan = ownerCoords + wxSheetCoords GetCellSpan(const wxSheetCoords &coords) const; + // Set the span of a cell, must be 1x1 or greater, + // To remove a spanned cell set it to a cell of size 1x1 + // For grid cells the whole block must be contained within the grid cells + // and if the block intersects a previously spanned cell block the top left + // corners must match up. + // Row and Col labels can span cells as well, spanned row labels must have a + // width of 1 and a height of >= 1, col labels a height of 1 and width >= 1 + virtual void SetCellSpan(const wxSheetBlock &block); + void SetCellSpan(const wxSheetCoords &coords, const wxSheetCoords &numRowsCols) + { + SetCellSpan(wxSheetBlock(coords, numRowsCols.m_row, numRowsCols.m_col)); + } + + // Get a pointer to the spanned blocks to iterate through, may return NULL. + const wxSheetSelection *GetSpannedBlocks() const + { + return GetTable() ? GetTable()->GetSpannedBlocks() : NULL; + } + // ------------------------------------------------------------------------ + // Get/Set attributes for the cells, row, col, corner labels + + // See wxSheetAttr_Type for a description of the type of attribute + + // The coords are specified as + // The Grid area (0 <= row < GetNumberRows), (0 <= col < GetNumberCols) + // The Corner window row = col = -1 + // The Row labels (0 <= row < GetNumberRows), col = -1 + // The Col labels row = -1, (0 <= col < GetNumberCols) + + // For the wxSHEET_AttrDefault type the coords should be contained within the + // size of the sheet, but the particular values are not used. + // see const wxGridCellSheetCoords = (0,0) for example + // wxRowLabelSheetCoords, wxColLabelSheetCoords, wxCornerLabelSheetCoords + + // To completely override this you may provide alternate + // GetOrCreateAttr, GetAttr, and SetAttr functions. + + // make sure that the last default attr of initAttr is defAttr + // This is called internally when you call SetAttr + bool InitAttr(wxSheetCellAttr &initAttr, const wxSheetCellAttr &defAttr) const; + + // Get an attribute for the coords if it exists or create a new one + // and put it into the table which puts it in the attr provider. + // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col for the grid cells + // and wxSHEET_AttrDefault/Cell for the labels + virtual wxSheetCellAttr GetOrCreateAttr(const wxSheetCoords &coords, + wxSheetAttr_Type type) const; + + // Get the attribute for any area depending on the coords and type + // returns a valid attr if the coords are valid and type = wxSHEET_AttrAny + // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col/Any for the grid cells + // and wxSHEET_AttrDefault/Cell/Any for the labels + virtual wxSheetCellAttr GetAttr(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + // Set the attribute for any area depending on the coords + // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col for the grid cells + // and wxSHEET_AttrDefault/Cell for the labels + virtual void SetAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr, + wxSheetAttr_Type type); + + // ------ Simplified functions for accessing the attributes --------------- + // Get an attribute for the grid coords, returning a cell/row/col attr or + // if multiple attr for the coords an attr that's merged, or the def attr + wxSheetCellAttr GetGridAttr(const wxSheetCoords &coords) const + { + return GetAttr(coords, wxSHEET_AttrAny); + } + + // Get a specific Cell/Row/Col attr for the coords in the grid + // if none set returns wxNullSheetCellAttr + wxSheetCellAttr GetGridCellAttr(const wxSheetCoords &coords) const + { + return GetAttr(coords, wxSHEET_AttrCell); + } + wxSheetCellAttr GetGridRowAttr(int row) const + { + return GetAttr(wxSheetCoords(row, 0), wxSHEET_AttrRow); + } + wxSheetCellAttr GetGridColAttr(int col) const + { + return GetAttr(wxSheetCoords(0, col), wxSHEET_AttrCol); + } + // Set a specific Cell/Row/Col attr for coords, row/col only apply to the grid + void SetGridCellAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr) + { + SetAttr(coords, attr, wxSHEET_AttrCell); + } + void SetGridRowAttr(int row, const wxSheetCellAttr &attr) + { + SetAttr(wxSheetCoords(row, 0), attr, wxSHEET_AttrRow); + } + void SetGridColAttr(int col, const wxSheetCellAttr &attr) + { + SetAttr(wxSheetCoords(0, col), attr, wxSHEET_AttrCol); + } + + // Get the row/col/corner label attributes, if one is not set for the + // particular coords, returns the default one. (note: only one corner attr) + // if you want the particular attr use GetRow/ColLabelCellAttr + wxSheetCellAttr GetRowLabelAttr(int row) const + { + return GetAttr(wxSheetCoords(row, -1), wxSHEET_AttrAny); + } + wxSheetCellAttr GetColLabelAttr(int col) const + { + return GetAttr(wxSheetCoords(-1, col), wxSHEET_AttrAny); + } + wxSheetCellAttr GetCornerLabelAttr() const + { + return GetAttr(wxSheetCoords(-1, -1), wxSHEET_AttrAny); + } + + // Get a specific attr the row/col/corner label cell + // if none set returns wxNullSheetCellAttr + wxSheetCellAttr GetRowLabelCellAttr(int row) const + { + return GetAttr(wxSheetCoords(row, -1), wxSHEET_AttrCell); + } + wxSheetCellAttr GetColLabelCellAttr(int col) const + { + return GetAttr(wxSheetCoords(-1, col), wxSHEET_AttrCell); + } + // Set a specific attribute for particular row/col/corner label cell + void SetRowLabelCellAttr(int row, const wxSheetCellAttr &attr) + { + SetAttr(wxSheetCoords(row, -1), attr, wxSHEET_AttrCell); + } + void SetColLabelCellAttr(int col, const wxSheetCellAttr &attr) + { + SetAttr(wxSheetCoords(-1, col), attr, wxSHEET_AttrCell); + } + void SetCornerLabelAttr(const wxSheetCellAttr &attr) + { + SetAttr(wxSheetCoords(-1, -1), attr, wxSHEET_AttrCell); + } + + // Get/Set default attributes for the areas (only one corner attr) + // For setting, wxSheetCellAttr::UpdateWith is called with the current default + // attr so you so need only set the values that you want to change. + wxSheetCellAttr GetDefaultAttr(const wxSheetCoords &coords) const + { + return GetAttr(coords, wxSHEET_AttrDefault); + } + wxSheetCellAttr GetDefaultGridCellAttr() const + { + return GetAttr(wxGridCellSheetCoords, wxSHEET_AttrDefault); + } + wxSheetCellAttr GetDefaultRowLabelAttr() const + { + return GetAttr(wxRowLabelSheetCoords, wxSHEET_AttrDefault); + } + wxSheetCellAttr GetDefaultColLabelAttr() const + { + return GetAttr(wxColLabelSheetCoords, wxSHEET_AttrDefault); + } + void SetDefaultAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr) + { + SetAttr(coords, attr, wxSHEET_AttrDefault); + } + void SetDefaultGridCellAttr(const wxSheetCellAttr &attr) + { + SetAttr(wxGridCellSheetCoords, attr, wxSHEET_AttrDefault); + } + void SetDefaultRowLabelAttr(const wxSheetCellAttr &attr) + { + SetAttr(wxRowLabelSheetCoords, attr, wxSHEET_AttrDefault); + } + void SetDefaultColLabelAttr(const wxSheetCellAttr &attr) + { + SetAttr(wxColLabelSheetCoords, attr, wxSHEET_AttrDefault); + } + + // These are convienience functions, if for example you want to subclass the + // table and modify and return default attr "on the fly" for each cell + const wxSheetCellAttr &DoGetDefaultGridAttr() const + { + return GetSheetRefData()->m_defaultGridCellAttr; + } + const wxSheetCellAttr &DoGetDefaultRowLabelAttr() const + { + return GetSheetRefData()->m_defaultRowLabelAttr; + } + const wxSheetCellAttr &DoGetDefaultColLabelAttr() const + { + return GetSheetRefData()->m_defaultColLabelAttr; + } + const wxSheetCellAttr &DoGetDefaultCornerLabelAttr() const + { + return GetSheetRefData()->m_defaultCornerLabelAttr; + } + + // Get/Set particular attributes for any type of cell/row/col anywhere + // The default is to get the attr val for type=wxSHEET_AttrAny meaning that + // it'll find a set attr first or return the default attr value as a last resort. + // For GetXXX you will receive an an error message if you specify a + // particular wxSHEET_AttrCell/Row/Col, but there isn't an attribute set + const wxColour &GetAttrBackgroundColour(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + const wxColour &GetAttrForegoundColour(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + const wxFont &GetAttrFont(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + int GetAttrAlignment(const wxSheetCoords &coords, wxSheetAttr_Type type = wxSHEET_AttrAny) const; + int GetAttrOrientation(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + int GetAttrLevel(const wxSheetCoords &coords, wxSheetAttr_Type type = wxSHEET_AttrAny) const; + bool GetAttrOverflow(const wxSheetCoords &coords, wxSheetAttr_Type type = wxSHEET_AttrAny) const; + bool GetAttrOverflowMarker(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + bool GetAttrShowEditor(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + bool GetAttrReadOnly(const wxSheetCoords &coords, wxSheetAttr_Type type = wxSHEET_AttrAny) const; + wxSheetCellRenderer GetAttrRenderer(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + wxSheetCellEditor GetAttrEditor(const wxSheetCoords &coords, + wxSheetAttr_Type type = wxSHEET_AttrAny) const; + + // Set attributes for a particular cell/row/col, relies on GetOrCreateAttr() + // so it creates and adds the attr to the attr provider if there wasn't one + // after setting the particular value. + // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col + void SetAttrBackgroundColour(const wxSheetCoords &coords, const wxColour &colour, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrForegroundColour(const wxSheetCoords &coords, const wxColour &colour, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrFont(const wxSheetCoords &coords, const wxFont &font, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrAlignment(const wxSheetCoords &coords, int align, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrOrientation(const wxSheetCoords &coords, int orientation, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrLevel(const wxSheetCoords &coords, int level, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrOverflow(const wxSheetCoords &coords, bool allow, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrOverflowMarker(const wxSheetCoords &coords, bool draw_marker, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrShowEditor(const wxSheetCoords &coords, bool show_editor, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrReadOnly(const wxSheetCoords &coords, bool isReadOnly, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrRenderer(const wxSheetCoords &coords, const wxSheetCellRenderer &renderer, + wxSheetAttr_Type type = wxSHEET_AttrCell); + void SetAttrEditor(const wxSheetCoords &coords, const wxSheetCellEditor &editor, + wxSheetAttr_Type type = wxSHEET_AttrCell); + + // helper functions that use SetColAttr to set renderer type + // set the format for the data in the column: default is string + void SetColFormatBool(int col) { SetColFormatCustom(col, wxSHEET_VALUE_BOOL); } + void SetColFormatNumber(int col) { SetColFormatCustom(col, wxSHEET_VALUE_NUMBER); } + void SetColFormatFloat(int col, int width = -1, int precision = -1); + void SetColFormatCustom(int col, const wxString &typeName); + + // ------------------------------------------------------------------------ + // Get/Set cell, row, col, and corner label values + // To completely override this you need only provide Get/SetCellValue + + // Get/Set cell value, uses coords = -1 notation for row/col/corner labels + virtual wxString GetCellValue(const wxSheetCoords &coords); + virtual void SetCellValue(const wxSheetCoords &coords, const wxString &value); + + // Is this cell empty, see wxSheetTable + virtual bool HasCellValue(const wxSheetCoords &coords); + + wxString GetRowLabelValue(int row) { return GetCellValue(wxSheetCoords(row, -1)); } + wxString GetColLabelValue(int col) { return GetCellValue(wxSheetCoords(-1, col)); } + void SetRowLabelValue(int row, const wxString &value) + { + SetCellValue(wxSheetCoords(row, -1), value); + } + void SetColLabelValue(int col, const wxString &value) + { + SetCellValue(wxSheetCoords(-1, col), value); + } + + wxString GetCornerLabelValue() { return GetCellValue(wxSheetCoords(-1, -1)); } + void SetCornerLabelValue(const wxString &value) { SetCellValue(wxSheetCoords(-1, -1), value); } + + // ------------------------------------------------------------------------ + // Register mapping between data types to Renderers/Editors + + void RegisterDataType(const wxString &typeName, const wxSheetCellRenderer &renderer, + const wxSheetCellEditor &editor); + + virtual wxSheetCellEditor GetDefaultEditorForType(const wxString &typeName) const; + virtual wxSheetCellRenderer GetDefaultRendererForType(const wxString &typeName) const; + + // FIXME what is the point of these? + virtual wxSheetCellEditor GetDefaultEditorForCell(const wxSheetCoords &coords) const; + virtual wxSheetCellRenderer GetDefaultRendererForCell(const wxSheetCoords &coords) const; + + // ------------------------------------------------------------------------ + // Cursor movement and visibility functions + + // check to see if a cell is either wholly visible (the default arg) or + // at least partially visible, uses -1 notation for labels + bool IsCellVisible(const wxSheetCoords &coords, bool wholeCellVisible = true) const; + bool IsRowVisible(int row, bool wholeRowVisible = true) const; + bool IsColVisible(int col, bool wholeColVisible = true) const; + // Make this cell visible, uses -1 notation, will not unhide label windows + void MakeCellVisible(const wxSheetCoords &coords); + + // Get/Set cursor cell, this is the "current" cell where a highlight is drawn + // the cursor only applies to the grid cells + const wxSheetCoords &GetGridCursorCell() const { return GetSheetRefData()->m_cursorCoords; } + int GetGridCursorRow() const { return GetGridCursorCell().GetRow(); } + int GetGridCursorCol() const { return GetGridCursorCell().GetCol(); } + void SetGridCursorCell(const wxSheetCoords &coords); + + bool MoveCursorUp(bool expandSelection) + { + return DoMoveCursor(wxSheetCoords(-1, 0), expandSelection); + } + bool MoveCursorDown(bool expandSelection) + { + return DoMoveCursor(wxSheetCoords(1, 0), expandSelection); + } + bool MoveCursorLeft(bool expandSelection) + { + return DoMoveCursor(wxSheetCoords(0, -1), expandSelection); + } + bool MoveCursorRight(bool expandSelection) + { + return DoMoveCursor(wxSheetCoords(0, 1), expandSelection); + } + bool MoveCursorUpBlock(bool expandSelection) + { + return DoMoveCursorBlock(wxSheetCoords(-1, 0), expandSelection); + } + bool MoveCursorDownBlock(bool expandSelection) + { + return DoMoveCursorBlock(wxSheetCoords(1, 0), expandSelection); + } + bool MoveCursorLeftBlock(bool expandSelection) + { + return DoMoveCursorBlock(wxSheetCoords(0, -1), expandSelection); + } + bool MoveCursorRightBlock(bool expandSelection) + { + return DoMoveCursorBlock(wxSheetCoords(0, 1), expandSelection); + } + bool MoveCursorUpPage(bool expandSelection) + { + return DoMoveCursorUpDownPage(true, expandSelection); + } + bool MoveCursorDownPage(bool expandSelection) + { + return DoMoveCursorUpDownPage(false, expandSelection); + } + + virtual bool DoMoveCursor(const wxSheetCoords &relCoords, bool expandSelection); + virtual bool DoMoveCursorBlock(const wxSheetCoords &relDir, bool expandSelection); + virtual bool DoMoveCursorUpDownPage(bool page_up, bool expandSelection); + + // ------------------------------------------------------------------------ + // Cell/Row/Col selection and deselection, you can only select grid cells + + // Note: A selection to the # of rows/cols means that the whole row/col is + // selected. Otherwise the right/bottom is rows/cols - 1, ie. contained + // within the actual number of cells. + // If sendEvt a wxEVT_SHEET_RANGE_SELECTED is sent, the SELECTING event + // should have been sent by the caller and if vetoed not call these. + // All functions (De)Select/Row/Col/Cell, SelectAll go to (De)SelectBlock. + // ClearSelection deselects everything and sends a single event with + // wxSheetBlock(0,0,rows,cols) to imply everything is cleared. + + // To override the selection mechanism you only need to override, + // HasSelection, IsCell/Row/ColSelected, (De)SelectBlock, and ClearSelection. + + // Is there any selection, if selecting, includes the active selection block + // which is not yet part of underlying selection system + virtual bool HasSelection(bool selecting = true) const; + // Are these coords within either the selecting block or selection + virtual bool IsCellSelected(const wxSheetCoords &coords) const; + bool IsCellSelected(int row, int col) const { return IsCellSelected(wxSheetCoords(row, col)); } + virtual bool IsRowSelected(int row) const; + virtual bool IsColSelected(int col) const; + // Are we currently in the middle of a selection + bool IsSelecting() const { return !GetSelectingBlock().IsEmpty(); } + + void SetSelectionMode(wxSheetSelectionMode_Type selmode); + int GetSelectionMode() const { return GetSheetRefData()->m_selectionMode; } + bool HasSelectionMode(int mode) { return (GetSelectionMode() & mode) != 0; } + + virtual bool SelectRow(int row, bool addToSelected = false, bool sendEvt = false); + virtual bool SelectRows(int rowTop, int rowBottom, bool addToSelected = false, + bool sendEvt = false); + virtual bool SelectCol(int col, bool addToSelected = false, bool sendEvt = false); + virtual bool SelectCols(int colLeft, int colRight, bool addToSelected = false, + bool sendEvt = false); + virtual bool SelectCell(const wxSheetCoords &coords, bool addToSelected = false, + bool sendEvt = false); + virtual bool SelectBlock(const wxSheetBlock &block, bool addToSelected = false, + bool sendEvt = false); + // selects everything to numRows, numCols + virtual bool SelectAll(bool sendEvt = false); + + virtual bool DeselectRow(int row, bool sendEvt = false); + virtual bool DeselectRows(int rowTop, int rowBottom, bool sendEvt = false); + virtual bool DeselectCol(int col, bool sendEvt = false); + virtual bool DeselectCols(int colLeft, int colRight, bool sendEvt = false); + virtual bool DeselectCell(const wxSheetCoords &coords, bool sendEvt = false); + virtual bool DeselectBlock(const wxSheetBlock &block, bool sendEvt = false); + // clears selection, single deselect event numRows, numCols + virtual bool ClearSelection(bool send_event = false); + + // toggle the selection of a single cell, row, or col + // addToSelected applies to a selection only, ignored if a deselection + virtual bool ToggleCellSelection(const wxSheetCoords &coords, bool addToSelected = false, + bool sendEvt = false); + virtual bool ToggleRowSelection(int row, bool addToSelected = false, bool sendEvt = false); + virtual bool ToggleColSelection(int col, bool addToSelected = false, bool sendEvt = false); + + // Get a pointer to the selection mechanism. You are free to do what you + // want with it, do a ForceRefresh to update the grid when done. + wxSheetSelection *GetSelection() const { return GetSheetRefData()->m_selection; } + + // During a selection this is the selecting block, else empty + const wxSheetBlock &GetSelectingBlock() const { return GetSheetRefData()->m_selectingBlock; } + const wxSheetCoords &GetSelectingAnchor() const { return GetSheetRefData()->m_selectingAnchor; } + + // These are internal use functions to highlight a block during mouse + // dragging or keyboard selecting + void SetSelectingBlock(const wxSheetBlock &selectingBlock) + { + GetSheetRefData()->m_selectingBlock = selectingBlock; + } + void SetSelectingAnchor(const wxSheetCoords &selectingAnchor) + { + GetSheetRefData()->m_selectingAnchor = selectingAnchor; + } + + // while selecting set and draw m_selectingBlock highlight and clear up last + virtual void HighlightSelectingBlock(const wxSheetBlock &selectingBlock); + void HighlightSelectingBlock(const wxSheetCoords &cornerCell, const wxSheetCoords &otherCell) + { + HighlightSelectingBlock(wxSheetBlock(cornerCell, otherCell)); + } + + // ------------------------------------------------------------------------ + // Copy/Paste functionality for strings + + // Copy the current selection using CopyCurrentSelectionInternal then + // to the wxClipboard using CopyInternalSelectionToClipboard + bool CopyCurrentSelectionToClipboard(bool copy_cursor = true, const wxChar &colSep = wxT('\t')); + // Copy the current selection to an internal copied selection mechanism + // storing both the positions and values of the selected cells, if no + // selection and copy_cursor then just copy the cursor value + bool CopyCurrentSelectionInternal(bool copy_cursor = true); + // Copy the internal selection to the wxClipboard as both a string using + // colSep to separate columns and as an internal representation for + // pasting back into the wxSheet. + bool CopyInternalSelectionToClipboard(const wxChar &colSep = wxT('\t')); + // Copy the internal selection to a clipboard string + // uses colSep for cols and \n for rows, called by CopySelectionToClipboard + wxString CopyInternalSelectionToString(const wxChar &colSep = wxT('\t')); + + // Copies the string (perhaps from the clipboard) to the internal copied + // selection uses colSep for cols and \n for rows, used by PasteFromClipboard + bool CopyStringToSelection(const wxString &value, const wxChar &colSep = wxT('\t')); + + // Tries to get the clipboard data as wxSheet's clipboard data + // representation else use CopyStringToSelection to convert a string + // using colSep as the column separator and \n as row separator. + bool PasteFromClipboard(const wxSheetCoords &topLeft = wxNullSheetCoords, + const wxChar &colSep = wxT('\t')); + // Paste the internal copied selection at the topLeft coords or if + // topLeft = wxNullSheetCoords then if IsSelection use the upper right of + // the current selection and only paste into currently selected cells. + // If no selection the the cursor is the topLeft cell. + virtual bool PasteInternalCopiedSelection(const wxSheetCoords &topLeft = wxNullSheetCoords); + // Are the cells being pasted right now, use this in the table's + // SetCellValue and AppendXXX to differentiate between a user typing + bool CurrentlyPasting() const { return GetSheetRefData()->m_pasting; } + + // ------------------------------------------------------------------------ + // Edit control functions (mostly used internally) + + // Is/Make the whole sheet editable or readonly + bool IsEditable() const { return GetSheetRefData()->m_editable; } + void EnableEditing(bool edit); + + // enable and show the editor control at the coords, returns sucess, ie. !vetoed + bool EnableCellEditControl(const wxSheetCoords &coords); + // hide and disable the editor and save the value if save_value, returns sucess, ie. !vetoed + bool DisableCellEditControl(bool save_value); + // is this cell valid and editable + bool CanEnableCellControl(const wxSheetCoords &coords) const; + // is the cell editor created (may not be shown though) + bool IsCellEditControlCreated() const; + // is the cell editor valid and shown + bool IsCellEditControlShown() const; + + // Create and show the appropriate editor at the EnableCellEditControl coords + // this is called internally by EnableCellEditControl, but if you call + // HideCellEditControl and if IsCellEditControlCreated then you can reshow + // it with this, returns sucess + bool ShowCellEditControl(); + // Hide the editor, doesn't destroy it (use DisableCellEditControl) + // check if IsCellEditControlShown first, returns sucess + bool HideCellEditControl(); + // Save the value of the editor, check IsCellEditControlEnabled() first + void SaveEditControlValue(); + + // Get the current editor, !Ok() if !IsCellEditControlCreated() + const wxSheetCellEditor &GetEditControl() const { return GetSheetRefData()->m_cellEditor; } + // These are the coords of the editor, check IsCellEditControlCreated before using + const wxSheetCoords &GetEditControlCoords() const + { + return GetSheetRefData()->m_cellEditorCoords; + } + + // ------------------------------------------------------------------------ + // Drawing functions + + // Code that does a lot of grid modification can be enclosed + // between BeginBatch() and EndBatch() calls to avoid screen flicker + // EndBatch's refresh = false will not refresh when batchCount is 0 + void BeginBatch() { m_batchCount++; } + void EndBatch(bool refresh = true); + int GetBatchCount() const { return m_batchCount; } + + // Use ForceRefresh, rather than wxWindow::Refresh(), to force an + // immediate repainting of the grid. No effect if GetBatchCount() > 0 + // This function is necessary because wxSheet has a minimal OnPaint() + // handler to reduce screen flicker. + void ForceRefresh() + { + BeginBatch(); + EndBatch(); + } + + // *** Use these redrawing functions to ensure refed sheets are redrawn *** + + // Refresh a single cell, can also draw cells for labels using -1 notation + // does nothing if cell !visible, or GetBatchCount != 0 + // if single_cell then literally draw only the single cell, else draw the + // cell to left in case the overflow marker needs to be drawn and the + // cells to the right in case this cell overflows. + void RefreshCell(const wxSheetCoords &coords, bool single_cell = true); + // Refresh a block of cells in any/all of the windows by chopping up the block, + // uses -1 notation to refresh labels + void RefreshBlock(const wxSheetBlock &block); + // Refresh a single row, row = -1 refreshes all col labels, + // does nothing if row !visible, or GetBatchCount != 0 + void RefreshRow(int row); + // Refresh a single col, col = -1 refreshes all row labels, + // does nothing if col !visible, or GetBatchCount != 0 + void RefreshCol(int col); + // Refresh is called using a rect surrounding the block + // does nothing if block IsEmpty, !visible, or GetBatchCount != 0 + void RefreshGridCellBlock(const wxSheetBlock &block); + // After SetAttr call this can appropriately refresh the wxSheet areas + void RefreshAttrChange(const wxSheetCoords &coords, wxSheetAttr_Type type); + + // ************************************************************************ + // Drawing implementation + + // Refresh an area of the window that calculates the smaller rects for + // each individual window (row/col/corner...) and calls Refresh(subRect) + // The rect is the logical rect, not the scrolled device rect + virtual void Refresh(bool eraseb = true, const wxRect *rect = NULL); + + // These directly call wxWindow::Refresh for the appropriate windows + // The input rect doesn't have to be clipped to the visible window since + // this function takes care of that, but it should be in client coords. + void RefreshGridWindow(bool eraseb = true, const wxRect *rect = NULL); + void RefreshRowLabelWindow(bool eraseb = true, const wxRect *rect = NULL); + void RefreshColLabelWindow(bool eraseb = true, const wxRect *rect = NULL); + void RefreshCornerLabelWindow(bool eraseb = true, const wxRect *rect = NULL); + + // Don't use these if you plan to use the splitter since they only act + // on this sheet. + + // These functions are called by the OnPaint handler of these windows + // use these to add "extra touches" before or after redrawing. + // The dc should be prepared before calling these. + virtual void PaintGridWindow(wxDC &dc, const wxRegion ®); + virtual void PaintRowLabelWindow(wxDC &dc, const wxRegion ®); + virtual void PaintColLabelWindow(wxDC &dc, const wxRegion ®); + virtual void PaintCornerLabelWindow(wxDC &dc, const wxRegion ®); + virtual void PaintSheetWindow(wxDC &dc, const wxRegion ®); + + // draws a bunch of blocks of grid cells onto the given DC + virtual void DrawGridCells(wxDC &dc, const wxSheetSelection &blockSel); + // Draw the area below and to right of grid up to scrollbars + virtual void DrawGridSpace(wxDC &dc); + // draw the border around a single cell + virtual void DrawCellBorder(wxDC &dc, const wxSheetCoords &coords); + // Draw all the grid lines in the region + virtual void DrawAllGridLines(wxDC &dc, const wxRegion ®); + // Draw a single cell + virtual void DrawCell(wxDC &dc, const wxSheetCoords &coords); + // Calls DrawCursorCellHighlight if contained within this selection + virtual void DrawCursorHighlight(wxDC &dc, const wxSheetSelection &blockSel); + // Draw the cursor cell highlight + virtual void DrawCursorCellHighlight(wxDC &dc, const wxSheetCellAttr &attr); + + // draw wxSheetRowLabelWindow labels + virtual void DrawRowLabels(wxDC &dc, const wxArrayInt &rows); + // draw wxSheetColLabelWindow labels + virtual void DrawColLabels(wxDC &dc, const wxArrayInt &cols); + // wxSheetCornerLabelWindow label + virtual void DrawCornerLabel(wxDC &dc); + + // Draw the row/col resizing marker and if newDragPos != -1, set the + // new position of the marker + virtual void DrawRowColResizingMarker(int newDragPos = -1); + + // Draw the splitter button in the rectangle + virtual void DrawSplitterButton(wxDC &dc, const wxRect &rect); + + // Calculate the Row/ColLabels and Cells exposed for the wxRegion + // returns false if none, used for redrawing windows + bool CalcRowLabelsExposed(const wxRegion ®, wxArrayInt &rows) const; + bool CalcColLabelsExposed(const wxRegion ®, wxArrayInt &cols) const; + bool CalcCellsExposed(const wxRegion ®, wxSheetSelection &blockSel) const; + int FindOverflowCell(const wxSheetCoords &coords, wxDC &dc); + + // helper drawing functions + void DrawTextRectangle(wxDC &dc, const wxString &value, const wxRect &rect, + int alignment = wxALIGN_LEFT | wxALIGN_TOP, + int textOrientation = wxHORIZONTAL); + + void DrawTextRectangle(wxDC &dc, const wxArrayString &lines, const wxRect &, + int alignment = wxALIGN_LEFT | wxALIGN_TOP, + int textOrientation = wxHORIZONTAL); + + // Split string by '\n' and add to array, returning the number of lines + // returns 0 for empty string. + int StringToLines(const wxString &value, wxArrayString &lines) const; + // Get the size of the lines drawn horizontally, returs true if size > 0 + bool GetTextBoxSize(wxDC &dc, const wxArrayString &lines, long *width, long *height) const; + + // ------------------------------------------------------------------------ + // Geometry utility functions, pixel <-> cell etc + + // Note that all of these functions work with the logical coordinates of + // grid cells and labels so you will need to convert from device + // coordinates for mouse events etc. + // clipToMinMax means that the return value will be within the grid cells + // if !clipToMinMax and out of bounds it returns -1. + // Use ContainsGridXXX to verify validity, -1 doesn't mean label + wxSheetCoords XYToGridCell(int x, int y, bool clipToMinMax = false) const; + int YToGridRow(int y, bool clipToMinMax = false) const; + int XToGridCol(int x, bool clipToMinMax = false) const; + + // return the row/col number that the x/y coord is near the edge of, or + // -1 if not near an edge, uses WXSHEET_LABEL_EDGE_ZONE + // Use ContainsGridXXX to verify validity, -1 doesn't mean label + int YToEdgeOfGridRow(int y) const; + int XToEdgeOfGridCol(int x) const; + + // Get a rect bounding the cell, handles spanning cells and the label + // windows using the -1 notation, getDeviceRect calls CalcScrolledRect + wxRect CellToRect(const wxSheetCoords &coords, bool getDeviceRect = false) const; + // Get a rect bounding the block, handles label windows using the -1 notation, + // getDeviceRect calls CalcScrolledRect + wxRect BlockToRect(const wxSheetBlock &block, bool getDeviceRect = false) const; + + // Expand the block by unioning with intersecting spanned cells + wxSheetBlock ExpandSpannedBlock(const wxSheetBlock &block) const; + + // Convert the block of cells into a wxRect in device coords, expands the + // block to contain spanned cells if expand_spanned. + // These functions do handle label cells, but if you span the block from a label + // into the grid then the rect will overlap the windows, probably not what you want. + wxRect BlockToDeviceRect(const wxSheetBlock &block, bool expand_spanned = true) const; + wxRect BlockToLogicalRect(const wxSheetBlock &block, bool expand_spanned = true) const; + + // Convert the rect in pixels into a block of cells for the grid + // if wholeCell then only include cells in the block that are + // wholly contained by the rect + wxSheetBlock LogicalGridRectToBlock(const wxRect &rect, bool wholeCell = false) const; + + // get a block containing all the currently (partially/fully) visible cells + wxSheetBlock GetVisibleGridCellsBlock(bool wholeCellVisible = false) const; + + // Align the size of an object inside the rect using wxALIGN enums + // if inside then align it to the left if it would have overflown + // always pins size to left hand side + wxPoint AlignInRect(int align, const wxRect &rect, const wxSize &size, bool inside = true) const; + + // ------------------------------------------------------------------------ + // Scrolling for the window, everything is done with pixels + // there is no need for scroll units and they only cause sizing problems + + // Get the scrolled origin of the grid in pixels + const wxPoint &GetGridOrigin() const { return m_gridOrigin; } + // Set the absolute scrolled origin of the grid window in pixels + // this checks validity and ensures proper positioning. + // Use x or y = -1 to not change the origin in the x or y direction + // Unless setting from a scrollbar event use adjustScrollBars=true + virtual void SetGridOrigin(int x, int y, bool adjustScrollBars = true, bool sendEvt = false); + void SetGridOrigin(const wxPoint &pt, bool adjustScrollBars = true, bool sendEvt = false) + { + SetGridOrigin(pt.x, pt.y, adjustScrollBars, sendEvt); + } + + // Get the virtual size of the grid in pixels, includes extra width/height + wxSize GetGridVirtualSize(bool add_margin = true) const; + + // Get the extent of the grid, this may be more than the virtual size if the + // grid is smaller than the containing window + wxSize GetGridExtent() const; + + // Same as wxScrolledWindow Calc(Un)ScrolledPosition + void CalcScrolledPosition(int x, int y, int *xx, int *yy) const + { + if (xx) { + *xx = x - m_gridOrigin.x; } - - bool Create( wxWindow *parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxWANTS_CHARS, - const wxString& name = wxT("wxSheet") ); - - virtual ~wxSheet(); - virtual bool Destroy(); - - // ref another wxSheet's ref data - see usage in wxSheetSplitter - void RefSheet(wxSheet* otherSheet); - // Create a new wxSheet with same parent, used for wxSheetSplitter. - // override this so that the top left sheet in the splitter can return - // a "new MySheet" for the other sheets as necessary - // This is one of the few ways for the splitter to create new sheets. - virtual wxSheet* Clone(wxWindowID id = wxID_ANY); - - // override wxWindow::Enable to ensure proper refresh - virtual bool Enable(bool enable = true); - - // ------------------------------------------------------------------------ - // Create/Set/Get wxSheetTable - the underlying data to be displayed - - wxSheetTable* GetTable() const { return GetSheetRefData()->m_table; } - // Set your own table derived from wxSheetTable, if takeOwnership the - // the table will be deleted when this window is destroyed - bool SetTable( wxSheetTable *table, bool takeOwnership ); - - // Create a wxSheetTable using string data containers to use - // see this function to see how to setup the table and use SetTable - // for the case where you want to customize things - // This function exists to show how to create and assign tables - bool CreateGrid( int numRows, int numCols, int options = 0 ); - - // ------------------------------------------------------------------------ - // Dimensions of the number of cells on the sheet and helper cell functions - - int GetNumberRows() const { return GetSheetRefData()->m_rowEdges.GetCount(); } - int GetNumberCols() const { return GetSheetRefData()->m_colEdges.GetCount(); } - - // Is the coords anywhere in labels or grid, -1 to GetNumberRows/Cols()-1 - bool ContainsCell( const wxSheetCoords& coords ) const - { return (coords.m_row >= -1) && (coords.m_col >= -1) && - (coords.m_row < GetNumberRows()) && - (coords.m_col < GetNumberCols()); } - - // returns true if the coords are within the grid cells of the sheet - bool ContainsGridRow( int row ) const { return (row >= 0) && (row < GetNumberRows()); } - bool ContainsGridCol( int col ) const { return (col >= 0) && (col < GetNumberCols()); } - bool ContainsGridCell( const wxSheetCoords& coords ) const - { return ContainsGridRow(coords.m_row) && ContainsGridCol(coords.m_col); } - - // returns true if the coords are within the row/col label cells - bool ContainsRowLabelCell( const wxSheetCoords& coords ) const - { return (coords.m_col == -1) && ContainsGridRow(coords.m_row); } - bool ContainsColLabelCell( const wxSheetCoords& coords ) const - { return (coords.m_row == -1) && ContainsGridCol(coords.m_col); } - - // static helper functions to determine what type of cell it is, not check validity - - static bool IsGridCell(const wxSheetCoords& coords) - { return (coords.m_row >= 0) && (coords.m_col >= 0); } - static bool IsLabelCell(const wxSheetCoords& coords) - { return (coords.m_row >= -1) && (coords.m_col >= -1) && - ((coords.m_row == -1) || (coords.m_col == -1)); } - static bool IsRowLabelCell(const wxSheetCoords& coords) - { return (coords.m_row >= 0) && (coords.m_col == -1); } - static bool IsColLabelCell(const wxSheetCoords& coords) - { return (coords.m_row == -1) && (coords.m_col >= 0); } - static bool IsCornerLabelCell(const wxSheetCoords& coords) - { return (coords.m_row == -1) && (coords.m_col == -1); } - - // Get an enum value of what window the coords are meant for - static wxSheetCell_Type GetCellCoordsType(const wxSheetCoords& coords); - - // "clear" the contents of the grid (depends on table's Clear() function) - // the string implementations clear the cell values, not the # rows/cols - void ClearValues(int update = wxSHEET_UpdateValues); - - // Insert/Add/DeleteRows/Cols to the grid cells - // update contains or'ed values of enum wxSheetUpdate_Type. - // you proabably want UpdateAll unless you ensure that no problems will occur - // or you will update some other way - bool InsertRows( size_t row, size_t numRows, int update = wxSHEET_UpdateAll ) - { return UpdateRows(row, numRows, update); } - bool AppendRows( size_t numRows, int update = wxSHEET_UpdateAll ) - { return UpdateRows(GetNumberRows(), numRows, update); } - bool DeleteRows( size_t row, size_t numRows, int update = wxSHEET_UpdateAll ) - { return UpdateRows(row, -int(numRows), update); } - - bool InsertCols( size_t col, size_t numCols, int update = wxSHEET_UpdateAll ) - { return UpdateCols(col, numCols, update); } - bool AppendCols( size_t numCols, int update = wxSHEET_UpdateAll ) - { return UpdateCols(GetNumberCols(), numCols, update); } - bool DeleteCols( size_t col, size_t numCols, int update = wxSHEET_UpdateAll ) - { return UpdateCols(col, -int(numCols), update); } - - // Set exactly the number of rows or cols, these functions Append or - // Delete rows/cols to/from the end. If you are setting attributes for - // particular cells/rows/cols you probably won't want to use these - bool SetNumberRows( size_t rows, int update = wxSHEET_UpdateAll ); - bool SetNumberCols( size_t cols, int update = wxSHEET_UpdateAll ); - bool SetNumberCells( size_t rows, size_t cols, int update = wxSHEET_UpdateAll ) - { return SetNumberRows(rows, update) || SetNumberCols(cols, update); } - - // Inserting/Appending/Deleting rows/cols functions are forwarded here - // and then sent to the wxSheetTable::UpdateRows/Cols functions - // numRows/Cols > 0 : InsertRows/Cols at row/col else if < 0 delete - // row/col == GetNumberRows/Cols && numRows/Cols > 0 to append to end - virtual bool UpdateRows( size_t row, int numRows, int update = wxSHEET_UpdateAll ); - virtual bool UpdateCols( size_t col, int numCols, int update = wxSHEET_UpdateAll ); - - // ------------------------------------------------------------------------ - // Dimensions of the row and column sizes - - // Get/Set the default height/width of newly created rows/cols - // if resizeExisting then resize all to match the newly set default - int GetDefaultRowHeight() const { return GetSheetRefData()->m_rowEdges.GetDefaultSize(); } - int GetDefaultColWidth() const { return GetSheetRefData()->m_colEdges.GetDefaultSize(); } - void SetDefaultRowHeight( int height, bool resizeExistingRows = false ); - void SetDefaultColWidth( int width, bool resizeExistingCols = false ); - - // Get/Set the absolute min row/col width/height, 0 for no min size - // Call during grid creation, existing rows/cols are not resized - // This value is used when dragging cell size with the mouse if no - // particular min size for a row/col has been set - int GetMinimalAcceptableRowHeight() const { return GetSheetRefData()->m_rowEdges.GetMinAllowedSize(); } - int GetMinimalAcceptableColWidth() const { return GetSheetRefData()->m_colEdges.GetMinAllowedSize(); } - void SetMinimalAcceptableRowHeight(int height) { GetSheetRefData()->m_rowEdges.SetMinAllowedSize(height); } - void SetMinimalAcceptableColWidth(int width) { GetSheetRefData()->m_colEdges.SetMinAllowedSize(width); } - - // Don't allow specific rows/cols to be resized smaller than this - // Call during grid creation, existing rows/cols are not resized - // The setting is cleared to default val if width/height is < min acceptable - int GetMinimalRowHeight(int row) const { return GetSheetRefData()->m_rowEdges.GetMinSize(row); } - int GetMinimalColWidth(int col) const { return GetSheetRefData()->m_colEdges.GetMinSize(col); } - void SetMinimalRowHeight(int row, int height) { GetSheetRefData()->m_rowEdges.SetMinSize(row, height); } - void SetMinimalColWidth(int col, int width) { GetSheetRefData()->m_colEdges.SetMinSize(col, width); } - - // Set the height of a row or width of a col, -1 notation for labels - // use height/width = -1 to autosize from the row/col labels - void SetRowHeight( int row, int height ); - void SetColWidth( int col, int width ); - - // Get the height/top/bottom for rows, uses -1 notation - int GetRowHeight(int row) const; - int GetRowTop(int row) const; - int GetRowBottom(int row) const; - // Get the width/left/right for cols, uses -1 notation - int GetColWidth(int col) const; - int GetColLeft(int col) const; - int GetColRight(int col) const; - // Get the width, height of a cell as a wxSize, -1 notation - // this does not include spanned cells - wxSize GetCellSize(const wxSheetCoords& coords) const; - - // does the cell have a non-zero width and height, may not be visible, -1 notation - bool IsCellShown( const wxSheetCoords& coords ) const; - - // grid may occupy more space than needed for its rows/columns, this - // function allows to set how big this margin space is - void SetMargins(int width, int height) - { GetSheetRefData()->m_marginSize.x = wxMax(0, width); - GetSheetRefData()->m_marginSize.y = wxMax(0, height); } - - // Get the renderer's best size for the cell, uses -1 notation - wxSize GetCellBestSize(const wxSheetCoords& coords, wxDC *dc = NULL) const; - // Get the best height of a row or the best width of a col using the - // renderer's best size - int GetRowBestHeight(int row) const; - int GetColBestWidth(int col) const; - - // ------------------------------------------------------------------------ - // Row/Col label size - - // Get the fixed initial size of the width of row labels or height of col labels - int GetDefaultRowLabelWidth() const { return WXSHEET_DEFAULT_ROW_LABEL_WIDTH; } - int GetDefaultColLabelHeight() const { return WXSHEET_DEFAULT_COL_LABEL_HEIGHT; } - - // Get/Set the row/col label widths, - // if zero_not_shown and row/col & corner not shown return 0 - int GetRowLabelWidth(bool zero_not_shown=true) const; - int GetColLabelHeight(bool zero_not_shown=true) const; - void SetRowLabelWidth( int width ); - void SetColLabelHeight( int height ); - - // ------------------------------------------------------------------------ - // Auto sizing of the row/col widths/heights - - // automatically size the col/row to fit to its contents, if setAsMin, - // this optimal width will also be set as minimal width for this column - // returns the width or height used. - int AutoSizeRow( int row, bool setAsMin = true ); - int AutoSizeCol( int col, bool setAsMin = true ); - - // auto size all columns (very ineffective for big grids!) - void AutoSizeRows( bool setAsMin = true ); - void AutoSizeCols( bool setAsMin = true ); - - // auto size the grid, that is make the columns/rows of the "right" size - // and also set the grid size to just fit its contents - void AutoSize( bool setAsMin = true ); - - // autosize row height depending on label text - void AutoSizeRowLabelHeight( int row ); - // autosize column width depending on label text - void AutoSizeColLabelWidth( int col ); - - // Force the col widths to be of equal size so that they fit within the - // the window size. This is maintained even when the window is resized. - // The col widths will not be sized less than min_width in pixels. - // Use this if you know that the window will be of a reasonable size to - // fit the cols, but you don't want to track the EVT_SIZE yourself. - // use a min_width <= 0 to turn it off - void SetEqualColWidths(int min_width); - - // ------------------------------------------------------------------------ - // Row/Col drag resizing enabled or disabled - // - // if CanDragRow/ColSize the rows/cols can be resized by the mouse - // if CanDragGridSize you can resize the rows/cols in the grid window - // else you resize in the label windows (if CanDragRow/ColSize is true) - - void EnableDragRowSize( bool enable = true ) { SetDragCellSize(wxSHEET_DragLabelRowHeight, enable); } - void EnableDragColSize( bool enable = true ) { SetDragCellSize(wxSHEET_DragLabelColWidth, enable); } - void EnableDragGridSize(bool enable = true ) { SetDragCellSize(wxSHEET_DragGridCellSize, enable); } - void DisableDragRowSize() { EnableDragRowSize( false ); } - void DisableDragColSize() { EnableDragColSize( false ); } - void DisableDragGridSize() { EnableDragGridSize(false); } - bool CanDragRowSize() const { return (GetDragCellSize() & wxSHEET_DragLabelRowHeight) != 0; } - bool CanDragColSize() const { return (GetDragCellSize() & wxSHEET_DragLabelColWidth) != 0; } - bool CanDragGridSize() const { return (GetDragCellSize() & wxSHEET_DragGridCellSize) != 0; } - - // Directly set the dragging of the cell size use wxSheetDragCellSize_Type enums - void SetDragCellSize( int type ) { GetSheetRefData()->m_canDrag = type; } - void SetDragCellSize( int type, bool enable ) - { SetDragCellSize( enable ? (GetDragCellSize() | type) : (GetDragCellSize() & (~type)) ); } - int GetDragCellSize() const { return GetSheetRefData()->m_canDrag; } - - // ------------------------------------------------------------------------ - // Grid line, cell highlight, selection colouring - - // Draw the grid lines, wxHORIZONAL | wxVERTICAL (wxBOTH), 0 for none - void EnableGridLines( int dir = wxBOTH ); - int GridLinesEnabled() const { return GetSheetRefData()->m_gridLinesEnabled; } - - const wxColour& GetGridLineColour() const { return GetSheetRefData()->m_gridLineColour; } - void SetGridLineColour( const wxColour& colour ); - - const wxColour& GetCursorCellHighlightColour() const { return GetSheetRefData()->m_cursorCellHighlightColour; } - int GetCursorCellHighlightPenWidth() const { return GetSheetRefData()->m_cursorCellHighlightPenWidth; } - int GetCursorCellHighlightROPenWidth() const { return GetSheetRefData()->m_cursorCellHighlightROPenWidth; } - void SetCursorCellHighlightColour( const wxColour& colour ); - void SetCursorCellHighlightPenWidth(int width); - void SetCursorCellHighlightROPenWidth(int width); - - // get/set the colour bounding the labels to give 3-D effect - const wxColour& GetLabelOutlineColour() const { return GetSheetRefData()->m_labelOutlineColour; } - void SetLabelOutlineColour( const wxColour& colour ); - - const wxColour& GetSelectionBackground() const { return GetSheetRefData()->m_selectionBackground; } - const wxColour& GetSelectionForeground() const { return GetSheetRefData()->m_selectionForeground; } - void SetSelectionBackground(const wxColour& c) { GetSheetRefData()->m_selectionBackground = c; } - void SetSelectionForeground(const wxColour& c) { GetSheetRefData()->m_selectionForeground = c; } - - // ------------------------------------------------------------------------ - // Span, cells can span across multiple cells, hiding cells below - // - // Normally cells are of size 1x1, but they can be larger. - // The other cells can still have values and attributes, but they - // will not be used since GetCellOwner is used for most coord operations - // so that the underlying cell values and attributes are ignored. - // The span for the owner cell is 1x1 or larger, the span for other - // cells contained within the spanned block have a cell span of <= 0, such - // that coords + GetCellSpan() = the owner cell - // - // You can completely override this functionality if you provide - // HasSpannedCells, GetCellBlock, SetCellSpan - - // Are there any spanned cells at all? - virtual bool HasSpannedCells() const; - - // if cell is part of a spanning cell, return owner's coords else input coords - wxSheetCoords GetCellOwner( const wxSheetCoords& coords ) const; - // Get a block of the cell, unless a spanned cell it's of size 1,1 - // note: the top left of block is the owner cell of coords - virtual wxSheetBlock GetCellBlock( const wxSheetCoords& coords ) const; - // Get the span of a cell, the owner (top right) cell always has a span of - // (1, 1) or greater. The other cells in a spanned block will have a span - // (<1, <1) such that, coords + coordsSpan = ownerCoords - wxSheetCoords GetCellSpan( const wxSheetCoords& coords ) const; - // Set the span of a cell, must be 1x1 or greater, - // To remove a spanned cell set it to a cell of size 1x1 - // For grid cells the whole block must be contained within the grid cells - // and if the block intersects a previously spanned cell block the top left - // corners must match up. - // Row and Col labels can span cells as well, spanned row labels must have a - // width of 1 and a height of >= 1, col labels a height of 1 and width >= 1 - virtual void SetCellSpan( const wxSheetBlock& block ); - void SetCellSpan( const wxSheetCoords& coords, const wxSheetCoords& numRowsCols ) - { SetCellSpan(wxSheetBlock(coords, numRowsCols.m_row, numRowsCols.m_col)); } - - // Get a pointer to the spanned blocks to iterate through, may return NULL. - const wxSheetSelection* GetSpannedBlocks() const { return GetTable() ? GetTable()->GetSpannedBlocks() : NULL; } - // ------------------------------------------------------------------------ - // Get/Set attributes for the cells, row, col, corner labels - - // See wxSheetAttr_Type for a description of the type of attribute - - // The coords are specified as - // The Grid area (0 <= row < GetNumberRows), (0 <= col < GetNumberCols) - // The Corner window row = col = -1 - // The Row labels (0 <= row < GetNumberRows), col = -1 - // The Col labels row = -1, (0 <= col < GetNumberCols) - - // For the wxSHEET_AttrDefault type the coords should be contained within the - // size of the sheet, but the particular values are not used. - // see const wxGridCellSheetCoords = (0,0) for example - // wxRowLabelSheetCoords, wxColLabelSheetCoords, wxCornerLabelSheetCoords - - // To completely override this you may provide alternate - // GetOrCreateAttr, GetAttr, and SetAttr functions. - - // make sure that the last default attr of initAttr is defAttr - // This is called internally when you call SetAttr - bool InitAttr( wxSheetCellAttr& initAttr, const wxSheetCellAttr& defAttr ) const; - - // Get an attribute for the coords if it exists or create a new one - // and put it into the table which puts it in the attr provider. - // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col for the grid cells - // and wxSHEET_AttrDefault/Cell for the labels - virtual wxSheetCellAttr GetOrCreateAttr( const wxSheetCoords& coords, - wxSheetAttr_Type type ) const; - - // Get the attribute for any area depending on the coords and type - // returns a valid attr if the coords are valid and type = wxSHEET_AttrAny - // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col/Any for the grid cells - // and wxSHEET_AttrDefault/Cell/Any for the labels - virtual wxSheetCellAttr GetAttr( const wxSheetCoords& coords, - wxSheetAttr_Type type = wxSHEET_AttrAny) const; - // Set the attribute for any area depending on the coords - // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col for the grid cells - // and wxSHEET_AttrDefault/Cell for the labels - virtual void SetAttr(const wxSheetCoords& coords, const wxSheetCellAttr& attr, - wxSheetAttr_Type type ); - - // ------ Simplified functions for accessing the attributes --------------- - // Get an attribute for the grid coords, returning a cell/row/col attr or - // if multiple attr for the coords an attr that's merged, or the def attr - wxSheetCellAttr GetGridAttr(const wxSheetCoords& coords) const { return GetAttr(coords, wxSHEET_AttrAny); } - - // Get a specific Cell/Row/Col attr for the coords in the grid - // if none set returns wxNullSheetCellAttr - wxSheetCellAttr GetGridCellAttr(const wxSheetCoords& coords) const { return GetAttr(coords, wxSHEET_AttrCell); } - wxSheetCellAttr GetGridRowAttr(int row) const { return GetAttr(wxSheetCoords(row, 0), wxSHEET_AttrRow); } - wxSheetCellAttr GetGridColAttr(int col) const { return GetAttr(wxSheetCoords(0, col), wxSHEET_AttrCol); } - // Set a specific Cell/Row/Col attr for coords, row/col only apply to the grid - void SetGridCellAttr(const wxSheetCoords& coords, const wxSheetCellAttr& attr) { SetAttr(coords, attr, wxSHEET_AttrCell); } - void SetGridRowAttr(int row, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(row, 0), attr, wxSHEET_AttrRow); } - void SetGridColAttr(int col, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(0, col), attr, wxSHEET_AttrCol); } - - // Get the row/col/corner label attributes, if one is not set for the - // particular coords, returns the default one. (note: only one corner attr) - // if you want the particular attr use GetRow/ColLabelCellAttr - wxSheetCellAttr GetRowLabelAttr(int row) const { return GetAttr(wxSheetCoords(row, -1), wxSHEET_AttrAny); } - wxSheetCellAttr GetColLabelAttr(int col) const { return GetAttr(wxSheetCoords(-1, col), wxSHEET_AttrAny); } - wxSheetCellAttr GetCornerLabelAttr() const { return GetAttr(wxSheetCoords(-1, -1), wxSHEET_AttrAny); } - - // Get a specific attr the row/col/corner label cell - // if none set returns wxNullSheetCellAttr - wxSheetCellAttr GetRowLabelCellAttr(int row) const { return GetAttr(wxSheetCoords(row, -1), wxSHEET_AttrCell); } - wxSheetCellAttr GetColLabelCellAttr(int col) const { return GetAttr(wxSheetCoords(-1, col), wxSHEET_AttrCell); } - // Set a specific attribute for particular row/col/corner label cell - void SetRowLabelCellAttr(int row, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(row, -1), attr, wxSHEET_AttrCell); } - void SetColLabelCellAttr(int col, const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(-1, col), attr, wxSHEET_AttrCell); } - void SetCornerLabelAttr(const wxSheetCellAttr& attr) { SetAttr(wxSheetCoords(-1, -1), attr, wxSHEET_AttrCell); } - - // Get/Set default attributes for the areas (only one corner attr) - // For setting, wxSheetCellAttr::UpdateWith is called with the current default - // attr so you so need only set the values that you want to change. - wxSheetCellAttr GetDefaultAttr(const wxSheetCoords& coords) const { return GetAttr(coords, wxSHEET_AttrDefault); } - wxSheetCellAttr GetDefaultGridCellAttr() const { return GetAttr(wxGridCellSheetCoords, wxSHEET_AttrDefault); } - wxSheetCellAttr GetDefaultRowLabelAttr() const { return GetAttr(wxRowLabelSheetCoords, wxSHEET_AttrDefault); } - wxSheetCellAttr GetDefaultColLabelAttr() const { return GetAttr(wxColLabelSheetCoords, wxSHEET_AttrDefault); } - void SetDefaultAttr(const wxSheetCoords& coords, const wxSheetCellAttr& attr) { SetAttr(coords, attr, wxSHEET_AttrDefault); } - void SetDefaultGridCellAttr(const wxSheetCellAttr& attr) { SetAttr(wxGridCellSheetCoords, attr, wxSHEET_AttrDefault); } - void SetDefaultRowLabelAttr(const wxSheetCellAttr& attr) { SetAttr(wxRowLabelSheetCoords, attr, wxSHEET_AttrDefault); } - void SetDefaultColLabelAttr(const wxSheetCellAttr& attr) { SetAttr(wxColLabelSheetCoords, attr, wxSHEET_AttrDefault); } - - // These are convienience functions, if for example you want to subclass the - // table and modify and return default attr "on the fly" for each cell - const wxSheetCellAttr& DoGetDefaultGridAttr() const { return GetSheetRefData()->m_defaultGridCellAttr; } - const wxSheetCellAttr& DoGetDefaultRowLabelAttr() const { return GetSheetRefData()->m_defaultRowLabelAttr; } - const wxSheetCellAttr& DoGetDefaultColLabelAttr() const { return GetSheetRefData()->m_defaultColLabelAttr; } - const wxSheetCellAttr& DoGetDefaultCornerLabelAttr() const { return GetSheetRefData()->m_defaultCornerLabelAttr; } - - // Get/Set particular attributes for any type of cell/row/col anywhere - // The default is to get the attr val for type=wxSHEET_AttrAny meaning that - // it'll find a set attr first or return the default attr value as a last resort. - // For GetXXX you will receive an an error message if you specify a - // particular wxSHEET_AttrCell/Row/Col, but there isn't an attribute set - const wxColour& GetAttrBackgroundColour( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - const wxColour& GetAttrForegoundColour( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - const wxFont& GetAttrFont( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - int GetAttrAlignment( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - int GetAttrOrientation( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - int GetAttrLevel( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - bool GetAttrOverflow( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - bool GetAttrOverflowMarker( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - bool GetAttrShowEditor( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - bool GetAttrReadOnly( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - wxSheetCellRenderer GetAttrRenderer( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - wxSheetCellEditor GetAttrEditor( const wxSheetCoords& coords, wxSheetAttr_Type type = wxSHEET_AttrAny ) const; - - // Set attributes for a particular cell/row/col, relies on GetOrCreateAttr() - // so it creates and adds the attr to the attr provider if there wasn't one - // after setting the particular value. - // The type may be only be wxSHEET_AttrDefault/Cell/Row/Col - void SetAttrBackgroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrForegroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrFont( const wxSheetCoords& coords, const wxFont& font, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrAlignment( const wxSheetCoords& coords, int align, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrOrientation( const wxSheetCoords& coords, int orientation, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrLevel( const wxSheetCoords& coords, int level, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrOverflow( const wxSheetCoords& coords, bool allow, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrOverflowMarker( const wxSheetCoords& coords, bool draw_marker, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrShowEditor( const wxSheetCoords& coords, bool show_editor, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrReadOnly( const wxSheetCoords& coords, bool isReadOnly, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrRenderer( const wxSheetCoords& coords, const wxSheetCellRenderer &renderer, wxSheetAttr_Type type = wxSHEET_AttrCell ); - void SetAttrEditor( const wxSheetCoords& coords, const wxSheetCellEditor &editor, wxSheetAttr_Type type = wxSHEET_AttrCell ); - - // helper functions that use SetColAttr to set renderer type - // set the format for the data in the column: default is string - void SetColFormatBool(int col) { SetColFormatCustom(col, wxSHEET_VALUE_BOOL); } - void SetColFormatNumber(int col) { SetColFormatCustom(col, wxSHEET_VALUE_NUMBER); } - void SetColFormatFloat(int col, int width = -1, int precision = -1); - void SetColFormatCustom(int col, const wxString& typeName); - - // ------------------------------------------------------------------------ - // Get/Set cell, row, col, and corner label values - // To completely override this you need only provide Get/SetCellValue - - // Get/Set cell value, uses coords = -1 notation for row/col/corner labels - virtual wxString GetCellValue( const wxSheetCoords& coords ); - virtual void SetCellValue( const wxSheetCoords& coords, const wxString& value ); - - // Is this cell empty, see wxSheetTable - virtual bool HasCellValue( const wxSheetCoords& coords ); - - wxString GetRowLabelValue( int row ) { return GetCellValue(wxSheetCoords(row, -1)); } - wxString GetColLabelValue( int col ) { return GetCellValue(wxSheetCoords(-1, col)); } - void SetRowLabelValue( int row, const wxString& value ) { SetCellValue(wxSheetCoords(row, -1), value); } - void SetColLabelValue( int col, const wxString& value ) { SetCellValue(wxSheetCoords(-1, col), value); } - - wxString GetCornerLabelValue() { return GetCellValue(wxSheetCoords(-1, -1)); } - void SetCornerLabelValue(const wxString& value) { SetCellValue(wxSheetCoords(-1, -1), value); } - - // ------------------------------------------------------------------------ - // Register mapping between data types to Renderers/Editors - - void RegisterDataType( const wxString& typeName, - const wxSheetCellRenderer& renderer, - const wxSheetCellEditor& editor ); - - virtual wxSheetCellEditor GetDefaultEditorForType(const wxString& typeName) const; - virtual wxSheetCellRenderer GetDefaultRendererForType(const wxString& typeName) const; - - // FIXME what is the point of these? - virtual wxSheetCellEditor GetDefaultEditorForCell(const wxSheetCoords& coords) const; - virtual wxSheetCellRenderer GetDefaultRendererForCell(const wxSheetCoords& coords) const; - - // ------------------------------------------------------------------------ - // Cursor movement and visibility functions - - // check to see if a cell is either wholly visible (the default arg) or - // at least partially visible, uses -1 notation for labels - bool IsCellVisible( const wxSheetCoords& coords, bool wholeCellVisible = true ) const; - bool IsRowVisible( int row, bool wholeRowVisible = true ) const; - bool IsColVisible( int col, bool wholeColVisible = true ) const; - // Make this cell visible, uses -1 notation, will not unhide label windows - void MakeCellVisible( const wxSheetCoords& coords ); - - // Get/Set cursor cell, this is the "current" cell where a highlight is drawn - // the cursor only applies to the grid cells - const wxSheetCoords& GetGridCursorCell() const { return GetSheetRefData()->m_cursorCoords; } - int GetGridCursorRow() const { return GetGridCursorCell().GetRow(); } - int GetGridCursorCol() const { return GetGridCursorCell().GetCol(); } - void SetGridCursorCell( const wxSheetCoords& coords ); - - bool MoveCursorUp( bool expandSelection ) { return DoMoveCursor(wxSheetCoords(-1, 0), expandSelection); } - bool MoveCursorDown( bool expandSelection ) { return DoMoveCursor(wxSheetCoords( 1, 0), expandSelection); } - bool MoveCursorLeft( bool expandSelection ) { return DoMoveCursor(wxSheetCoords( 0,-1), expandSelection); } - bool MoveCursorRight( bool expandSelection ) { return DoMoveCursor(wxSheetCoords( 0, 1), expandSelection); } - bool MoveCursorUpBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords(-1, 0), expandSelection); } - bool MoveCursorDownBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords( 1, 0), expandSelection); } - bool MoveCursorLeftBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords( 0,-1), expandSelection); } - bool MoveCursorRightBlock( bool expandSelection ) { return DoMoveCursorBlock(wxSheetCoords( 0, 1), expandSelection); } - bool MoveCursorUpPage( bool expandSelection ) { return DoMoveCursorUpDownPage(true, expandSelection); } - bool MoveCursorDownPage( bool expandSelection ) { return DoMoveCursorUpDownPage(false, expandSelection); } - - virtual bool DoMoveCursor( const wxSheetCoords& relCoords, bool expandSelection ); - virtual bool DoMoveCursorBlock( const wxSheetCoords& relDir, bool expandSelection ); - virtual bool DoMoveCursorUpDownPage( bool page_up, bool expandSelection ); - - // ------------------------------------------------------------------------ - // Cell/Row/Col selection and deselection, you can only select grid cells - - // Note: A selection to the # of rows/cols means that the whole row/col is - // selected. Otherwise the right/bottom is rows/cols - 1, ie. contained - // within the actual number of cells. - // If sendEvt a wxEVT_SHEET_RANGE_SELECTED is sent, the SELECTING event - // should have been sent by the caller and if vetoed not call these. - // All functions (De)Select/Row/Col/Cell, SelectAll go to (De)SelectBlock. - // ClearSelection deselects everything and sends a single event with - // wxSheetBlock(0,0,rows,cols) to imply everything is cleared. - - // To override the selection mechanism you only need to override, - // HasSelection, IsCell/Row/ColSelected, (De)SelectBlock, and ClearSelection. - - // Is there any selection, if selecting, includes the active selection block - // which is not yet part of underlying selection system - virtual bool HasSelection(bool selecting = true) const; - // Are these coords within either the selecting block or selection - virtual bool IsCellSelected( const wxSheetCoords& coords ) const; - bool IsCellSelected( int row, int col ) const { return IsCellSelected(wxSheetCoords(row, col)); } - virtual bool IsRowSelected( int row ) const; - virtual bool IsColSelected( int col ) const; - // Are we currently in the middle of a selection - bool IsSelecting() const { return !GetSelectingBlock().IsEmpty(); } - - void SetSelectionMode(wxSheetSelectionMode_Type selmode); - int GetSelectionMode() const { return GetSheetRefData()->m_selectionMode; } - bool HasSelectionMode(int mode) { return (GetSelectionMode() & mode) != 0; } - - virtual bool SelectRow( int row, bool addToSelected = false, bool sendEvt = false ); - virtual bool SelectRows( int rowTop, int rowBottom, bool addToSelected = false, bool sendEvt = false ); - virtual bool SelectCol( int col, bool addToSelected = false, bool sendEvt = false ); - virtual bool SelectCols( int colLeft, int colRight, bool addToSelected = false, bool sendEvt = false ); - virtual bool SelectCell( const wxSheetCoords& coords, bool addToSelected = false, bool sendEvt = false ); - virtual bool SelectBlock( const wxSheetBlock& block, bool addToSelected = false, - bool sendEvt = false ); - // selects everything to numRows, numCols - virtual bool SelectAll(bool sendEvt = false); - - virtual bool DeselectRow( int row, bool sendEvt = false ); - virtual bool DeselectRows( int rowTop, int rowBottom, bool sendEvt = false ); - virtual bool DeselectCol( int col, bool sendEvt = false ); - virtual bool DeselectCols( int colLeft, int colRight, bool sendEvt = false ); - virtual bool DeselectCell( const wxSheetCoords& coords, bool sendEvt = false ); - virtual bool DeselectBlock( const wxSheetBlock& block, bool sendEvt = false ); - // clears selection, single deselect event numRows, numCols - virtual bool ClearSelection(bool send_event = false); - - // toggle the selection of a single cell, row, or col - // addToSelected applies to a selection only, ignored if a deselection - virtual bool ToggleCellSelection( const wxSheetCoords& coords, - bool addToSelected = false, bool sendEvt = false ); - virtual bool ToggleRowSelection( int row, - bool addToSelected = false, bool sendEvt = false ); - virtual bool ToggleColSelection( int col, - bool addToSelected = false, bool sendEvt = false ); - - // Get a pointer to the selection mechanism. You are free to do what you - // want with it, do a ForceRefresh to update the grid when done. - wxSheetSelection* GetSelection() const { return GetSheetRefData()->m_selection; } - - // During a selection this is the selecting block, else empty - const wxSheetBlock& GetSelectingBlock() const { return GetSheetRefData()->m_selectingBlock; } - const wxSheetCoords& GetSelectingAnchor() const { return GetSheetRefData()->m_selectingAnchor; } - - // These are internal use functions to highlight a block during mouse - // dragging or keyboard selecting - void SetSelectingBlock(const wxSheetBlock& selectingBlock) { GetSheetRefData()->m_selectingBlock = selectingBlock; } - void SetSelectingAnchor(const wxSheetCoords& selectingAnchor) { GetSheetRefData()->m_selectingAnchor = selectingAnchor; } - - // while selecting set and draw m_selectingBlock highlight and clear up last - virtual void HighlightSelectingBlock( const wxSheetBlock& selectingBlock ); - void HighlightSelectingBlock( const wxSheetCoords& cornerCell, - const wxSheetCoords& otherCell ) - { HighlightSelectingBlock(wxSheetBlock(cornerCell, otherCell)); } - - // ------------------------------------------------------------------------ - // Copy/Paste functionality for strings - - // Copy the current selection using CopyCurrentSelectionInternal then - // to the wxClipboard using CopyInternalSelectionToClipboard - bool CopyCurrentSelectionToClipboard(bool copy_cursor = true, - const wxChar& colSep = wxT('\t')); - // Copy the current selection to an internal copied selection mechanism - // storing both the positions and values of the selected cells, if no - // selection and copy_cursor then just copy the cursor value - bool CopyCurrentSelectionInternal(bool copy_cursor = true); - // Copy the internal selection to the wxClipboard as both a string using - // colSep to separate columns and as an internal representation for - // pasting back into the wxSheet. - bool CopyInternalSelectionToClipboard(const wxChar& colSep = wxT('\t')); - // Copy the internal selection to a clipboard string - // uses colSep for cols and \n for rows, called by CopySelectionToClipboard - wxString CopyInternalSelectionToString(const wxChar& colSep = wxT('\t')); - - // Copies the string (perhaps from the clipboard) to the internal copied - // selection uses colSep for cols and \n for rows, used by PasteFromClipboard - bool CopyStringToSelection(const wxString& value, const wxChar& colSep = wxT('\t')); - - // Tries to get the clipboard data as wxSheet's clipboard data - // representation else use CopyStringToSelection to convert a string - // using colSep as the column separator and \n as row separator. - bool PasteFromClipboard(const wxSheetCoords &topLeft = wxNullSheetCoords, - const wxChar& colSep = wxT('\t')); - // Paste the internal copied selection at the topLeft coords or if - // topLeft = wxNullSheetCoords then if IsSelection use the upper right of - // the current selection and only paste into currently selected cells. - // If no selection the the cursor is the topLeft cell. - virtual bool PasteInternalCopiedSelection(const wxSheetCoords &topLeft = wxNullSheetCoords); - // Are the cells being pasted right now, use this in the table's - // SetCellValue and AppendXXX to differentiate between a user typing - bool CurrentlyPasting() const { return GetSheetRefData()->m_pasting; } - - // ------------------------------------------------------------------------ - // Edit control functions (mostly used internally) - - // Is/Make the whole sheet editable or readonly - bool IsEditable() const { return GetSheetRefData()->m_editable; } - void EnableEditing( bool edit ); - - // enable and show the editor control at the coords, returns sucess, ie. !vetoed - bool EnableCellEditControl( const wxSheetCoords& coords ); - // hide and disable the editor and save the value if save_value, returns sucess, ie. !vetoed - bool DisableCellEditControl( bool save_value ); - // is this cell valid and editable - bool CanEnableCellControl(const wxSheetCoords& coords) const; - // is the cell editor created (may not be shown though) - bool IsCellEditControlCreated() const; - // is the cell editor valid and shown - bool IsCellEditControlShown() const; - - // Create and show the appropriate editor at the EnableCellEditControl coords - // this is called internally by EnableCellEditControl, but if you call - // HideCellEditControl and if IsCellEditControlCreated then you can reshow - // it with this, returns sucess - bool ShowCellEditControl(); - // Hide the editor, doesn't destroy it (use DisableCellEditControl) - // check if IsCellEditControlShown first, returns sucess - bool HideCellEditControl(); - // Save the value of the editor, check IsCellEditControlEnabled() first - void SaveEditControlValue(); - - // Get the current editor, !Ok() if !IsCellEditControlCreated() - const wxSheetCellEditor& GetEditControl() const { return GetSheetRefData()->m_cellEditor; } - // These are the coords of the editor, check IsCellEditControlCreated before using - const wxSheetCoords& GetEditControlCoords() const { return GetSheetRefData()->m_cellEditorCoords; } - - // ------------------------------------------------------------------------ - // Drawing functions - - // Code that does a lot of grid modification can be enclosed - // between BeginBatch() and EndBatch() calls to avoid screen flicker - // EndBatch's refresh = false will not refresh when batchCount is 0 - void BeginBatch() { m_batchCount++; } - void EndBatch(bool refresh=true); - int GetBatchCount() const { return m_batchCount; } - - // Use ForceRefresh, rather than wxWindow::Refresh(), to force an - // immediate repainting of the grid. No effect if GetBatchCount() > 0 - // This function is necessary because wxSheet has a minimal OnPaint() - // handler to reduce screen flicker. - void ForceRefresh() { BeginBatch(); EndBatch(); } - - // *** Use these redrawing functions to ensure refed sheets are redrawn *** - - // Refresh a single cell, can also draw cells for labels using -1 notation - // does nothing if cell !visible, or GetBatchCount != 0 - // if single_cell then literally draw only the single cell, else draw the - // cell to left in case the overflow marker needs to be drawn and the - // cells to the right in case this cell overflows. - void RefreshCell(const wxSheetCoords& coords, bool single_cell = true); - // Refresh a block of cells in any/all of the windows by chopping up the block, - // uses -1 notation to refresh labels - void RefreshBlock(const wxSheetBlock& block); - // Refresh a single row, row = -1 refreshes all col labels, - // does nothing if row !visible, or GetBatchCount != 0 - void RefreshRow(int row); - // Refresh a single col, col = -1 refreshes all row labels, - // does nothing if col !visible, or GetBatchCount != 0 - void RefreshCol(int col); - // Refresh is called using a rect surrounding the block - // does nothing if block IsEmpty, !visible, or GetBatchCount != 0 - void RefreshGridCellBlock( const wxSheetBlock& block ); - // After SetAttr call this can appropriately refresh the wxSheet areas - void RefreshAttrChange(const wxSheetCoords& coords, wxSheetAttr_Type type); - - // ************************************************************************ - // Drawing implementation - - // Refresh an area of the window that calculates the smaller rects for - // each individual window (row/col/corner...) and calls Refresh(subRect) - // The rect is the logical rect, not the scrolled device rect - virtual void Refresh(bool eraseb = true, const wxRect* rect = NULL); - - // These directly call wxWindow::Refresh for the appropriate windows - // The input rect doesn't have to be clipped to the visible window since - // this function takes care of that, but it should be in client coords. - void RefreshGridWindow(bool eraseb = true, const wxRect* rect = NULL); - void RefreshRowLabelWindow(bool eraseb = true, const wxRect* rect = NULL); - void RefreshColLabelWindow(bool eraseb = true, const wxRect* rect = NULL); - void RefreshCornerLabelWindow(bool eraseb = true, const wxRect* rect = NULL); - - // Don't use these if you plan to use the splitter since they only act - // on this sheet. - - // These functions are called by the OnPaint handler of these windows - // use these to add "extra touches" before or after redrawing. - // The dc should be prepared before calling these. - virtual void PaintGridWindow( wxDC& dc, const wxRegion& reg ); - virtual void PaintRowLabelWindow( wxDC& dc, const wxRegion& reg ); - virtual void PaintColLabelWindow( wxDC& dc, const wxRegion& reg ); - virtual void PaintCornerLabelWindow( wxDC& dc, const wxRegion& reg ); - virtual void PaintSheetWindow( wxDC& dc, const wxRegion& reg ); - - // draws a bunch of blocks of grid cells onto the given DC - virtual void DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel ); - // Draw the area below and to right of grid up to scrollbars - virtual void DrawGridSpace( wxDC& dc ); - // draw the border around a single cell - virtual void DrawCellBorder( wxDC& dc, const wxSheetCoords& coords ); - // Draw all the grid lines in the region - virtual void DrawAllGridLines( wxDC& dc, const wxRegion& reg ); - // Draw a single cell - virtual void DrawCell( wxDC& dc, const wxSheetCoords& coords ); - // Calls DrawCursorCellHighlight if contained within this selection - virtual void DrawCursorHighlight( wxDC& dc, const wxSheetSelection& blockSel ); - // Draw the cursor cell highlight - virtual void DrawCursorCellHighlight(wxDC& dc, const wxSheetCellAttr &attr); - - // draw wxSheetRowLabelWindow labels - virtual void DrawRowLabels( wxDC& dc, const wxArrayInt& rows ); - // draw wxSheetColLabelWindow labels - virtual void DrawColLabels( wxDC& dc, const wxArrayInt& cols ); - // wxSheetCornerLabelWindow label - virtual void DrawCornerLabel( wxDC& dc ); - - // Draw the row/col resizing marker and if newDragPos != -1, set the - // new position of the marker - virtual void DrawRowColResizingMarker( int newDragPos = -1 ); - - // Draw the splitter button in the rectangle - virtual void DrawSplitterButton(wxDC &dc, const wxRect& rect); - - // Calculate the Row/ColLabels and Cells exposed for the wxRegion - // returns false if none, used for redrawing windows - bool CalcRowLabelsExposed( const wxRegion& reg, wxArrayInt& rows ) const; - bool CalcColLabelsExposed( const wxRegion& reg, wxArrayInt& cols ) const; - bool CalcCellsExposed( const wxRegion& reg, wxSheetSelection& blockSel ) const; - int FindOverflowCell( const wxSheetCoords& coords, wxDC& dc ); - - // helper drawing functions - void DrawTextRectangle( wxDC& dc, const wxString& value, const wxRect& rect, - int alignment = wxALIGN_LEFT|wxALIGN_TOP, - int textOrientation = wxHORIZONTAL ); - - void DrawTextRectangle( wxDC& dc, const wxArrayString& lines, const wxRect&, - int alignment = wxALIGN_LEFT|wxALIGN_TOP, - int textOrientation = wxHORIZONTAL ); - - // Split string by '\n' and add to array, returning the number of lines - // returns 0 for empty string. - int StringToLines( const wxString& value, wxArrayString& lines ) const; - // Get the size of the lines drawn horizontally, returs true if size > 0 - bool GetTextBoxSize( wxDC& dc, const wxArrayString& lines, - long *width, long *height ) const; - - // ------------------------------------------------------------------------ - // Geometry utility functions, pixel <-> cell etc - - // Note that all of these functions work with the logical coordinates of - // grid cells and labels so you will need to convert from device - // coordinates for mouse events etc. - // clipToMinMax means that the return value will be within the grid cells - // if !clipToMinMax and out of bounds it returns -1. - // Use ContainsGridXXX to verify validity, -1 doesn't mean label - wxSheetCoords XYToGridCell( int x, int y, bool clipToMinMax = false ) const; - int YToGridRow( int y, bool clipToMinMax = false ) const; - int XToGridCol( int x, bool clipToMinMax = false ) const; - - // return the row/col number that the x/y coord is near the edge of, or - // -1 if not near an edge, uses WXSHEET_LABEL_EDGE_ZONE - // Use ContainsGridXXX to verify validity, -1 doesn't mean label - int YToEdgeOfGridRow( int y ) const; - int XToEdgeOfGridCol( int x ) const; - - // Get a rect bounding the cell, handles spanning cells and the label - // windows using the -1 notation, getDeviceRect calls CalcScrolledRect - wxRect CellToRect( const wxSheetCoords& coords, bool getDeviceRect = false ) const; - // Get a rect bounding the block, handles label windows using the -1 notation, - // getDeviceRect calls CalcScrolledRect - wxRect BlockToRect( const wxSheetBlock& block, bool getDeviceRect = false ) const; - - // Expand the block by unioning with intersecting spanned cells - wxSheetBlock ExpandSpannedBlock( const wxSheetBlock& block ) const; - - // Convert the block of cells into a wxRect in device coords, expands the - // block to contain spanned cells if expand_spanned. - // These functions do handle label cells, but if you span the block from a label - // into the grid then the rect will overlap the windows, probably not what you want. - wxRect BlockToDeviceRect( const wxSheetBlock& block, bool expand_spanned = true ) const; - wxRect BlockToLogicalRect( const wxSheetBlock& block, bool expand_spanned = true ) const; - - // Convert the rect in pixels into a block of cells for the grid - // if wholeCell then only include cells in the block that are - // wholly contained by the rect - wxSheetBlock LogicalGridRectToBlock(const wxRect &rect, bool wholeCell = false) const; - - // get a block containing all the currently (partially/fully) visible cells - wxSheetBlock GetVisibleGridCellsBlock(bool wholeCellVisible = false) const; - - // Align the size of an object inside the rect using wxALIGN enums - // if inside then align it to the left if it would have overflown - // always pins size to left hand side - wxPoint AlignInRect( int align, const wxRect& rect, const wxSize& size, bool inside=true ) const; - - // ------------------------------------------------------------------------ - // Scrolling for the window, everything is done with pixels - // there is no need for scroll units and they only cause sizing problems - - // Get the scrolled origin of the grid in pixels - const wxPoint& GetGridOrigin() const { return m_gridOrigin; } - // Set the absolute scrolled origin of the grid window in pixels - // this checks validity and ensures proper positioning. - // Use x or y = -1 to not change the origin in the x or y direction - // Unless setting from a scrollbar event use adjustScrollBars=true - virtual void SetGridOrigin(int x, int y, bool adjustScrollBars = true, bool sendEvt=false); - void SetGridOrigin(const wxPoint& pt, bool adjustScrollBars = true, bool sendEvt=false) - { SetGridOrigin(pt.x, pt.y, adjustScrollBars, sendEvt); } - - // Get the virtual size of the grid in pixels, includes extra width/height - wxSize GetGridVirtualSize(bool add_margin=true) const; - - // Get the extent of the grid, this may be more than the virtual size if the - // grid is smaller than the containing window - wxSize GetGridExtent() const; - - // Same as wxScrolledWindow Calc(Un)ScrolledPosition - void CalcScrolledPosition(int x, int y, int *xx, int *yy) const - { if (xx) *xx = x - m_gridOrigin.x; if (yy) *yy = y - m_gridOrigin.y; } - void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const - { if (xx) *xx = x + m_gridOrigin.x; if (yy) *yy = y + m_gridOrigin.y; } - wxPoint CalcScrolledPosition(const wxPoint& pt) const { return pt - m_gridOrigin; } - wxPoint CalcUnscrolledPosition(const wxPoint& pt) const { return pt + m_gridOrigin; } - - // returns the scrolled position of the rect, logical -> device coords - wxRect CalcScrolledRect(const wxRect &r) const - { return wxRect(r.x-m_gridOrigin.x, r.y-m_gridOrigin.y, r.width, r.height); } - // returns the unscrolled position of the rect, device -> logical coords - wxRect CalcUnscrolledRect(const wxRect &r) const - { return wxRect(r.x+m_gridOrigin.x, r.y+m_gridOrigin.y, r.width, r.height); } - - // Adjust the scrollbars to match the size/origin of the grid window - // call this after SetScrollBarMode - virtual void AdjustScrollbars(bool calc_win_sizes = true); - - enum SB_Mode - { - SB_AS_NEEDED = 0x0, // Show the scrollbars as needed - SB_HORIZ_NEVER = 0x1, // Never show horiz scrollbar, even if needed - SB_VERT_NEVER = 0x2, // Never show vert scrollbar, even if needed - SB_NEVER = SB_HORIZ_NEVER | SB_VERT_NEVER, - SB_HORIZ_ALWAYS = 0x4, // Always show horiz scrollbar - SB_VERT_ALWAYS = 0x8, // Always show vert scrollbar - SB_ALWAYS = SB_HORIZ_ALWAYS | SB_VERT_ALWAYS, - - SB_HORIZ_MASK = SB_HORIZ_NEVER|SB_HORIZ_ALWAYS, - SB_VERT_MASK = SB_VERT_NEVER|SB_VERT_ALWAYS - }; - - int GetScrollBarMode() const { return m_scrollBarMode; } - void SetScrollBarMode(int mode) { m_scrollBarMode = mode; } - void SetHorizontalScrollBarMode(int mode) - { m_scrollBarMode &= (~SB_HORIZ_MASK); m_scrollBarMode |= mode; } - void SetVerticalScrollBarMode(int mode) - { m_scrollBarMode &= (~SB_VERT_MASK); m_scrollBarMode |= mode; } - - bool NeedsVerticalScrollBar() const { return GetGridVirtualSize().y > m_gridWin->GetSize().y; } - bool NeedsHorizontalScrollBar() const { return GetGridVirtualSize().x > m_gridWin->GetSize().x; } - - // SetDeviceOrigin for the wxDC as appropriate for these windows - - virtual void PrepareGridDC( wxDC& dc ); - virtual void PrepareRowLabelDC( wxDC& dc ); - virtual void PrepareColLabelDC( wxDC& dc ); - - // ------------------------------------------------------------------------ - // Splitting of the grid window - note that the sheet does not split at all - // and that only a wxEVT_SHEET_SPLIT_BEGIN event is sent to notify the - // parent that splitting should take place, see wxSheetSplitter. - // The "splitter" is just two small rectangles at the top of the vertical - // scrollbar and right of the horizontal scrollbar. They're only shown - // when the scrollbars are shown and if splitting is enabled. - // Call CalcWindowSizes after setting to update the display. - - bool GetEnableSplitVertically() const { return m_enable_split_vert; } - bool GetEnableSplitHorizontally() const { return m_enable_split_horiz; } - - void EnableSplitVertically(bool can_split) { m_enable_split_vert = can_split; } - void EnableSplitHorizontally(bool can_split) { m_enable_split_horiz = can_split; } - - // ------------------------------------------------------------------------ - // implementation - - // helper function to set only the horiz or vert component of orig_align - // returns modified alignment, doesn't modify any bits not in wxAlignment - // use -1 for hAlign/vAlign to not modify that direction - static int SetAlignment(int orig_align, int hAlign, int vAlign); - - // Do any of the windows of the wxSheet have the focus? - bool HasFocus() const; - - // Accessors for component windows - wxSheetChildWindow* GetGridWindow() const { return m_gridWin; } - wxSheetChildWindow* GetRowLabelWindow() const { return m_rowLabelWin; } - wxSheetChildWindow* GetColLabelWindow() const { return m_colLabelWin; } - wxSheetChildWindow* GetCornerLabelWindow() const { return m_cornerLabelWin; } - // Get the window with these coords, uses -1 notation - wxWindow* GetWindowForCoords( const wxSheetCoords& coords ) const; - - // ------ event handlers - void OnMouse( wxMouseEvent& event ); - void OnMouseWheel( wxMouseEvent& event ); - - void ProcessSheetMouseEvent( wxMouseEvent& event ); - void ProcessRowLabelMouseEvent( wxMouseEvent& event ); - void ProcessColLabelMouseEvent( wxMouseEvent& event ); - void ProcessCornerLabelMouseEvent( wxMouseEvent& event ); - void ProcessGridCellMouseEvent( wxMouseEvent& event ); - - void OnScroll( wxScrollEvent& event ); - - // End the row/col dragging, returns true if width/height have changed - bool DoEndDragResizeRowCol(); - - // ------ control types - enum { wxSHEET_TEXTCTRL = 2100, - wxSHEET_CHECKBOX, - wxSHEET_CHOICE, - wxSHEET_COMBOBOX }; - - enum - { - ID_HORIZ_SCROLLBAR = 1, - ID_VERT_SCROLLBAR, - ID_MOUSE_DRAG_TIMER, - ID_GRID_WINDOW, - ID_ROW_LABEL_WINDOW, - ID_COL_LABEL_WINDOW, - ID_CORNER_LABEL_WINDOW - }; - - virtual void CalcWindowSizes(bool adjustScrollBars = true); - virtual void Fit() { AutoSize(); } // overridden wxWindow methods - - // Get the ref counted data the sheet uses, *please* try to not access this - // directly if a functions exists to do it for you. - wxSheetRefData* GetSheetRefData() const { return (wxSheetRefData*)GetRefData(); } - - // Create and send wxSheetXXXEvent depending on type and fill extra data - // from a wxKeyEvent or wxMouseEvent (if NULL all keydown are set false) - // returns EVT_VETOED/SKIPPED/CLAIMED - enum - { - EVT_VETOED = -1, // veto was called on the event - EVT_SKIPPED = 0, // no evt handler found or evt was Skip()ed - EVT_CLAIMED = 1 // event was handled and not Skip()ed - }; - int SendEvent( const wxEventType type, const wxSheetCoords& coords, - wxEvent* mouseOrKeyEvt = NULL ); - - int SendRangeEvent( const wxEventType type, const wxSheetBlock& block, - bool selecting, bool add, wxEvent* mouseOrKeyEvt = NULL ); - // Just send the event returning EVT_VETOED/SKIPPED/CLAIMED - int DoSendEvent( wxSheetEvent* event ); - - enum MouseCursorMode - { - WXSHEET_CURSOR_SELECT_CELL = 0x0001, - WXSHEET_CURSOR_SELECT_ROW = 0x0002, - WXSHEET_CURSOR_SELECT_COL = 0x0004, - WXSHEET_CURSOR_SELECTING = WXSHEET_CURSOR_SELECT_CELL|WXSHEET_CURSOR_SELECT_ROW|WXSHEET_CURSOR_SELECT_COL, - WXSHEET_CURSOR_RESIZE_ROW = 0x0008, - WXSHEET_CURSOR_RESIZE_COL = 0x0010, - WXSHEET_CURSOR_RESIZING = WXSHEET_CURSOR_RESIZE_ROW|WXSHEET_CURSOR_RESIZE_COL, - WXSHEET_CURSOR_SPLIT_VERTICAL = 0x0020, - WXSHEET_CURSOR_SPLIT_HORIZONTAL = 0x0040, - WXSHEET_CURSOR_SPLITTING = WXSHEET_CURSOR_SPLIT_VERTICAL|WXSHEET_CURSOR_SPLIT_HORIZONTAL - }; - // Set the m_mouseCursor for the wxCursor and m_mouseCursorMode for behavior - // you should always use it and not set m_mouseCursor[Mode] directly! - void SetMouseCursorMode( MouseCursorMode mode, wxWindow *win ); - // Get the mouse cursor mode, &ed with mask, default returns original value - int GetMouseCursorMode(int mask = ~0) const { return (m_mouseCursorMode & mask); } - // Is the mouse cursor in the mode? - bool HasMouseCursorMode(int mode) const { return GetMouseCursorMode(mode) != 0; } - - // Set the window that has capture, releases the previous one if necessary - // always use this, set with NULL to release mouse - void SetCaptureWindow( wxWindow *win ); - wxWindow *GetCaptureWindow() const { return m_winCapture; } + if (yy) { + *yy = y - m_gridOrigin.y; + } + } + void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const + { + if (xx) { + *xx = x + m_gridOrigin.x; + } + if (yy) { + *yy = y + m_gridOrigin.y; + } + } + wxPoint CalcScrolledPosition(const wxPoint &pt) const { return pt - m_gridOrigin; } + wxPoint CalcUnscrolledPosition(const wxPoint &pt) const { return pt + m_gridOrigin; } + + // returns the scrolled position of the rect, logical -> device coords + wxRect CalcScrolledRect(const wxRect &r) const + { + return wxRect(r.x - m_gridOrigin.x, r.y - m_gridOrigin.y, r.width, r.height); + } + // returns the unscrolled position of the rect, device -> logical coords + wxRect CalcUnscrolledRect(const wxRect &r) const + { + return wxRect(r.x + m_gridOrigin.x, r.y + m_gridOrigin.y, r.width, r.height); + } + + // Adjust the scrollbars to match the size/origin of the grid window + // call this after SetScrollBarMode + virtual void AdjustScrollbars(bool calc_win_sizes = true); + + enum SB_Mode { + SB_AS_NEEDED = 0x0, // Show the scrollbars as needed + SB_HORIZ_NEVER = 0x1, // Never show horiz scrollbar, even if needed + SB_VERT_NEVER = 0x2, // Never show vert scrollbar, even if needed + SB_NEVER = SB_HORIZ_NEVER | SB_VERT_NEVER, + SB_HORIZ_ALWAYS = 0x4, // Always show horiz scrollbar + SB_VERT_ALWAYS = 0x8, // Always show vert scrollbar + SB_ALWAYS = SB_HORIZ_ALWAYS | SB_VERT_ALWAYS, + + SB_HORIZ_MASK = SB_HORIZ_NEVER | SB_HORIZ_ALWAYS, + SB_VERT_MASK = SB_VERT_NEVER | SB_VERT_ALWAYS + }; + + int GetScrollBarMode() const { return m_scrollBarMode; } + void SetScrollBarMode(int mode) { m_scrollBarMode = mode; } + void SetHorizontalScrollBarMode(int mode) + { + m_scrollBarMode &= (~SB_HORIZ_MASK); + m_scrollBarMode |= mode; + } + void SetVerticalScrollBarMode(int mode) + { + m_scrollBarMode &= (~SB_VERT_MASK); + m_scrollBarMode |= mode; + } + + bool NeedsVerticalScrollBar() const { return GetGridVirtualSize().y > m_gridWin->GetSize().y; } + bool NeedsHorizontalScrollBar() const { return GetGridVirtualSize().x > m_gridWin->GetSize().x; } + + // SetDeviceOrigin for the wxDC as appropriate for these windows + + virtual void PrepareGridDC(wxDC &dc); + virtual void PrepareRowLabelDC(wxDC &dc); + virtual void PrepareColLabelDC(wxDC &dc); + + // ------------------------------------------------------------------------ + // Splitting of the grid window - note that the sheet does not split at all + // and that only a wxEVT_SHEET_SPLIT_BEGIN event is sent to notify the + // parent that splitting should take place, see wxSheetSplitter. + // The "splitter" is just two small rectangles at the top of the vertical + // scrollbar and right of the horizontal scrollbar. They're only shown + // when the scrollbars are shown and if splitting is enabled. + // Call CalcWindowSizes after setting to update the display. + + bool GetEnableSplitVertically() const { return m_enable_split_vert; } + bool GetEnableSplitHorizontally() const { return m_enable_split_horiz; } + + void EnableSplitVertically(bool can_split) { m_enable_split_vert = can_split; } + void EnableSplitHorizontally(bool can_split) { m_enable_split_horiz = can_split; } + + // ------------------------------------------------------------------------ + // implementation + + // helper function to set only the horiz or vert component of orig_align + // returns modified alignment, doesn't modify any bits not in wxAlignment + // use -1 for hAlign/vAlign to not modify that direction + static int SetAlignment(int orig_align, int hAlign, int vAlign); + + // Do any of the windows of the wxSheet have the focus? + bool HasFocus() const; + + // Accessors for component windows + wxSheetChildWindow *GetGridWindow() const { return m_gridWin; } + wxSheetChildWindow *GetRowLabelWindow() const { return m_rowLabelWin; } + wxSheetChildWindow *GetColLabelWindow() const { return m_colLabelWin; } + wxSheetChildWindow *GetCornerLabelWindow() const { return m_cornerLabelWin; } + // Get the window with these coords, uses -1 notation + wxWindow *GetWindowForCoords(const wxSheetCoords &coords) const; + + // ------ event handlers + void OnMouse(wxMouseEvent &event); + void OnMouseWheel(wxMouseEvent &event); + + void ProcessSheetMouseEvent(wxMouseEvent &event); + void ProcessRowLabelMouseEvent(wxMouseEvent &event); + void ProcessColLabelMouseEvent(wxMouseEvent &event); + void ProcessCornerLabelMouseEvent(wxMouseEvent &event); + void ProcessGridCellMouseEvent(wxMouseEvent &event); + + void OnScroll(wxScrollEvent &event); + + // End the row/col dragging, returns true if width/height have changed + bool DoEndDragResizeRowCol(); + + // ------ control types + enum { wxSHEET_TEXTCTRL = 2100, wxSHEET_CHECKBOX, wxSHEET_CHOICE, wxSHEET_COMBOBOX }; + + enum { + ID_HORIZ_SCROLLBAR = 1, + ID_VERT_SCROLLBAR, + ID_MOUSE_DRAG_TIMER, + ID_GRID_WINDOW, + ID_ROW_LABEL_WINDOW, + ID_COL_LABEL_WINDOW, + ID_CORNER_LABEL_WINDOW + }; + + virtual void CalcWindowSizes(bool adjustScrollBars = true); + virtual void Fit() { AutoSize(); } // overridden wxWindow methods + + // Get the ref counted data the sheet uses, *please* try to not access this + // directly if a functions exists to do it for you. + wxSheetRefData *GetSheetRefData() const { return (wxSheetRefData *)GetRefData(); } + + // Create and send wxSheetXXXEvent depending on type and fill extra data + // from a wxKeyEvent or wxMouseEvent (if NULL all keydown are set false) + // returns EVT_VETOED/SKIPPED/CLAIMED + enum { + EVT_VETOED = -1, // veto was called on the event + EVT_SKIPPED = 0, // no evt handler found or evt was Skip()ed + EVT_CLAIMED = 1 // event was handled and not Skip()ed + }; + int SendEvent(const wxEventType type, const wxSheetCoords &coords, + wxEvent *mouseOrKeyEvt = NULL); + + int SendRangeEvent(const wxEventType type, const wxSheetBlock &block, bool selecting, bool add, + wxEvent *mouseOrKeyEvt = NULL); + // Just send the event returning EVT_VETOED/SKIPPED/CLAIMED + int DoSendEvent(wxSheetEvent *event); + + enum MouseCursorMode { + WXSHEET_CURSOR_SELECT_CELL = 0x0001, + WXSHEET_CURSOR_SELECT_ROW = 0x0002, + WXSHEET_CURSOR_SELECT_COL = 0x0004, + WXSHEET_CURSOR_SELECTING = + WXSHEET_CURSOR_SELECT_CELL | WXSHEET_CURSOR_SELECT_ROW | WXSHEET_CURSOR_SELECT_COL, + WXSHEET_CURSOR_RESIZE_ROW = 0x0008, + WXSHEET_CURSOR_RESIZE_COL = 0x0010, + WXSHEET_CURSOR_RESIZING = WXSHEET_CURSOR_RESIZE_ROW | WXSHEET_CURSOR_RESIZE_COL, + WXSHEET_CURSOR_SPLIT_VERTICAL = 0x0020, + WXSHEET_CURSOR_SPLIT_HORIZONTAL = 0x0040, + WXSHEET_CURSOR_SPLITTING = WXSHEET_CURSOR_SPLIT_VERTICAL | WXSHEET_CURSOR_SPLIT_HORIZONTAL + }; + // Set the m_mouseCursor for the wxCursor and m_mouseCursorMode for behavior + // you should always use it and not set m_mouseCursor[Mode] directly! + void SetMouseCursorMode(MouseCursorMode mode, wxWindow *win); + // Get the mouse cursor mode, &ed with mask, default returns original value + int GetMouseCursorMode(int mask = ~0) const { return (m_mouseCursorMode & mask); } + // Is the mouse cursor in the mode? + bool HasMouseCursorMode(int mode) const { return GetMouseCursorMode(mode) != 0; } + + // Set the window that has capture, releases the previous one if necessary + // always use this, set with NULL to release mouse + void SetCaptureWindow(wxWindow *win); + wxWindow *GetCaptureWindow() const { return m_winCapture; } protected: - - bool DoUpdateRows(size_t row, int numRows, int update = wxSHEET_UpdateAll ); - bool DoUpdateCols(size_t col, int numCols, int update = wxSHEET_UpdateAll ); - - virtual wxSize DoGetBestSize() const; - void OnSize( wxSizeEvent& event ); - - wxWindow *m_winCapture; // the window that captured the mouse (don't use!) - - wxSheetChildWindow *m_gridWin; - wxSheetChildWindow *m_rowLabelWin; - wxSheetChildWindow *m_colLabelWin; - wxSheetChildWindow *m_cornerLabelWin; - wxScrollBar *m_horizScrollBar; - wxScrollBar *m_vertScrollBar; - - wxPoint m_gridOrigin; // origin of the gridWin in pixels - int m_scrollBarMode; - - bool m_keySelecting; - - // cell attribute cache - wxSheetCellAttr m_cacheAttr; - wxSheetCoords m_cacheAttrCoords; - int m_cacheAttrType; - - // invalidates the attribute cache - void ClearAttrCache(); - // adds an attribute to cache - void CacheAttr(const wxSheetCoords& coords, const wxSheetCellAttr &attr, - wxSheetAttr_Type type ) const; - // looks for an attr in cache, returns true if found - bool LookupAttr(const wxSheetCoords& coords, wxSheetAttr_Type type, - wxSheetCellAttr &attr) const; - - bool m_inOnKeyDown; - int m_batchCount; - bool m_resizing; - - enum KeyModifiers - { - NO_MODIFIERS = 0, - CTRL_DOWN = 0x0001, - SHIFT_DOWN = 0x0002, - ALT_DOWN = 0x0004, - META_DOWN = 0x0008 // meta is numlock in GTK so it's ignored - }; - int GetKeyModifiers(wxEvent *mouseOrKeyEvent) const; - - MouseCursorMode m_mouseCursorMode; - MouseCursorMode m_mouseCursor; - - int m_dragLastPos; - int m_dragRowOrCol; - bool m_isDragging; - wxPoint m_startDragPos; - wxPoint m_mousePos; - - bool m_waitForSlowClick; - - // mouse timer for smooth scrolling when selecting or resizing off window - void StartMouseTimer(); - void StopMouseTimer(); - void OnMouseTimer( wxTimerEvent &event ); - wxTimer *m_mouseTimer; - - bool m_enable_split_vert; - bool m_enable_split_horiz; - wxRect m_vertSplitRect; // pos/size of the splitter rect, 0 if not shown - wxRect m_horizSplitRect; // pos/size of the splitter rect, 0 if not shown - - void OnPaint( wxPaintEvent& event ); - void OnEraseBackground( wxEraseEvent& ); - void OnKeyDown( wxKeyEvent& event ); - void OnKeyUp( wxKeyEvent& event ); - void OnChar( wxKeyEvent& event ); // let wxWidgets translate numpad keys - - // ------ functions to get/send data (see also public functions) - bool GetModelValues(); - bool SetModelValues(); + bool DoUpdateRows(size_t row, int numRows, int update = wxSHEET_UpdateAll); + bool DoUpdateCols(size_t col, int numCols, int update = wxSHEET_UpdateAll); + + virtual wxSize DoGetBestSize() const; + void OnSize(wxSizeEvent &event); + + wxWindow *m_winCapture; // the window that captured the mouse (don't use!) + + wxSheetChildWindow *m_gridWin; + wxSheetChildWindow *m_rowLabelWin; + wxSheetChildWindow *m_colLabelWin; + wxSheetChildWindow *m_cornerLabelWin; + wxScrollBar *m_horizScrollBar; + wxScrollBar *m_vertScrollBar; + + wxPoint m_gridOrigin; // origin of the gridWin in pixels + int m_scrollBarMode; + + bool m_keySelecting; + + // cell attribute cache + wxSheetCellAttr m_cacheAttr; + wxSheetCoords m_cacheAttrCoords; + int m_cacheAttrType; + + // invalidates the attribute cache + void ClearAttrCache(); + // adds an attribute to cache + void CacheAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr, + wxSheetAttr_Type type) const; + // looks for an attr in cache, returns true if found + bool LookupAttr(const wxSheetCoords &coords, wxSheetAttr_Type type, wxSheetCellAttr &attr) const; + + bool m_inOnKeyDown; + int m_batchCount; + bool m_resizing; + + enum KeyModifiers { + NO_MODIFIERS = 0, + CTRL_DOWN = 0x0001, + SHIFT_DOWN = 0x0002, + ALT_DOWN = 0x0004, + META_DOWN = 0x0008 // meta is numlock in GTK so it's ignored + }; + int GetKeyModifiers(wxEvent *mouseOrKeyEvent) const; + + MouseCursorMode m_mouseCursorMode; + MouseCursorMode m_mouseCursor; + + int m_dragLastPos; + int m_dragRowOrCol; + bool m_isDragging; + wxPoint m_startDragPos; + wxPoint m_mousePos; + + bool m_waitForSlowClick; + + // mouse timer for smooth scrolling when selecting or resizing off window + void StartMouseTimer(); + void StopMouseTimer(); + void OnMouseTimer(wxTimerEvent &event); + wxTimer *m_mouseTimer; + + bool m_enable_split_vert; + bool m_enable_split_horiz; + wxRect m_vertSplitRect; // pos/size of the splitter rect, 0 if not shown + wxRect m_horizSplitRect; // pos/size of the splitter rect, 0 if not shown + + void OnPaint(wxPaintEvent &event); + void OnEraseBackground(wxEraseEvent &); + void OnKeyDown(wxKeyEvent &event); + void OnKeyUp(wxKeyEvent &event); + void OnChar(wxKeyEvent &event); // let wxWidgets translate numpad keys + + // ------ functions to get/send data (see also public functions) + bool GetModelValues(); + bool SetModelValues(); private: - void Init(); - friend class wxSheetTable; - DECLARE_DYNAMIC_CLASS(wxSheet) - DECLARE_EVENT_TABLE() - DECLARE_NO_COPY_CLASS(wxSheet) + void Init(); + friend class wxSheetTable; + DECLARE_DYNAMIC_CLASS(wxSheet) + DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxSheet) }; // ---------------------------------------------------------------------------- // wxSheetEvent // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetEvent : public wxNotifyEvent -{ +class WXDLLIMPEXP_SHEET wxSheetEvent : public wxNotifyEvent { public: - wxSheetEvent(int id=0, wxEventType type=wxEVT_NULL, wxObject* obj=NULL, - const wxSheetCoords &coords = wxNullSheetCoords, - const wxPoint &pos = wxPoint(-1, -1), bool sel = true); - - wxSheetEvent(const wxSheetEvent& event) : wxNotifyEvent(event), - m_coords(event.m_coords), m_pos(event.m_pos), - m_selecting(event.m_selecting), - m_control(event.m_control), m_shift(event.m_shift), - m_alt(event.m_alt), m_meta(event.m_meta) { } - - int GetRow() const { return m_coords.m_row; } - int GetCol() const { return m_coords.m_col; } - const wxSheetCoords& GetCoords() const { return m_coords; } - const wxPoint& GetPosition() const { return m_pos; } - bool Selecting() const { return m_selecting; } - bool ControlDown() const { return m_control; } - bool ShiftDown() const { return m_shift; } - bool AltDown() const { return m_alt; } - bool MetaDown() const { return m_meta; } - - // implementation - - // setup the Ctrl/Shift/Alt/Meta keysDown from a wxKeyEvent or wxMouseEvent - // Also mouse position, but the GetEventObject must be of type wxSheet - void SetKeysDownMousePos(wxEvent *mouseOrKeyEvent); - - virtual wxEvent *Clone() const { return new wxSheetEvent(*this); } - - wxSheetCoords m_coords; - wxPoint m_pos; - bool m_selecting; - bool m_control; - bool m_shift; - bool m_alt; - bool m_meta; - - DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetEvent) + wxSheetEvent(int id = 0, wxEventType type = wxEVT_NULL, wxObject *obj = NULL, + const wxSheetCoords &coords = wxNullSheetCoords, + const wxPoint &pos = wxPoint(-1, -1), bool sel = true); + + wxSheetEvent(const wxSheetEvent &event) + : wxNotifyEvent(event), m_coords(event.m_coords), m_pos(event.m_pos), + m_selecting(event.m_selecting), m_control(event.m_control), m_shift(event.m_shift), + m_alt(event.m_alt), m_meta(event.m_meta) + { + } + + int GetRow() const { return m_coords.m_row; } + int GetCol() const { return m_coords.m_col; } + const wxSheetCoords &GetCoords() const { return m_coords; } + const wxPoint &GetPosition() const { return m_pos; } + bool Selecting() const { return m_selecting; } + bool ControlDown() const { return m_control; } + bool ShiftDown() const { return m_shift; } + bool AltDown() const { return m_alt; } + bool MetaDown() const { return m_meta; } + + // implementation + + // setup the Ctrl/Shift/Alt/Meta keysDown from a wxKeyEvent or wxMouseEvent + // Also mouse position, but the GetEventObject must be of type wxSheet + void SetKeysDownMousePos(wxEvent *mouseOrKeyEvent); + + virtual wxEvent *Clone() const { return new wxSheetEvent(*this); } + + wxSheetCoords m_coords; + wxPoint m_pos; + bool m_selecting; + bool m_control; + bool m_shift; + bool m_alt; + bool m_meta; + + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetEvent) }; // ---------------------------------------------------------------------------- // wxSheetRangeSelectEvent - wxEVT_SHEET_RANGE_SELECTING(ED) // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetRangeSelectEvent : public wxSheetEvent -{ +class WXDLLIMPEXP_SHEET wxSheetRangeSelectEvent : public wxSheetEvent { public: - wxSheetRangeSelectEvent( int id=0, wxEventType type=wxEVT_NULL, wxObject* obj=NULL, - const wxSheetBlock& block=wxNullSheetBlock, - bool sel=false, bool add_to_sel=false ); + wxSheetRangeSelectEvent(int id = 0, wxEventType type = wxEVT_NULL, wxObject *obj = NULL, + const wxSheetBlock &block = wxNullSheetBlock, bool sel = false, + bool add_to_sel = false); - wxSheetRangeSelectEvent(const wxSheetRangeSelectEvent& event) - : wxSheetEvent(event), m_block(event.m_block), m_add(event.m_add) { } + wxSheetRangeSelectEvent(const wxSheetRangeSelectEvent &event) + : wxSheetEvent(event), m_block(event.m_block), m_add(event.m_add) + { + } - const wxSheetBlock& GetBlock() const { return m_block; } - bool GetAddToSelection() const { return m_add; } + const wxSheetBlock &GetBlock() const { return m_block; } + bool GetAddToSelection() const { return m_add; } - void SetBlock( const wxSheetBlock& block ) { m_block = block; } + void SetBlock(const wxSheetBlock &block) { m_block = block; } - // wxPoint GetPosition() is unused - // int GetCoords/Row/Col() is unused + // wxPoint GetPosition() is unused + // int GetCoords/Row/Col() is unused - // implementation - virtual wxEvent *Clone() const { return new wxSheetRangeSelectEvent(*this); } + // implementation + virtual wxEvent *Clone() const { return new wxSheetRangeSelectEvent(*this); } - wxSheetBlock m_block; - bool m_add; + wxSheetBlock m_block; + bool m_add; - DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetRangeSelectEvent) + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetRangeSelectEvent) }; // ---------------------------------------------------------------------------- // wxSheetEditorCreatedEvent - wxEVT_SHEET_EDITOR_CREATED // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetEditorCreatedEvent : public wxCommandEvent -{ +class WXDLLIMPEXP_SHEET wxSheetEditorCreatedEvent : public wxCommandEvent { public: - wxSheetEditorCreatedEvent( int id=0, wxEventType type=wxEVT_NULL, wxObject* obj=NULL, - const wxSheetCoords& coords=wxNullSheetCoords, - wxWindow* ctrl=NULL ); - - wxSheetEditorCreatedEvent(const wxSheetEditorCreatedEvent& evt) - : wxCommandEvent(evt), m_coords(evt.m_coords), m_ctrl(evt.m_ctrl) { } + wxSheetEditorCreatedEvent(int id = 0, wxEventType type = wxEVT_NULL, wxObject *obj = NULL, + const wxSheetCoords &coords = wxNullSheetCoords, + wxWindow *ctrl = NULL); + wxSheetEditorCreatedEvent(const wxSheetEditorCreatedEvent &evt) + : wxCommandEvent(evt), m_coords(evt.m_coords), m_ctrl(evt.m_ctrl) + { + } - const wxSheetCoords& GetCoords() const { return m_coords; } - wxWindow* GetControl() const { return m_ctrl; } + const wxSheetCoords &GetCoords() const { return m_coords; } + wxWindow *GetControl() const { return m_ctrl; } - void SetCoords(const wxSheetCoords& coords) { m_coords = coords; } - void SetControl(wxWindow* ctrl) { m_ctrl = ctrl; } + void SetCoords(const wxSheetCoords &coords) { m_coords = coords; } + void SetControl(wxWindow *ctrl) { m_ctrl = ctrl; } - // implementation - virtual wxEvent *Clone() const { return new wxSheetEditorCreatedEvent(*this); } + // implementation + virtual wxEvent *Clone() const { return new wxSheetEditorCreatedEvent(*this); } - wxSheetCoords m_coords; - wxWindow* m_ctrl; + wxSheetCoords m_coords; + wxWindow *m_ctrl; - DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetEditorCreatedEvent) + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxSheetEditorCreatedEvent) }; // ---------------------------------------------------------------------------- @@ -1363,102 +1606,207 @@ class WXDLLIMPEXP_SHEET wxSheetEditorCreatedEvent : public wxCommandEvent // ---------------------------------------------------------------------------- BEGIN_DECLARE_EVENT_TYPES() - // The origin of the grid window has changed - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_VIEW_CHANGED, 1592) - - // The grid cursor is about to be in a new cell, veto or !Skip() to block - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SELECTING_CELL, 1592) - // The grid cursor is in a new cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SELECTED_CELL, 1592) - - // left down click in a grid cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_DOWN, 1580) - // right down click in a grid cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_DOWN, 1581) - // left up click in a grid cell, sent after default processing - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_UP, 1580) - // right up click in a grid cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_UP, 1581) - // left double click in a grid cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_DCLICK, 1582) - // right double click in a grid cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_DCLICK, 1583) - - // left down click in a label cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_DOWN, 1584) - // right down click in a label cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_DOWN, 1585) - // left up click in a label cell, sent after default processing - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_UP, 1584) - // right up click in a label cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_UP, 1585) - // left double click in a label cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_DCLICK, 1586) - // right double click in a label cell - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_DCLICK, 1587) - - // A row has been resized, sent after default processing - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_ROW_SIZE, 1588) - // A col has been resized, sent after default processing - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_COL_SIZE, 1589) - - // A block of cells is about to be (de)selected (veto to stop) - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_RANGE_SELECTING, 1590) - // A block of cells has been (de)selected - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_RANGE_SELECTED, 1590) - - // The value of a cell is about to be changed (veto to stop) - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_VALUE_CHANGING, 1591) - // The value of a cell has been changed (veto to put old val back) - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_VALUE_CHANGED, 1591) - - // From EnableCellEditControl, the control is about to enabled (can veto) - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_ENABLED, 1593) - // From DisableCellEditControl, the control is about to disabled (can veto) - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_DISABLED, 1594) - // From EnableCellEditControl, the edit control has been created - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_CREATED, 1595) +// The origin of the grid window has changed +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_VIEW_CHANGED, 1592) + +// The grid cursor is about to be in a new cell, veto or !Skip() to block +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SELECTING_CELL, 1592) +// The grid cursor is in a new cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SELECTED_CELL, 1592) + +// left down click in a grid cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_DOWN, 1580) +// right down click in a grid cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_DOWN, 1581) +// left up click in a grid cell, sent after default processing +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_UP, 1580) +// right up click in a grid cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_UP, 1581) +// left double click in a grid cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_LEFT_DCLICK, 1582) +// right double click in a grid cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_RIGHT_DCLICK, 1583) + +// left down click in a label cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_DOWN, 1584) +// right down click in a label cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_DOWN, 1585) +// left up click in a label cell, sent after default processing +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_UP, 1584) +// right up click in a label cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_UP, 1585) +// left double click in a label cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_LEFT_DCLICK, 1586) +// right double click in a label cell +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_LABEL_RIGHT_DCLICK, 1587) + +// A row has been resized, sent after default processing +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_ROW_SIZE, 1588) +// A col has been resized, sent after default processing +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_COL_SIZE, 1589) + +// A block of cells is about to be (de)selected (veto to stop) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_RANGE_SELECTING, 1590) +// A block of cells has been (de)selected +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_RANGE_SELECTED, 1590) + +// The value of a cell is about to be changed (veto to stop) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_VALUE_CHANGING, 1591) +// The value of a cell has been changed (veto to put old val back) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_CELL_VALUE_CHANGED, 1591) + +// From EnableCellEditControl, the control is about to enabled (can veto) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_ENABLED, 1593) +// From DisableCellEditControl, the control is about to disabled (can veto) +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_DISABLED, 1594) +// From EnableCellEditControl, the edit control has been created +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_EDITOR_CREATED, 1595) END_DECLARE_EVENT_TYPES() -typedef void (wxEvtHandler::*wxSheetEventFunction)(wxSheetEvent&); -typedef void (wxEvtHandler::*wxSheetRangeSelectEventFunction)(wxSheetRangeSelectEvent&); -typedef void (wxEvtHandler::*wxSheetEditorCreatedEventFunction)(wxSheetEditorCreatedEvent&); - -#define EVT_SHEET_VIEW_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_VIEW_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_SELECTING_CELL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SELECTING_CELL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_SELECTED_CELL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SELECTED_CELL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_LEFT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_LEFT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_RIGHT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_RIGHT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_LEFT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_LEFT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_RIGHT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_RIGHT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_LEFT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_LEFT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_RIGHT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_RIGHT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_LABEL_LEFT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_LEFT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_LABEL_RIGHT_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_RIGHT_DOWN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_LABEL_LEFT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_LEFT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_LABEL_RIGHT_UP(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_RIGHT_UP, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_LABEL_LEFT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_LEFT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_LABEL_RIGHT_DCLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_LABEL_RIGHT_DCLICK, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_ROW_SIZE(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_ROW_SIZE, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_COL_SIZE(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_COL_SIZE, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_RANGE_SELECTING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_RANGE_SELECTING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetRangeSelectEventFunction, &fn), NULL ), -#define EVT_SHEET_RANGE_SELECTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_RANGE_SELECTED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetRangeSelectEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_VALUE_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_VALUE_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_CELL_VALUE_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CELL_VALUE_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_EDITOR_ENABLED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_EDITOR_ENABLED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_EDITOR_DISABLED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_EDITOR_DISABLED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEventFunction, &fn), NULL ), -#define EVT_SHEET_EDITOR_CREATED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_EDITOR_CREATED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetEditorCreatedEventFunction, &fn), NULL ), - -#if 0 // TODO: implement these ? others ? +typedef void (wxEvtHandler::*wxSheetEventFunction)(wxSheetEvent &); +typedef void (wxEvtHandler::*wxSheetRangeSelectEventFunction)(wxSheetRangeSelectEvent &); +typedef void (wxEvtHandler::*wxSheetEditorCreatedEventFunction)(wxSheetEditorCreatedEvent &); + +#define EVT_SHEET_VIEW_CHANGED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_VIEW_CHANGED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_SELECTING_CELL(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_SELECTING_CELL, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_SELECTED_CELL(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_SELECTED_CELL, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_LEFT_DOWN(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_LEFT_DOWN, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_RIGHT_DOWN(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_RIGHT_DOWN, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_LEFT_UP(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_LEFT_UP, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_RIGHT_UP(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_RIGHT_UP, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_LEFT_DCLICK(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_LEFT_DCLICK, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_RIGHT_DCLICK(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_RIGHT_DCLICK, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_LABEL_LEFT_DOWN(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_LABEL_LEFT_DOWN, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_LABEL_RIGHT_DOWN(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_LABEL_RIGHT_DOWN, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_LABEL_LEFT_UP(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_LABEL_LEFT_UP, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_LABEL_RIGHT_UP(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_LABEL_RIGHT_UP, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_LABEL_LEFT_DCLICK(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_LABEL_LEFT_DCLICK, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_LABEL_RIGHT_DCLICK(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_LABEL_RIGHT_DCLICK, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_ROW_SIZE(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_ROW_SIZE, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_COL_SIZE(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_COL_SIZE, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_RANGE_SELECTING(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_RANGE_SELECTING, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetRangeSelectEventFunction, &fn), \ + NULL), +#define EVT_SHEET_RANGE_SELECTED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_RANGE_SELECTED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetRangeSelectEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_VALUE_CHANGING(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_VALUE_CHANGING, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_CELL_VALUE_CHANGED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_CELL_VALUE_CHANGED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_EDITOR_ENABLED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_EDITOR_ENABLED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_EDITOR_DISABLED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY( \ + wxEVT_SHEET_EDITOR_DISABLED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxSheetEventFunction, &fn), \ + NULL), +#define EVT_SHEET_EDITOR_CREATED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_EDITOR_CREATED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetEditorCreatedEventFunction, &fn), \ + NULL), + +#if 0 // TODO: implement these ? others ? wxEVT_SHEET_CREATE_CELL; wxEVT_SHEET_CHANGE_LABELS; wxEVT_SHEET_CHANGE_SEL_LABEL; -#define EVT_SHEET_CREATE_CELL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CREATE_CELL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxSheetEventFunction) &fn, NULL ), -#define EVT_SHEET_CHANGE_LABELS(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CHANGE_LABELS, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxSheetEventFunction) &fn, NULL ), -#define EVT_SHEET_CHANGE_SEL_LABEL(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_CHANGE_SEL_LABEL, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxSheetEventFunction) &fn, NULL ), +#define EVT_SHEET_CREATE_CELL(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_CREATE_CELL, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)(wxSheetEventFunction) & fn, \ + NULL), +#define EVT_SHEET_CHANGE_LABELS(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_CHANGE_LABELS, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)(wxSheetEventFunction) & fn, \ + NULL), +#define EVT_SHEET_CHANGE_SEL_LABEL(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_CHANGE_SEL_LABEL, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)(wxSheetEventFunction) & fn, \ + NULL), #endif // 0 -#endif // __WX_SHEET_H__ +#endif // __WX_SHEET_H__ diff --git a/src/labenski/include/wx/sheet/sheetatr.h b/src/labenski/include/wx/sheet/sheetatr.h index 29ca94c16..dd2662426 100644 --- a/src/labenski/include/wx/sheet/sheetatr.h +++ b/src/labenski/include/wx/sheet/sheetatr.h @@ -27,109 +27,115 @@ // attr which gets them from it's def attr and so on, they're chained together. // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellAttr : public wxObject -{ +class WXDLLIMPEXP_SHEET wxSheetCellAttr : public wxObject { public: - // if create then create with ref data - wxSheetCellAttr( bool create = false ); - // make a refed copy of the other attribute - wxSheetCellAttr( const wxSheetCellAttr& attr ) : wxObject() { Ref(attr); } - - // Recreate the ref data, unrefing the old - bool Create(); - void Destroy() { UnRef(); } - inline bool Ok() const { return m_refData != NULL; } - - // Makes a full new unrefed copy of the other, this doesn't have to be created - bool Copy(const wxSheetCellAttr& other); - // Copies the values from the other, but only if the other has them, this must be created - bool UpdateWith(const wxSheetCellAttr& other); - // Merges this with the other, copy values of other only this doesn't have them - bool MergeWith(const wxSheetCellAttr &mergefrom); - - // setters - void SetForegroundColour(const wxColour& foreColour); - void SetBackgroundColour(const wxColour& backColour); - void SetFont(const wxFont& font); - // wxSheetAttrAlign_Type - void SetAlignment(int align); - void SetAlignment(int horzAlign, int vertAlign); - // wxSheetAttrOrientation_Type - void SetOrientation(int orientation); - void SetLevel(wxSheetAttrLevel_Type level); - void SetOverflow(bool allow); - void SetOverflowMarker(bool draw_marker); - void SetShowEditor(bool show_editor); - void SetReadOnly(bool isReadOnly); - void SetRenderer(const wxSheetCellRenderer& renderer); - void SetEditor(const wxSheetCellEditor& editor); - void SetKind(wxSheetAttr_Type kind); - - // validation - bool HasForegoundColour() const; - bool HasBackgroundColour() const; - bool HasFont() const; - bool HasAlignment() const; - bool HasOrientation() const; - bool HasLevel() const; - bool HasOverflowMode() const; - bool HasOverflowMarkerMode() const; - bool HasShowEditorMode() const; - bool HasReadWriteMode() const; - bool HasRenderer() const; - bool HasEditor() const; - bool HasDefaultAttr() const; - // bool HasKind() const - always has kind, default is wxSHEET_AttrCell - - // does this attr define all the HasXXX properties, except DefaultAttr - // if this is true, it's a suitable default attr for an area - bool IsComplete() const; - - // accessors - const wxColour& GetForegroundColour() const; - const wxColour& GetBackgroundColour() const; - const wxFont& GetFont() const; - int GetAlignment() const; - wxOrientation GetOrientation() const; - wxSheetAttrLevel_Type GetLevel() const; - bool GetOverflow() const; - bool GetOverflowMarker() const; - bool GetShowEditor() const; - bool GetReadOnly() const; - wxSheetCellRenderer GetRenderer(wxSheet* grid, const wxSheetCoords& coords) const; - wxSheetCellEditor GetEditor(wxSheet* grid, const wxSheetCoords& coords) const; - wxSheetAttr_Type GetKind() const; - - // any unset values of this attr are retrieved from the default attr - // if you try to set the def attr to this, it's ignored - // don't bother to link multiple attributes together in a loop, obviously. - const wxSheetCellAttr& GetDefaultAttr() const; - void SetDefaultAttr(const wxSheetCellAttr& defaultAttr); - - // operators - bool operator == (const wxSheetCellAttr& obj) const { return m_refData == obj.m_refData; } - bool operator != (const wxSheetCellAttr& obj) const { return m_refData != obj.m_refData; } - wxSheetCellAttr& operator = (const wxSheetCellAttr& obj) - { - if ( (*this) != obj ) Ref(obj); - return *this; + // if create then create with ref data + wxSheetCellAttr(bool create = false); + // make a refed copy of the other attribute + wxSheetCellAttr(const wxSheetCellAttr &attr) : wxObject() { Ref(attr); } + + // Recreate the ref data, unrefing the old + bool Create(); + void Destroy() { UnRef(); } + inline bool Ok() const { return m_refData != NULL; } + + // Makes a full new unrefed copy of the other, this doesn't have to be created + bool Copy(const wxSheetCellAttr &other); + // Copies the values from the other, but only if the other has them, this must be created + bool UpdateWith(const wxSheetCellAttr &other); + // Merges this with the other, copy values of other only this doesn't have them + bool MergeWith(const wxSheetCellAttr &mergefrom); + + // setters + void SetForegroundColour(const wxColour &foreColour); + void SetBackgroundColour(const wxColour &backColour); + void SetFont(const wxFont &font); + // wxSheetAttrAlign_Type + void SetAlignment(int align); + void SetAlignment(int horzAlign, int vertAlign); + // wxSheetAttrOrientation_Type + void SetOrientation(int orientation); + void SetLevel(wxSheetAttrLevel_Type level); + void SetOverflow(bool allow); + void SetOverflowMarker(bool draw_marker); + void SetShowEditor(bool show_editor); + void SetReadOnly(bool isReadOnly); + void SetRenderer(const wxSheetCellRenderer &renderer); + void SetEditor(const wxSheetCellEditor &editor); + void SetKind(wxSheetAttr_Type kind); + + // validation + bool HasForegoundColour() const; + bool HasBackgroundColour() const; + bool HasFont() const; + bool HasAlignment() const; + bool HasOrientation() const; + bool HasLevel() const; + bool HasOverflowMode() const; + bool HasOverflowMarkerMode() const; + bool HasShowEditorMode() const; + bool HasReadWriteMode() const; + bool HasRenderer() const; + bool HasEditor() const; + bool HasDefaultAttr() const; + // bool HasKind() const - always has kind, default is wxSHEET_AttrCell + + // does this attr define all the HasXXX properties, except DefaultAttr + // if this is true, it's a suitable default attr for an area + bool IsComplete() const; + + // accessors + const wxColour &GetForegroundColour() const; + const wxColour &GetBackgroundColour() const; + const wxFont &GetFont() const; + int GetAlignment() const; + wxOrientation GetOrientation() const; + wxSheetAttrLevel_Type GetLevel() const; + bool GetOverflow() const; + bool GetOverflowMarker() const; + bool GetShowEditor() const; + bool GetReadOnly() const; + wxSheetCellRenderer GetRenderer(wxSheet *grid, const wxSheetCoords &coords) const; + wxSheetCellEditor GetEditor(wxSheet *grid, const wxSheetCoords &coords) const; + wxSheetAttr_Type GetKind() const; + + // any unset values of this attr are retrieved from the default attr + // if you try to set the def attr to this, it's ignored + // don't bother to link multiple attributes together in a loop, obviously. + const wxSheetCellAttr &GetDefaultAttr() const; + void SetDefaultAttr(const wxSheetCellAttr &defaultAttr); + + // operators + bool operator==(const wxSheetCellAttr &obj) const { return m_refData == obj.m_refData; } + bool operator!=(const wxSheetCellAttr &obj) const { return m_refData != obj.m_refData; } + wxSheetCellAttr &operator=(const wxSheetCellAttr &obj) + { + if ((*this) != obj) { + Ref(obj); } - - wxSheetCellAttr Clone() const { wxSheetCellAttr obj; obj.Copy(*this); return obj; } - wxSheetCellAttr* NewClone() const { return new wxSheetCellAttr(Clone()); } - - // implementation - void SetType(int type, int mask); - int GetType(int mask = ~0) const; - bool HasType(int type) const { return GetType(type) != 0; } + return *this; + } + + wxSheetCellAttr Clone() const + { + wxSheetCellAttr obj; + obj.Copy(*this); + return obj; + } + wxSheetCellAttr *NewClone() const { return new wxSheetCellAttr(Clone()); } + + // implementation + void SetType(int type, int mask); + int GetType(int mask = ~0) const; + bool HasType(int type) const { return GetType(type) != 0; } protected: - // override wxObject's create a new m_refData - virtual wxObjectRefData *CreateRefData() const; - // override wxObject's create a new m_refData initialized with the given one - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; + // override wxObject's create a new m_refData + virtual wxObjectRefData *CreateRefData() const; + // override wxObject's create a new m_refData initialized with the given one + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxSheetCellAttr) + DECLARE_DYNAMIC_CLASS(wxSheetCellAttr) }; // ---------------------------------------------------------------------------- @@ -137,23 +143,21 @@ class WXDLLIMPEXP_SHEET wxSheetCellAttr : public wxObject // // only use this as a LAST resort for overriding the behavior // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellAttrRefData : public wxObjectRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellAttrRefData : public wxObjectRefData { public: - wxSheetCellAttrRefData(); - wxSheetCellAttrRefData( const wxSheetCellAttrRefData& data ); - virtual ~wxSheetCellAttrRefData(); - - wxColour m_foreColour, - m_backColour; - wxFont m_font; - // stores wxSheetAttr_Type, align, orient, overflow, show edit, read, level - wxUint32 m_attrTypes; - - // these are pointers since we can't define the edit/ren/attr all at once - wxSheetCellRenderer *m_renderer; - wxSheetCellEditor *m_editor; - wxSheetCellAttr *m_defaultAttr; + wxSheetCellAttrRefData(); + wxSheetCellAttrRefData(const wxSheetCellAttrRefData &data); + virtual ~wxSheetCellAttrRefData(); + + wxColour m_foreColour, m_backColour; + wxFont m_font; + // stores wxSheetAttr_Type, align, orient, overflow, show edit, read, level + wxUint32 m_attrTypes; + + // these are pointers since we can't define the edit/ren/attr all at once + wxSheetCellRenderer *m_renderer; + wxSheetCellEditor *m_editor; + wxSheetCellAttr *m_defaultAttr; }; // ---------------------------------------------------------------------------- @@ -169,11 +173,10 @@ WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellAttr) wxNullSheetCellAttr; // ---------------------------------------------------------------------------- // Create a 1-D array of wxArraySheetCellAttr for row/col labels -WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetCellAttr, wxArraySheetCellAttr, - class WXDLLIMPEXP_SHEET); +WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetCellAttr, wxArraySheetCellAttr, class WXDLLIMPEXP_SHEET); // Create the paired array of attrs for row/col labels -DECLARE_PAIRED_INT_DATA_ARRAYS( wxSheetCellAttr, wxArraySheetCellAttr, - wxPairArrayIntSheetCellAttr, class WXDLLIMPEXP_SHEET) +DECLARE_PAIRED_INT_DATA_ARRAYS(wxSheetCellAttr, wxArraySheetCellAttr, wxPairArrayIntSheetCellAttr, + class WXDLLIMPEXP_SHEET) // Create wxPairArraySheetCoordsCellAttr for storing coords keys and attr values. DECLARE_PAIREDSHEETCOORDS_DATA_ARRAYS(wxSheetCellAttr, wxArraySheetCellAttr, @@ -191,46 +194,40 @@ DECLARE_PAIREDSHEETCOORDS_DATA_ARRAYS(wxSheetCellAttr, wxArraySheetCellAttr, // if you have performance problems with the stock one or the attribute // properties lend themselves to be calculated on the fly // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellAttrProvider : public wxClientDataContainer -{ +class WXDLLIMPEXP_SHEET wxSheetCellAttrProvider : public wxClientDataContainer { public: - wxSheetCellAttrProvider() {} - virtual ~wxSheetCellAttrProvider() {} - - // Get the attribute for the coords of type wxSheetAttr_Type - // you must implement these cell coords for grid, row/col/corner labels - // see wxSheet::IsGridCell/IsRowLabelCell/IsColLabelCell/IsCornerLabelCell - // and all types except wxSHEET_AttrDefault, which sheet should have handled - // If type is wxSHEET_AttrCell/Row/Col return wxNullSheetCellAttr if one is - // not set. Type wxSHEET_AttrAny is used to merge row/col/cell attr - // based on their level. - // return wxNullSheetCellAttr if none set for coords and type - virtual wxSheetCellAttr GetAttr( const wxSheetCoords& coords, - wxSheetAttr_Type type ); - - // Set the attribute for the coords, see GetAttr for coords and type - // if the !attr.Ok() the attr is removed w/o error even if it didn't exist - // use wxNullSheetCellAttr to remove attr for coords and type - virtual void SetAttr( const wxSheetCoords& coords, - const wxSheetCellAttr& attr, - wxSheetAttr_Type type ); - - // Update internal data whenever # rows/cols change (must be called) - // this shifts rows/cols and deletes them as appropriate - // you can specificly update only some of the attributes by ORing - // enum wxSheetUpdate_Type for the attributes. - virtual void UpdateRows( size_t pos, int numRows, int update = wxSHEET_UpdateAttributes ); - virtual void UpdateCols( size_t pos, int numCols, int update = wxSHEET_UpdateAttributes ); + wxSheetCellAttrProvider() {} + virtual ~wxSheetCellAttrProvider() {} + + // Get the attribute for the coords of type wxSheetAttr_Type + // you must implement these cell coords for grid, row/col/corner labels + // see wxSheet::IsGridCell/IsRowLabelCell/IsColLabelCell/IsCornerLabelCell + // and all types except wxSHEET_AttrDefault, which sheet should have handled + // If type is wxSHEET_AttrCell/Row/Col return wxNullSheetCellAttr if one is + // not set. Type wxSHEET_AttrAny is used to merge row/col/cell attr + // based on their level. + // return wxNullSheetCellAttr if none set for coords and type + virtual wxSheetCellAttr GetAttr(const wxSheetCoords &coords, wxSheetAttr_Type type); + + // Set the attribute for the coords, see GetAttr for coords and type + // if the !attr.Ok() the attr is removed w/o error even if it didn't exist + // use wxNullSheetCellAttr to remove attr for coords and type + virtual void SetAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr, + wxSheetAttr_Type type); + + // Update internal data whenever # rows/cols change (must be called) + // this shifts rows/cols and deletes them as appropriate + // you can specificly update only some of the attributes by ORing + // enum wxSheetUpdate_Type for the attributes. + virtual void UpdateRows(size_t pos, int numRows, int update = wxSHEET_UpdateAttributes); + virtual void UpdateCols(size_t pos, int numCols, int update = wxSHEET_UpdateAttributes); protected: - wxPairArraySheetCoordsCellAttr m_cellAttrs; + wxPairArraySheetCoordsCellAttr m_cellAttrs; - wxPairArrayIntSheetCellAttr m_rowAttrs, - m_colAttrs, - m_rowLabelAttrs, - m_colLabelAttrs; + wxPairArrayIntSheetCellAttr m_rowAttrs, m_colAttrs, m_rowLabelAttrs, m_colLabelAttrs; - DECLARE_NO_COPY_CLASS(wxSheetCellAttrProvider) + DECLARE_NO_COPY_CLASS(wxSheetCellAttrProvider) }; -#endif // __WX_SHEETATR_H__ +#endif // __WX_SHEETATR_H__ diff --git a/src/labenski/include/wx/sheet/sheetdef.h b/src/labenski/include/wx/sheet/sheetdef.h index dde8c2147..522e0b663 100644 --- a/src/labenski/include/wx/sheet/sheetdef.h +++ b/src/labenski/include/wx/sheet/sheetdef.h @@ -32,8 +32,8 @@ #define WXDLLIMPEXP_DATA_SHEET(type) WXIMPORT type #else // not making nor using DLL */ - #define WXDLLIMPEXP_SHEET - #define WXDLLIMPEXP_DATA_SHEET(type) type +#define WXDLLIMPEXP_SHEET +#define WXDLLIMPEXP_DATA_SHEET(type) type /* #endif */ @@ -43,57 +43,60 @@ // giving reasonable messages to help debugging // ---------------------------------------------------------------------------- -#define wxSHEET_CHECKUPDATE_RET(pos, count, origcount) \ - wxCHECK_RET((count == 0) || ((int(count) > 0) && (int(pos) <= int(origcount))) || \ - ((int(count) < 0) && (int(pos) - int(count) <= int(origcount))), \ - wxString::Format(wxT("Updating past end of array, pos %d count %d, orig count %d"), pos, count, origcount)); +#define wxSHEET_CHECKUPDATE_RET(pos, count, origcount) \ + wxCHECK_RET((count == 0) || ((int(count) > 0) && (int(pos) <= int(origcount))) || \ + ((int(count) < 0) && (int(pos) - int(count) <= int(origcount))), \ + wxString::Format(wxT("Updating past end of array, pos %d count %d, orig count %d"), \ + pos, count, origcount)); -#define wxSHEET_CHECKUPDATE_MSG(pos, count, origcount, ret) \ - wxCHECK_MSG((count == 0) || ((int(count) > 0) && (int(pos) <= int(origcount))) || \ - ((int(count) < 0) && (int(pos) - int(count) <= int(origcount))), ret, \ - wxString::Format(wxT("Updating past end of array, pos %d count %d, orig count %d"), pos, count, origcount)); +#define wxSHEET_CHECKUPDATE_MSG(pos, count, origcount, ret) \ + wxCHECK_MSG((count == 0) || ((int(count) > 0) && (int(pos) <= int(origcount))) || \ + ((int(count) < 0) && (int(pos) - int(count) <= int(origcount))), \ + ret, \ + wxString::Format(wxT("Updating past end of array, pos %d count %d, orig count %d"), \ + pos, count, origcount)); // ---------------------------------------------------------------------------- // Complete list of classes implemented by wxSheet // ---------------------------------------------------------------------------- // Windows -class WXDLLIMPEXP_SHEET wxSheet; // the spreadsheet widget -class WXDLLIMPEXP_SHEET wxSheetChildWindow; // child windows of the sheet -class WXDLLIMPEXP_SHEET wxSheetRefData; // internal use sheet data +class WXDLLIMPEXP_SHEET wxSheet; // the spreadsheet widget +class WXDLLIMPEXP_SHEET wxSheetChildWindow; // child windows of the sheet +class WXDLLIMPEXP_SHEET wxSheetRefData; // internal use sheet data // Events -class WXDLLIMPEXP_SHEET wxSheetEvent; // events returned from the sheet -class WXDLLIMPEXP_SHEET wxSheetRangeSelectEvent; // cells (de)selected +class WXDLLIMPEXP_SHEET wxSheetEvent; // events returned from the sheet +class WXDLLIMPEXP_SHEET wxSheetRangeSelectEvent; // cells (de)selected class WXDLLIMPEXP_SHEET wxSheetEditorCreatedEvent; // editor created -class WXDLLIMPEXP_SHEET wxSheetSplitterEvent; // events sent from the sheet splitter +class WXDLLIMPEXP_SHEET wxSheetSplitterEvent; // events sent from the sheet splitter // Attributes -class WXDLLIMPEXP_SHEET wxSheetCellAttr; // attribute for cell/row/col -class WXDLLIMPEXP_SHEET wxSheetCellAttrRefData;// refdata for attribute -class WXDLLIMPEXP_SHEET wxArraySheetCellAttr; // array of cell attrs -class WXDLLIMPEXP_SHEET wxPairArrayIntSheetCellAttr; // int, attr pair array +class WXDLLIMPEXP_SHEET wxSheetCellAttr; // attribute for cell/row/col +class WXDLLIMPEXP_SHEET wxSheetCellAttrRefData; // refdata for attribute +class WXDLLIMPEXP_SHEET wxArraySheetCellAttr; // array of cell attrs +class WXDLLIMPEXP_SHEET wxPairArrayIntSheetCellAttr; // int, attr pair array class WXDLLIMPEXP_SHEET wxPairArraySheetCoordsCellAttr; // coords, attr pair array -class WXDLLIMPEXP_SHEET wxSheetCellAttrProvider; // provider of attr for row/col/cell -class WXDLLIMPEXP_SHEET wxSheetTypeRegistry; // internal use +class WXDLLIMPEXP_SHEET wxSheetCellAttrProvider; // provider of attr for row/col/cell +class WXDLLIMPEXP_SHEET wxSheetTypeRegistry; // internal use // String containers -//class WXDLLIMPEXP_SHEET wxSheetStringArray; // wxArray of wxArrayString -class WXDLLIMPEXP_SHEET wxPairArrayIntSheetString; // pair (int, wxString) -class WXDLLIMPEXP_SHEET wxArrayPairArrayIntSheetString; // array of (int, str) pair +// class WXDLLIMPEXP_SHEET wxSheetStringArray; // wxArray of wxArrayString +class WXDLLIMPEXP_SHEET wxPairArrayIntSheetString; // pair (int, wxString) +class WXDLLIMPEXP_SHEET wxArrayPairArrayIntSheetString; // array of (int, str) pair class WXDLLIMPEXP_SHEET wxSheetValueProviderBase; // base class value provider class WXDLLIMPEXP_SHEET wxSheetValueProviderString; // a wxArrayString value provider class WXDLLIMPEXP_SHEET wxSheetValueProviderSparseString; // a string pair array value provider // Coords/Blocks/Selection/Int arrays/Edge arrays -class WXDLLIMPEXP_SHEET wxSheetCoords; // cell coordinates -class WXDLLIMPEXP_SHEET wxSheetBlock; // rectangular block of cells -class WXDLLIMPEXP_SHEET wxSheetSelection; // cell selection container +class WXDLLIMPEXP_SHEET wxSheetCoords; // cell coordinates +class WXDLLIMPEXP_SHEET wxSheetBlock; // rectangular block of cells +class WXDLLIMPEXP_SHEET wxSheetSelection; // cell selection container class WXDLLIMPEXP_SHEET wxSheetSelectionIterator; // selection iterator -class WXDLLIMPEXP_SHEET wxSheetArrayEdge; // row/col edge container -class WXDLLIMPEXP_SHEET wxPairArrayIntInt; // pair of (int, int) +class WXDLLIMPEXP_SHEET wxSheetArrayEdge; // row/col edge container +class WXDLLIMPEXP_SHEET wxPairArrayIntInt; // pair of (int, int) // "Widgets" -class WXDLLIMPEXP_SHEET wxSheetCellRenderer; // drawing renderer for cell -class WXDLLIMPEXP_SHEET wxSheetCellEditor; // cell editor +class WXDLLIMPEXP_SHEET wxSheetCellRenderer; // drawing renderer for cell +class WXDLLIMPEXP_SHEET wxSheetCellEditor; // cell editor // Tables -class WXDLLIMPEXP_SHEET wxSheetTable; // cell value/attr provider +class WXDLLIMPEXP_SHEET wxSheetTable; // cell value/attr provider // ---------------------------------------------------------------------------- // constants @@ -101,26 +104,26 @@ class WXDLLIMPEXP_SHEET wxSheetTable; // cell value/attr provider // Default parameters for wxSheet #ifdef __WXMSW__ - #define WXSHEET_DEFAULT_ROW_HEIGHT 25 +#define WXSHEET_DEFAULT_ROW_HEIGHT 25 #else - #define WXSHEET_DEFAULT_ROW_HEIGHT 30 -#endif // __WXMSW__ -#define WXSHEET_DEFAULT_COL_WIDTH 80 -#define WXSHEET_DEFAULT_COL_LABEL_HEIGHT 32 -#define WXSHEET_DEFAULT_ROW_LABEL_WIDTH 82 -#define WXSHEET_LABEL_EDGE_ZONE 2 -#define WXSHEET_MIN_ROW_HEIGHT 15 -#define WXSHEET_MIN_COL_WIDTH 15 +#define WXSHEET_DEFAULT_ROW_HEIGHT 30 +#endif // __WXMSW__ +#define WXSHEET_DEFAULT_COL_WIDTH 80 +#define WXSHEET_DEFAULT_COL_LABEL_HEIGHT 32 +#define WXSHEET_DEFAULT_ROW_LABEL_WIDTH 82 +#define WXSHEET_LABEL_EDGE_ZONE 2 +#define WXSHEET_MIN_ROW_HEIGHT 15 +#define WXSHEET_MIN_COL_WIDTH 15 // type names for grid table values -#define wxSHEET_VALUE_STRING _T("string") -#define wxSHEET_VALUE_BOOL _T("bool") -#define wxSHEET_VALUE_NUMBER _T("long") -#define wxSHEET_VALUE_FLOAT _T("double") -#define wxSHEET_VALUE_CHOICE _T("choice") -#define wxSHEET_VALUE_CHOICEINT _T("choiceint") -#define wxSHEET_VALUE_DATETIME _T("datetime") -#define wxSHEET_VALUE_LABEL _T("label") +#define wxSHEET_VALUE_STRING _T("string") +#define wxSHEET_VALUE_BOOL _T("bool") +#define wxSHEET_VALUE_NUMBER _T("long") +#define wxSHEET_VALUE_FLOAT _T("double") +#define wxSHEET_VALUE_CHOICE _T("choice") +#define wxSHEET_VALUE_CHOICEINT _T("choiceint") +#define wxSHEET_VALUE_DATETIME _T("datetime") +#define wxSHEET_VALUE_LABEL _T("label") // ---------------------------------------------------------------------------- // wxSheet cell drawing scheme, also applies to label cells @@ -161,48 +164,45 @@ class WXDLLIMPEXP_SHEET wxSheetTable; // cell value/attr provider // wxSheetCell_Type : enum of the different window cell types // ---------------------------------------------------------------------------- -enum wxSheetCell_Type -{ - wxSHEET_CELL_UNKNOWN = 0, // An invalid cell coords - wxSHEET_CELL_GRID, // A grid cell row >= 0 && col >= 0 - wxSHEET_CELL_ROWLABEL, // A row label cell row >= 0 && col == -1 - wxSHEET_CELL_COLLABEL, // A col label cell row == -1 && col >= 0 - wxSHEET_CELL_CORNERLABEL // The corner label row == -1 && col == -1 +enum wxSheetCell_Type { + wxSHEET_CELL_UNKNOWN = 0, // An invalid cell coords + wxSHEET_CELL_GRID, // A grid cell row >= 0 && col >= 0 + wxSHEET_CELL_ROWLABEL, // A row label cell row >= 0 && col == -1 + wxSHEET_CELL_COLLABEL, // A col label cell row == -1 && col >= 0 + wxSHEET_CELL_CORNERLABEL // The corner label row == -1 && col == -1 }; // ---------------------------------------------------------------------------- // wxSheetSelectionMode_Type : how selections are made by the mouse and cursor // ---------------------------------------------------------------------------- -enum wxSheetSelectionMode_Type -{ - wxSHEET_SelectNone = 0x0001, // don't allow selections by mouse or keyboard - // direct calls to the selections work however - wxSHEET_SelectCells = 0x0002, // single cells, blocks, rows, and cols - wxSHEET_SelectRows = 0x0004, // only rows can be selected - wxSHEET_SelectCols = 0x0008 // only cols can be selected +enum wxSheetSelectionMode_Type { + wxSHEET_SelectNone = 0x0001, // don't allow selections by mouse or keyboard + // direct calls to the selections work however + wxSHEET_SelectCells = 0x0002, // single cells, blocks, rows, and cols + wxSHEET_SelectRows = 0x0004, // only rows can be selected + wxSHEET_SelectCols = 0x0008 // only cols can be selected }; // ---------------------------------------------------------------------------- // wxSheetMouseDrag_Type : can the mouse or keyboard be used to resize cells // ---------------------------------------------------------------------------- -enum wxSheetDragCellSize_Type -{ - wxSHEET_DragLabelRowHeight = 0x0010, // Mouse can resize row heights on label - wxSHEET_DragLabelColWidth = 0x0020, // Mouse can resize col widths on label - wxSHEET_DragLabelCellSize = (wxSHEET_DragLabelRowHeight|wxSHEET_DragLabelColWidth), +enum wxSheetDragCellSize_Type { + wxSHEET_DragLabelRowHeight = 0x0010, // Mouse can resize row heights on label + wxSHEET_DragLabelColWidth = 0x0020, // Mouse can resize col widths on label + wxSHEET_DragLabelCellSize = (wxSHEET_DragLabelRowHeight | wxSHEET_DragLabelColWidth), - wxSHEET_DragLabelRowWidth = 0x0040, // Mouse can resize row label width - wxSHEET_DragLabelColHeight = 0x0080, // Mouse can resize col label height - wxSHEET_DragLabelSize = (wxSHEET_DragLabelRowWidth|wxSHEET_DragLabelColHeight), + wxSHEET_DragLabelRowWidth = 0x0040, // Mouse can resize row label width + wxSHEET_DragLabelColHeight = 0x0080, // Mouse can resize col label height + wxSHEET_DragLabelSize = (wxSHEET_DragLabelRowWidth | wxSHEET_DragLabelColHeight), - wxSHEET_DragGridRowHeight = 0x0100, // Mouse can resize row heights on grid - wxSHEET_DragGridColWidth = 0x0200, // Mouse can resize col widths on grid - wxSHEET_DragGridCellSize = (wxSHEET_DragGridRowHeight|wxSHEET_DragGridColWidth), + wxSHEET_DragGridRowHeight = 0x0100, // Mouse can resize row heights on grid + wxSHEET_DragGridColWidth = 0x0200, // Mouse can resize col widths on grid + wxSHEET_DragGridCellSize = (wxSHEET_DragGridRowHeight | wxSHEET_DragGridColWidth), - wxSHEET_DragCellSize = (wxSHEET_DragLabelCellSize|wxSHEET_DragGridCellSize), - wxSHEET_DragSize = (wxSHEET_DragCellSize|wxSHEET_DragLabelSize) + wxSHEET_DragCellSize = (wxSHEET_DragLabelCellSize | wxSHEET_DragGridCellSize), + wxSHEET_DragSize = (wxSHEET_DragCellSize | wxSHEET_DragLabelSize) }; // ---------------------------------------------------------------------------- @@ -211,138 +211,137 @@ enum wxSheetDragCellSize_Type // can ensure that no problems will occur. // ---------------------------------------------------------------------------- -enum wxSheetUpdate_Type -{ - wxSHEET_UpdateNone = 0x0000, // update nothing +enum wxSheetUpdate_Type { + wxSHEET_UpdateNone = 0x0000, // update nothing - wxSHEET_UpdateGridCellValues = 0x0001, // update the grid cell data container - wxSHEET_UpdateRowLabelValues = 0x0002, // update the row label data container - wxSHEET_UpdateColLabelValues = 0x0004, // update the col label data container - wxSHEET_UpdateLabelValues = wxSHEET_UpdateRowLabelValues|wxSHEET_UpdateColLabelValues, // update the label containers - wxSHEET_UpdateValues = wxSHEET_UpdateGridCellValues|wxSHEET_UpdateLabelValues, + wxSHEET_UpdateGridCellValues = 0x0001, // update the grid cell data container + wxSHEET_UpdateRowLabelValues = 0x0002, // update the row label data container + wxSHEET_UpdateColLabelValues = 0x0004, // update the col label data container + wxSHEET_UpdateLabelValues = + wxSHEET_UpdateRowLabelValues | wxSHEET_UpdateColLabelValues, // update the label containers + wxSHEET_UpdateValues = wxSHEET_UpdateGridCellValues | wxSHEET_UpdateLabelValues, - wxSHEET_UpdateSpanned = 0x0008, // update the spanned cells + wxSHEET_UpdateSpanned = 0x0008, // update the spanned cells - wxSHEET_UpdateGridCellAttrs = 0x0010, // update grid cell attributes - wxSHEET_UpdateRowLabelAttrs = 0x0020, // update row label attributes - wxSHEET_UpdateColLabelAttrs = 0x0040, // update col label attributes - wxSHEET_UpdateLabelAttrs = wxSHEET_UpdateRowLabelAttrs|wxSHEET_UpdateColLabelAttrs, - wxSHEET_UpdateAttributes = wxSHEET_UpdateGridCellAttrs|wxSHEET_UpdateLabelAttrs, // update the attr container + wxSHEET_UpdateGridCellAttrs = 0x0010, // update grid cell attributes + wxSHEET_UpdateRowLabelAttrs = 0x0020, // update row label attributes + wxSHEET_UpdateColLabelAttrs = 0x0040, // update col label attributes + wxSHEET_UpdateLabelAttrs = wxSHEET_UpdateRowLabelAttrs | wxSHEET_UpdateColLabelAttrs, + wxSHEET_UpdateAttributes = + wxSHEET_UpdateGridCellAttrs | wxSHEET_UpdateLabelAttrs, // update the attr container - wxSHEET_UpdateSelection = 0x0100, // update the selection + wxSHEET_UpdateSelection = 0x0100, // update the selection - wxSHEET_UpdateAll = (wxSHEET_UpdateValues|wxSHEET_UpdateSpanned|wxSHEET_UpdateAttributes|wxSHEET_UpdateSelection), - wxSHEET_UpdateType_Mask = wxSHEET_UpdateAll + wxSHEET_UpdateAll = (wxSHEET_UpdateValues | wxSHEET_UpdateSpanned | wxSHEET_UpdateAttributes | + wxSHEET_UpdateSelection), + wxSHEET_UpdateType_Mask = wxSHEET_UpdateAll }; // ---------------------------------------------------------------------------- // wxSheetCellAttr_Type : contains all the attributes for a wxSheet cell // ---------------------------------------------------------------------------- -enum wxSheetAttr_Type -{ - // A default attr, used when no particular one is set, all areas have def attr - wxSHEET_AttrDefault = 0x00010, - // The attr for a single cell coords, applies to all areas - wxSHEET_AttrCell = 0x00020, - // The attr for a row of cells, only applies to the grid cells - // not label attrs, they only have default or single cell - wxSHEET_AttrRow = 0x00040, - // The attr for a col of cells, only applies to the grid cells - // not label attrs, they only have default or single cell - wxSHEET_AttrCol = 0x00080, - // Only for getting attrs, get an attr that may be merged from cell/row/col - // attrs, if none of those then resort to default attr for area - // this is the best choice for getting an attr since it's guaranteed to work - wxSHEET_AttrAny = wxSHEET_AttrDefault|wxSHEET_AttrCell|wxSHEET_AttrRow|wxSHEET_AttrCol, - - wxSHEET_AttrType_Mask = wxSHEET_AttrAny +enum wxSheetAttr_Type { + // A default attr, used when no particular one is set, all areas have def attr + wxSHEET_AttrDefault = 0x00010, + // The attr for a single cell coords, applies to all areas + wxSHEET_AttrCell = 0x00020, + // The attr for a row of cells, only applies to the grid cells + // not label attrs, they only have default or single cell + wxSHEET_AttrRow = 0x00040, + // The attr for a col of cells, only applies to the grid cells + // not label attrs, they only have default or single cell + wxSHEET_AttrCol = 0x00080, + // Only for getting attrs, get an attr that may be merged from cell/row/col + // attrs, if none of those then resort to default attr for area + // this is the best choice for getting an attr since it's guaranteed to work + wxSHEET_AttrAny = wxSHEET_AttrDefault | wxSHEET_AttrCell | wxSHEET_AttrRow | wxSHEET_AttrCol, + + wxSHEET_AttrType_Mask = wxSHEET_AttrAny }; // ---------------------------------------------------------------------------- // Alignment of the text (or whatever) for a sheet cell attribute -enum wxSheetAttrAlign_Type -{ - // wxALIGN_TOP=wxALIGN_LEFT=wxALIGN_NOT=0, use these for unset - wxSHEET_AttrAlignHorizUnset = 0x01000, - wxSHEET_AttrAlignVertUnset = 0x02000, - wxSHEET_AttrAlignUnset = (wxSHEET_AttrAlignHorizUnset|wxSHEET_AttrAlignVertUnset), - - wxSHEET_AttrAlignCenterHoriz = wxALIGN_CENTER_HORIZONTAL, // = 0x0100, - wxSHEET_AttrAlignLeft = wxALIGN_LEFT, // = wxALIGN_NOT, - wxSHEET_AttrAlignTop = wxALIGN_TOP, // = wxALIGN_NOT, - wxSHEET_AttrAlignRight = wxALIGN_RIGHT, // = 0x0200, - wxSHEET_AttrAlignBottom = wxALIGN_BOTTOM, // = 0x0400, - wxSHEET_AttrAlignCenterVert = wxALIGN_CENTER_VERTICAL, // = 0x0800, - wxSHEET_AttrAlignCenter = wxALIGN_CENTER, // = (wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL), - wxSHEET_AttrAlignType_Mask = (wxALIGN_MASK|wxSHEET_AttrAlignUnset), // = 0x0f00 - - // A bit mask for the wxALIGN_XXX enums for extracting horiz and vert alignments - wxSHEET_AttrAlignHoriz_Mask = (wxALIGN_LEFT|wxALIGN_RIGHT|wxALIGN_CENTER_HORIZONTAL|wxSHEET_AttrAlignHorizUnset), - wxSHEET_AttrAlignVert_Mask = (wxALIGN_TOP|wxALIGN_BOTTOM|wxALIGN_CENTER_VERTICAL|wxSHEET_AttrAlignVertUnset) +enum wxSheetAttrAlign_Type { + // wxALIGN_TOP=wxALIGN_LEFT=wxALIGN_NOT=0, use these for unset + wxSHEET_AttrAlignHorizUnset = 0x01000, + wxSHEET_AttrAlignVertUnset = 0x02000, + wxSHEET_AttrAlignUnset = (wxSHEET_AttrAlignHorizUnset | wxSHEET_AttrAlignVertUnset), + + wxSHEET_AttrAlignCenterHoriz = wxALIGN_CENTER_HORIZONTAL, // = 0x0100, + wxSHEET_AttrAlignLeft = wxALIGN_LEFT, // = wxALIGN_NOT, + wxSHEET_AttrAlignTop = wxALIGN_TOP, // = wxALIGN_NOT, + wxSHEET_AttrAlignRight = wxALIGN_RIGHT, // = 0x0200, + wxSHEET_AttrAlignBottom = wxALIGN_BOTTOM, // = 0x0400, + wxSHEET_AttrAlignCenterVert = wxALIGN_CENTER_VERTICAL, // = 0x0800, + wxSHEET_AttrAlignCenter = + wxALIGN_CENTER, // = (wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL), + wxSHEET_AttrAlignType_Mask = (wxALIGN_MASK | wxSHEET_AttrAlignUnset), // = 0x0f00 + + // A bit mask for the wxALIGN_XXX enums for extracting horiz and vert alignments + wxSHEET_AttrAlignHoriz_Mask = + (wxALIGN_LEFT | wxALIGN_RIGHT | wxALIGN_CENTER_HORIZONTAL | wxSHEET_AttrAlignHorizUnset), + wxSHEET_AttrAlignVert_Mask = + (wxALIGN_TOP | wxALIGN_BOTTOM | wxALIGN_CENTER_VERTICAL | wxSHEET_AttrAlignVertUnset) }; // ---------------------------------------------------------------------------- // Orientation of the text (or whatever) for a sheet cell attribute -enum wxSheetAttrOrientation_Type -{ - wxSHEET_AttrOrientUnset = 0, - wxSHEET_AttrOrientHoriz = wxHORIZONTAL, // 0x0004 Horizontally orientated - wxSHEET_AttrOrientVert = wxVERTICAL, // 0x0008 Vertically orientated - wxSHEET_AttrOrientType_Mask = (wxSHEET_AttrOrientHoriz|wxSHEET_AttrOrientVert) +enum wxSheetAttrOrientation_Type { + wxSHEET_AttrOrientUnset = 0, + wxSHEET_AttrOrientHoriz = wxHORIZONTAL, // 0x0004 Horizontally orientated + wxSHEET_AttrOrientVert = wxVERTICAL, // 0x0008 Vertically orientated + wxSHEET_AttrOrientType_Mask = (wxSHEET_AttrOrientHoriz | wxSHEET_AttrOrientVert) }; // ---------------------------------------------------------------------------- // Level of the attribute if there are multiple attrs per cell // default ordering if all have same level is cell->row->col // default attributes for the wxSheet are initialized to wxSHEET_AttrLevelBottom -enum wxSheetAttrLevel_Type -{ - wxSHEET_AttrLevelUnset = 0, - wxSHEET_AttrLevelBottom = 0x0010000, - wxSHEET_AttrLevelMiddle = 0x0020000, - wxSHEET_AttrLevelTop = 0x0040000, - wxSHEET_AttrLevelType_Mask = (wxSHEET_AttrLevelBottom|wxSHEET_AttrLevelMiddle|wxSHEET_AttrLevelTop) +enum wxSheetAttrLevel_Type { + wxSHEET_AttrLevelUnset = 0, + wxSHEET_AttrLevelBottom = 0x0010000, + wxSHEET_AttrLevelMiddle = 0x0020000, + wxSHEET_AttrLevelTop = 0x0040000, + wxSHEET_AttrLevelType_Mask = + (wxSHEET_AttrLevelBottom | wxSHEET_AttrLevelMiddle | wxSHEET_AttrLevelTop) }; // ---------------------------------------------------------------------------- // Read/Write mode of an attribute -enum wxSheetAttrRead_Type -{ - wxSHEET_AttrReadUnset = 0, - wxSHEET_AttrReadWrite = 0x0100000, - wxSHEET_AttrReadOnly = 0x0200000, - wxSHEET_AttrReadType_Mask = (wxSHEET_AttrReadWrite|wxSHEET_AttrReadOnly) +enum wxSheetAttrRead_Type { + wxSHEET_AttrReadUnset = 0, + wxSHEET_AttrReadWrite = 0x0100000, + wxSHEET_AttrReadOnly = 0x0200000, + wxSHEET_AttrReadType_Mask = (wxSHEET_AttrReadWrite | wxSHEET_AttrReadOnly) }; // ---------------------------------------------------------------------------- // Can the cell contents overflow in the cells to the right? -enum wxSheetAttrOverflow_Type -{ - wxSHEET_AttrOverflowUnset = 0, - wxSHEET_AttrOverflow = 0x0400000, - wxSHEET_AttrOverflowNot = 0x0800000, - wxSHEET_AttrOverflowType_Mask = (wxSHEET_AttrOverflow|wxSHEET_AttrOverflowNot) +enum wxSheetAttrOverflow_Type { + wxSHEET_AttrOverflowUnset = 0, + wxSHEET_AttrOverflow = 0x0400000, + wxSHEET_AttrOverflowNot = 0x0800000, + wxSHEET_AttrOverflowType_Mask = (wxSHEET_AttrOverflow | wxSHEET_AttrOverflowNot) }; // ---------------------------------------------------------------------------- // If the cell contents overflows then should a |> tick mark be drawn to show it -enum wxSheetAttrOverflowMarker_Type -{ - wxSHEET_AttrOverflowMarkerUnset = 0, - wxSHEET_AttrOverflowMarker = 0x1000000, - wxSHEET_AttrOverflowMarkerNot = 0x2000000, - wxSHEET_AttrOverflowMarkerType_Mask = (wxSHEET_AttrOverflowMarker|wxSHEET_AttrOverflowMarkerNot) +enum wxSheetAttrOverflowMarker_Type { + wxSHEET_AttrOverflowMarkerUnset = 0, + wxSHEET_AttrOverflowMarker = 0x1000000, + wxSHEET_AttrOverflowMarkerNot = 0x2000000, + wxSHEET_AttrOverflowMarkerType_Mask = + (wxSHEET_AttrOverflowMarker | wxSHEET_AttrOverflowMarkerNot) }; // ---------------------------------------------------------------------------- // Should the editors always be shown FIXME not implemented -enum wxSheetAttrShowEditor_Type -{ - wxSHEET_AttrShowEditorUnset = 0, - wxSHEET_AttrShowEditor = 0x4000000, - wxSHEET_AttrShowEditorNot = 0x8000000, - wxSHEET_AttrShowEditorType_Mask = (wxSHEET_AttrShowEditor|wxSHEET_AttrShowEditorNot) +enum wxSheetAttrShowEditor_Type { + wxSHEET_AttrShowEditorUnset = 0, + wxSHEET_AttrShowEditor = 0x4000000, + wxSHEET_AttrShowEditorNot = 0x8000000, + wxSHEET_AttrShowEditorType_Mask = (wxSHEET_AttrShowEditor | wxSHEET_AttrShowEditorNot) }; // ---------------------------------------------------------------------------- @@ -354,60 +353,77 @@ enum wxSheetAttrShowEditor_Type // ---------------------------------------------------------------------------- #include "wx/sheet/sheetsel.h" -#define DECLARE_PAIREDSHEETCOORDS_DATA_ARRAYS(Tval, TvalArray, name, classexp) \ -DECLARE_PAIRED_DATA_ARRAYS_BASE(wxSheetCoords, wxArraySheetCoords, Tval, TvalArray, name, classexp) \ -public: \ - bool UpdateRows( size_t pos, int numRows ); \ - bool UpdateCols( size_t pos, int numCols ); \ -}; - -#define DEFINE_PAIREDSHEETCOORDS_DATA_ARRAYS(Tval, name) \ -DEFINE_PAIRED_DATA_ARRAYS(wxSheetCoords, Tval, name) \ -bool name::UpdateRows( size_t pos_, int numRows ) \ -{ \ - if (numRows == 0) return false; \ - int n, count = GetCount(), pos = pos_; \ - bool done = false, remove = numRows < 0; \ - for ( n = 0; n < count; n++ ) \ - { \ - wxSheetCoords& coords = GetItemKey(n); \ - if (coords.m_row >= pos) \ - { \ - if (remove && (coords.m_row < pos - numRows)) \ - { done = true; RemoveAt(n); count--; n--; } \ - else \ - { done = true; coords.m_row += numRows; } \ - } \ - } \ - return done; \ -} \ -bool name::UpdateCols( size_t pos_, int numCols ) \ -{ \ - if (numCols == 0) return false; \ - int n, count = GetCount(), pos = pos_; \ - bool done = false, remove = numCols < 0; \ - for ( n = 0; n < count; n++ ) \ - { \ - wxSheetCoords& coords = GetItemKey(n); \ - if (coords.m_col >= pos) \ - { \ - if (remove && (coords.m_col < pos - numCols)) \ - { done = true; RemoveAt(n); count--; n--; } \ - else \ - { done = true; coords.m_col += numCols; } \ - } \ - } \ - return done; \ -} +#define DECLARE_PAIREDSHEETCOORDS_DATA_ARRAYS(Tval, TvalArray, name, classexp) \ + DECLARE_PAIRED_DATA_ARRAYS_BASE(wxSheetCoords, wxArraySheetCoords, Tval, TvalArray, name, \ + classexp) \ +public: \ + bool UpdateRows(size_t pos, int numRows); \ + bool UpdateCols(size_t pos, int numCols); \ + } \ + ; + +#define DEFINE_PAIREDSHEETCOORDS_DATA_ARRAYS(Tval, name) \ + DEFINE_PAIRED_DATA_ARRAYS(wxSheetCoords, Tval, name) \ + bool name::UpdateRows(size_t pos_, int numRows) \ + { \ + if (numRows == 0) \ + return false; \ + int n, count = GetCount(), pos = pos_; \ + bool done = false, remove = numRows < 0; \ + for (n = 0; n < count; n++) { \ + wxSheetCoords &coords = GetItemKey(n); \ + if (coords.m_row >= pos) { \ + if (remove && (coords.m_row < pos - numRows)) { \ + done = true; \ + RemoveAt(n); \ + count--; \ + n--; \ + } \ + else { \ + done = true; \ + coords.m_row += numRows; \ + } \ + } \ + } \ + return done; \ + } \ + bool name::UpdateCols(size_t pos_, int numCols) \ + { \ + if (numCols == 0) \ + return false; \ + int n, count = GetCount(), pos = pos_; \ + bool done = false, remove = numCols < 0; \ + for (n = 0; n < count; n++) { \ + wxSheetCoords &coords = GetItemKey(n); \ + if (coords.m_col >= pos) { \ + if (remove && (coords.m_col < pos - numCols)) { \ + done = true; \ + RemoveAt(n); \ + count--; \ + n--; \ + } \ + else { \ + done = true; \ + coords.m_col += numCols; \ + } \ + } \ + } \ + return done; \ + } // ---------------------------------------------------------------------------- // DECLARE_SHEETOBJREFDATA_COPY_CLASS for Renderers and Editors // ---------------------------------------------------------------------------- // classes must define a "bool Copy(const classname& other)" function to copy all // the data in the class so that Clone can create a "new" copied instance. -#define DECLARE_SHEETOBJREFDATA_COPY_CLASS(classname, basename) \ - DECLARE_DYNAMIC_CLASS(classname) \ - public: \ - virtual basename * Clone() const { classname * aclass = new classname(); aclass->Copy( * ((classname * )this)); return (basename * )aclass; } - -#endif // __WX_SHEETDEF_H__ +#define DECLARE_SHEETOBJREFDATA_COPY_CLASS(classname, basename) \ + DECLARE_DYNAMIC_CLASS(classname) \ +public: \ + virtual basename *Clone() const \ + { \ + classname *aclass = new classname(); \ + aclass->Copy(*((classname *)this)); \ + return (basename *)aclass; \ + } + +#endif // __WX_SHEETDEF_H__ diff --git a/src/labenski/include/wx/sheet/sheetedg.h b/src/labenski/include/wx/sheet/sheetedg.h index 34426cac4..a06d956ee 100644 --- a/src/labenski/include/wx/sheet/sheetedg.h +++ b/src/labenski/include/wx/sheet/sheetedg.h @@ -19,8 +19,7 @@ // used to store the min col widths for rows and cols // ---------------------------------------------------------------------------- -DECLARE_PAIRED_INT_DATA_ARRAYS( int, wxArrayInt, - wxPairArrayIntInt, class WXDLLIMPEXP_SHEET ) +DECLARE_PAIRED_INT_DATA_ARRAYS(int, wxArrayInt, wxPairArrayIntInt, class WXDLLIMPEXP_SHEET) // ---------------------------------------------------------------------------- // wxSheetArrayEdge - a wxArrayInt container that sums its values, starts at 0 @@ -30,64 +29,66 @@ DECLARE_PAIRED_INT_DATA_ARRAYS( int, wxArrayInt, // Stores only the maxes (rights/bottoms) of the edges, but can be used // to get their mins (lefts/tops) and sizes (widths/heights). // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetArrayEdge -{ +class WXDLLIMPEXP_SHEET wxSheetArrayEdge { public: - // Create an array of initial 'count' edges with default_size - wxSheetArrayEdge( size_t count = 0, size_t default_size = 1, - size_t min_allowed_size = 0 ); + // Create an array of initial 'count' edges with default_size + wxSheetArrayEdge(size_t count = 0, size_t default_size = 1, size_t min_allowed_size = 0); - // Get the number of edges - int GetCount() const { return m_count; } - // Find the index of the element that corresponds to this coord - // if clipToMinMax return the min or max edge element, else -1 for out of bounds - int FindIndex(int val, bool clipToMinMax) const; - // Find the index of the element whose max edge is within +/- edge_size - int FindMaxEdgeIndex(int val, int edge_size = WXSHEET_LABEL_EDGE_ZONE) const; + // Get the number of edges + int GetCount() const { return m_count; } + // Find the index of the element that corresponds to this coord + // if clipToMinMax return the min or max edge element, else -1 for out of bounds + int FindIndex(int val, bool clipToMinMax) const; + // Find the index of the element whose max edge is within +/- edge_size + int FindMaxEdgeIndex(int val, int edge_size = WXSHEET_LABEL_EDGE_ZONE) const; - // Get the minimum of the element (left or top edge) - int GetMin(size_t index) const; - // Get the maximum of the element (right or bottom edge) - int GetMax(size_t index) const; - // Get the size of the element (width or height) - // note : GetSize(n) = GetMax(n) - GetMin(n) + 1; - // eg. 0123|4567|89 for index 1 : min = 4, max = 7, size = 4 = max-min+1 - int GetSize(size_t index) const; + // Get the minimum of the element (left or top edge) + int GetMin(size_t index) const; + // Get the maximum of the element (right or bottom edge) + int GetMax(size_t index) const; + // Get the size of the element (width or height) + // note : GetSize(n) = GetMax(n) - GetMin(n) + 1; + // eg. 0123|4567|89 for index 1 : min = 4, max = 7, size = 4 = max-min+1 + int GetSize(size_t index) const; - // Set the size of the element (width or height) - void SetSize(size_t item, int size); + // Set the size of the element (width or height) + void SetSize(size_t item, int size); - // Get the default size to use between the edges - int GetDefaultSize() const { return m_default_size; } - // Set the default size to use between edges, used when inserting - // if resizeExisting then make all equal widths - void SetDefaultSize(int default_size, bool resizeExisting = false); + // Get the default size to use between the edges + int GetDefaultSize() const { return m_default_size; } + // Set the default size to use between edges, used when inserting + // if resizeExisting then make all equal widths + void SetDefaultSize(int default_size, bool resizeExisting = false); - // Get the minimum size for this index, = GetMinAllowedSize unless set higher - int GetMinSize(size_t index) const; - // Set the minimum size for this index, must be >= min allowed size - void SetMinSize(size_t index, int size); + // Get the minimum size for this index, = GetMinAllowedSize unless set higher + int GetMinSize(size_t index) const; + // Set the minimum size for this index, must be >= min allowed size + void SetMinSize(size_t index, int size); - // Get the min allowed size for all elements - int GetMinAllowedSize() const { return m_min_allowed_size; } - // set the min allowed size, resize the existing sizes to match the min size - // if resizeExisting and return if anything was done - bool SetMinAllowedSize(int min_allowed_size, bool resizeExisting = false); + // Get the min allowed size for all elements + int GetMinAllowedSize() const { return m_min_allowed_size; } + // set the min allowed size, resize the existing sizes to match the min size + // if resizeExisting and return if anything was done + bool SetMinAllowedSize(int min_allowed_size, bool resizeExisting = false); - // Clear the number of edges to zero - void Clear() { m_data.Clear(); m_count = 0; } - // Update the number of edges by inserting at pos if num > 0, else deleting - // inserts use the defaut size. - void UpdatePos(size_t pos, int num); + // Clear the number of edges to zero + void Clear() + { + m_data.Clear(); + m_count = 0; + } + // Update the number of edges by inserting at pos if num > 0, else deleting + // inserts use the defaut size. + void UpdatePos(size_t pos, int num); protected: - bool CheckMinimize(); // maybe we don't need the array anymore - void InitArray(); // init array to the default size - int m_count; // number of elements - int m_default_size; // default size to init with - int m_min_allowed_size; // overall min allowed size - wxArrayInt m_data; // maxes of each index, filled as needed - wxPairArrayIntInt m_minSizes; // min sizes for specific indexes + bool CheckMinimize(); // maybe we don't need the array anymore + void InitArray(); // init array to the default size + int m_count; // number of elements + int m_default_size; // default size to init with + int m_min_allowed_size; // overall min allowed size + wxArrayInt m_data; // maxes of each index, filled as needed + wxPairArrayIntInt m_minSizes; // min sizes for specific indexes }; -#endif // __WX_SHEETEDG_H__ +#endif // __WX_SHEETEDG_H__ diff --git a/src/labenski/include/wx/sheet/sheetedt.h b/src/labenski/include/wx/sheet/sheetedt.h index 3ff5b8459..22dec6194 100644 --- a/src/labenski/include/wx/sheet/sheetedt.h +++ b/src/labenski/include/wx/sheet/sheetedt.h @@ -29,25 +29,24 @@ class WXDLLEXPORT wxSpinCtrl; // forwards the keydown and char events to the sheet. // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellEditorEvtHandler : public wxEvtHandler -{ +class WXDLLIMPEXP_SHEET wxSheetCellEditorEvtHandler : public wxEvtHandler { public: - wxSheetCellEditorEvtHandler() : m_sheet(NULL), m_editor(NULL) { } - wxSheetCellEditorEvtHandler(wxSheet* sheet, const wxSheetCellEditor &editor); + wxSheetCellEditorEvtHandler() : m_sheet(NULL), m_editor(NULL) {} + wxSheetCellEditorEvtHandler(wxSheet *sheet, const wxSheetCellEditor &editor); - void OnKeyDown(wxKeyEvent& event); - void OnChar(wxKeyEvent& event); - void OnDestroy(wxWindowDestroyEvent& event); + void OnKeyDown(wxKeyEvent &event); + void OnChar(wxKeyEvent &event); + void OnDestroy(wxWindowDestroyEvent &event); - wxSheet *m_sheet; - // This is a pointer, not a refed editor since editor's destructor - // pops event handler which deletes this and we don't want recursion - wxSheetCellEditorRefData *m_editor; + wxSheet *m_sheet; + // This is a pointer, not a refed editor since editor's destructor + // pops event handler which deletes this and we don't want recursion + wxSheetCellEditorRefData *m_editor; private: - DECLARE_DYNAMIC_CLASS(wxSheetCellEditorEvtHandler) - DECLARE_EVENT_TABLE() - DECLARE_NO_COPY_CLASS(wxSheetCellEditorEvtHandler) + DECLARE_DYNAMIC_CLASS(wxSheetCellEditorEvtHandler) + DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxSheetCellEditorEvtHandler) }; // ---------------------------------------------------------------------------- @@ -60,103 +59,106 @@ class WXDLLIMPEXP_SHEET wxSheetCellEditorEvtHandler : public wxEvtHandler // even for the entire grid (the default). // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellEditor : public wxObject -{ +class WXDLLIMPEXP_SHEET wxSheetCellEditor : public wxObject { public: - wxSheetCellEditor( wxSheetCellEditorRefData *editor = NULL ); - wxSheetCellEditor( const wxSheetCellEditor& editor ) { Ref(editor); } - - void Destroy() { UnRef(); } - bool Ok() const { return m_refData != NULL; } - - // Is this editor ready to use (typically means the control is created) - bool IsCreated() const; - // Is the control currently shown - bool IsShown() const; - - // Get a pointer to the control - wxWindow* GetControl() const; - // Destroy the old control (if any) and set the new one - void SetControl(wxWindow* control); - // Destroy the control, doesn't fail even if the control isn't created - void DestroyControl(); - - // Creates the actual edit control using the parent, id, and - // pushing the evtHandler onto it if !NULL. - void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); - - // Size and position the edit control, uses attr.GetAlignment if Ok. - void SetSize(const wxRect& rect, const wxSheetCellAttr& attr); - // get the preferred size of the editor for its contents - wxSize GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, - const wxSheetCoords& coords); - // Show or hide the edit control, use the specified attributes to set - // colours/fonts for it if attr is Ok. - void Show(bool show, const wxSheetCellAttr &attr); - // Draws the part of the cell not occupied by the control: the base class - // version just fills it with background colour from the attribute - void PaintBackground(wxSheet& grid, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); - // Fetch the value from the table and prepare the edit control - // to begin editing. Set the focus to the edit control. - void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); - // Complete the editing of the current cell. Returns true if the value has - // changed. If necessary, the control may be destroyed. - bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); - // Reset the value in the control back to its starting value - void ResetValue(); - - // return true to allow the given key to start editing: the base class - // version only checks that the event has no modifiers. The derived - // classes are supposed to do "if ( base::IsAcceptedKey() && ... )" in - // their IsAcceptedKey() implementation, although, of course, it is not a - // mandatory requirment. - // - // NB: if the key is F2 (special), editing will always start and this - // method will not be called at all (but StartingKey() will) - bool IsAcceptedKey(wxKeyEvent& event); - // If the editor is enabled by pressing keys on the grid, this will be - // called to let the editor do something about that first key if desired - void StartingKey(wxKeyEvent& event); - // if the editor is enabled by clicking on the cell, this method will be - // called - void StartingClick(); - // Some types of controls on some platforms may need some help - // with the Return key. - void HandleReturn(wxKeyEvent& event); - - // the wxSheetCellEditorEvtHandler passes the key event here first - // return false to stop default EvtHandler processing - bool OnKeyDown(wxKeyEvent& event); - // the wxSheetCellEditorEvtHandler passes the key event here first - // return false to stop default EvtHandler processing - bool OnChar(wxKeyEvent& event); - - // interpret renderer parameters: arbitrary string whose interpretation is - // left to the derived classes - void SetParameters(const wxString& params); - - // Get the current value of the control as a string - wxString GetValue() const; - // Get the value that the editor started with - wxString GetInitValue() const; - - bool Copy(const wxSheetCellEditor& other); - - // operators - bool operator == (const wxSheetCellEditor& obj) const { return m_refData == obj.m_refData; } - bool operator != (const wxSheetCellEditor& obj) const { return m_refData != obj.m_refData; } - wxSheetCellEditor& operator = (const wxSheetCellEditor& obj) - { - if ( (*this) != obj ) Ref(obj); - return *this; + wxSheetCellEditor(wxSheetCellEditorRefData *editor = NULL); + wxSheetCellEditor(const wxSheetCellEditor &editor) { Ref(editor); } + + void Destroy() { UnRef(); } + bool Ok() const { return m_refData != NULL; } + + // Is this editor ready to use (typically means the control is created) + bool IsCreated() const; + // Is the control currently shown + bool IsShown() const; + + // Get a pointer to the control + wxWindow *GetControl() const; + // Destroy the old control (if any) and set the new one + void SetControl(wxWindow *control); + // Destroy the control, doesn't fail even if the control isn't created + void DestroyControl(); + + // Creates the actual edit control using the parent, id, and + // pushing the evtHandler onto it if !NULL. + void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, wxSheet *sheet); + + // Size and position the edit control, uses attr.GetAlignment if Ok. + void SetSize(const wxRect &rect, const wxSheetCellAttr &attr); + // get the preferred size of the editor for its contents + wxSize GetBestSize(wxSheet &grid, const wxSheetCellAttr &attr, const wxSheetCoords &coords); + // Show or hide the edit control, use the specified attributes to set + // colours/fonts for it if attr is Ok. + void Show(bool show, const wxSheetCellAttr &attr); + // Draws the part of the cell not occupied by the control: the base class + // version just fills it with background colour from the attribute + void PaintBackground(wxSheet &grid, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); + // Fetch the value from the table and prepare the edit control + // to begin editing. Set the focus to the edit control. + void BeginEdit(const wxSheetCoords &coords, wxSheet *grid); + // Complete the editing of the current cell. Returns true if the value has + // changed. If necessary, the control may be destroyed. + bool EndEdit(const wxSheetCoords &coords, wxSheet *grid); + // Reset the value in the control back to its starting value + void ResetValue(); + + // return true to allow the given key to start editing: the base class + // version only checks that the event has no modifiers. The derived + // classes are supposed to do "if ( base::IsAcceptedKey() && ... )" in + // their IsAcceptedKey() implementation, although, of course, it is not a + // mandatory requirment. + // + // NB: if the key is F2 (special), editing will always start and this + // method will not be called at all (but StartingKey() will) + bool IsAcceptedKey(wxKeyEvent &event); + // If the editor is enabled by pressing keys on the grid, this will be + // called to let the editor do something about that first key if desired + void StartingKey(wxKeyEvent &event); + // if the editor is enabled by clicking on the cell, this method will be + // called + void StartingClick(); + // Some types of controls on some platforms may need some help + // with the Return key. + void HandleReturn(wxKeyEvent &event); + + // the wxSheetCellEditorEvtHandler passes the key event here first + // return false to stop default EvtHandler processing + bool OnKeyDown(wxKeyEvent &event); + // the wxSheetCellEditorEvtHandler passes the key event here first + // return false to stop default EvtHandler processing + bool OnChar(wxKeyEvent &event); + + // interpret renderer parameters: arbitrary string whose interpretation is + // left to the derived classes + void SetParameters(const wxString ¶ms); + + // Get the current value of the control as a string + wxString GetValue() const; + // Get the value that the editor started with + wxString GetInitValue() const; + + bool Copy(const wxSheetCellEditor &other); + + // operators + bool operator==(const wxSheetCellEditor &obj) const { return m_refData == obj.m_refData; } + bool operator!=(const wxSheetCellEditor &obj) const { return m_refData != obj.m_refData; } + wxSheetCellEditor &operator=(const wxSheetCellEditor &obj) + { + if ((*this) != obj) { + Ref(obj); } - - wxSheetCellEditor Clone() const { wxSheetCellEditor obj; obj.Copy(*this); return obj; } - wxSheetCellEditor* NewClone() const { return new wxSheetCellEditor(Clone()); } - DECLARE_DYNAMIC_CLASS(wxSheetCellEditor) + return *this; + } + + wxSheetCellEditor Clone() const + { + wxSheetCellEditor obj; + obj.Copy(*this); + return obj; + } + wxSheetCellEditor *NewClone() const { return new wxSheetCellEditor(Clone()); } + DECLARE_DYNAMIC_CLASS(wxSheetCellEditor) }; WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellEditor) wxNullSheetCellEditor; @@ -164,50 +166,50 @@ WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellEditor) wxNullSheetCellEditor; // ---------------------------------------------------------------------------- // wxSheetCellEditorRefData // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellEditorRefData : public wxObject, public wxObjectRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellEditorRefData : public wxObject, public wxObjectRefData { public: - wxSheetCellEditorRefData() : m_control(NULL) {} - virtual ~wxSheetCellEditorRefData(); - - virtual bool IsCreated() const { return (GetControl() != NULL); } - virtual bool IsShown() const; - - wxWindow* GetControl() const { return m_control; } - virtual void SetControl(wxWindow* control); - virtual void DestroyControl(); - - virtual void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); - virtual void SetSize(const wxRect& rect, const wxSheetCellAttr &attr); - // get the preferred size of the cell for its contents - virtual wxSize GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, - const wxSheetCoords& coords); - - virtual void Show(bool show, const wxSheetCellAttr &attr); - virtual void PaintBackground(wxSheet& grid, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); - virtual void BeginEdit(const wxSheetCoords& WXUNUSED(coords), wxSheet* WXUNUSED(grid)) {} - virtual bool EndEdit(const wxSheetCoords& WXUNUSED(coords), wxSheet* WXUNUSED(grid)) { return false; } - virtual void ResetValue() {} - - virtual bool IsAcceptedKey(wxKeyEvent& event); - virtual void StartingKey(wxKeyEvent& event) { event.Skip(); } - virtual bool OnKeyDown(wxKeyEvent& WXUNUSED(event)) { return true; } - virtual bool OnChar(wxKeyEvent& WXUNUSED(event)) { return true; } - virtual void StartingClick() {} - virtual void HandleReturn(wxKeyEvent& event) { event.Skip(); } - - virtual void SetParameters(const wxString& WXUNUSED(params)) {} - virtual wxString GetValue() const { return wxEmptyString; } - virtual wxString GetInitValue() const { return wxEmptyString; } - - bool Copy(const wxSheetCellEditorRefData& WXUNUSED(other)) { return true; } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEditorRefData, - wxSheetCellEditorRefData) - - wxWindow* m_control; // the control we show on screen + wxSheetCellEditorRefData() : m_control(NULL) {} + virtual ~wxSheetCellEditorRefData(); + + virtual bool IsCreated() const { return (GetControl() != NULL); } + virtual bool IsShown() const; + + wxWindow *GetControl() const { return m_control; } + virtual void SetControl(wxWindow *control); + virtual void DestroyControl(); + + virtual void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet); + virtual void SetSize(const wxRect &rect, const wxSheetCellAttr &attr); + // get the preferred size of the cell for its contents + virtual wxSize GetBestSize(wxSheet &grid, const wxSheetCellAttr &attr, + const wxSheetCoords &coords); + + virtual void Show(bool show, const wxSheetCellAttr &attr); + virtual void PaintBackground(wxSheet &grid, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect, const wxSheetCoords &coords, bool isSelected); + virtual void BeginEdit(const wxSheetCoords &WXUNUSED(coords), wxSheet *WXUNUSED(grid)) {} + virtual bool EndEdit(const wxSheetCoords &WXUNUSED(coords), wxSheet *WXUNUSED(grid)) + { + return false; + } + virtual void ResetValue() {} + + virtual bool IsAcceptedKey(wxKeyEvent &event); + virtual void StartingKey(wxKeyEvent &event) { event.Skip(); } + virtual bool OnKeyDown(wxKeyEvent &WXUNUSED(event)) { return true; } + virtual bool OnChar(wxKeyEvent &WXUNUSED(event)) { return true; } + virtual void StartingClick() {} + virtual void HandleReturn(wxKeyEvent &event) { event.Skip(); } + + virtual void SetParameters(const wxString &WXUNUSED(params)) {} + virtual wxString GetValue() const { return wxEmptyString; } + virtual wxString GetInitValue() const { return wxEmptyString; } + + bool Copy(const wxSheetCellEditorRefData &WXUNUSED(other)) { return true; } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEditorRefData, wxSheetCellEditorRefData) + + wxWindow *m_control; // the control we show on screen }; //----------------------------------------------------------------------------- @@ -215,66 +217,69 @@ class WXDLLIMPEXP_SHEET wxSheetCellEditorRefData : public wxObject, public wxObj //----------------------------------------------------------------------------- #if wxUSE_TEXTCTRL -class WXDLLIMPEXP_SHEET wxSheetCellTextEditorRefData : public wxSheetCellEditorRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellTextEditorRefData : public wxSheetCellEditorRefData { public: - wxSheetCellTextEditorRefData() : m_maxChars(0) {} + wxSheetCellTextEditorRefData() : m_maxChars(0) {} - virtual void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); - virtual void SetSize(const wxRect& rect, const wxSheetCellAttr &attr); + virtual void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet); + virtual void SetSize(const wxRect &rect, const wxSheetCellAttr &attr); - virtual void PaintBackground(wxSheet& , const wxSheetCellAttr& , - wxDC& , const wxRect& , - const wxSheetCoords& , bool ) {} + virtual void PaintBackground(wxSheet &, const wxSheetCellAttr &, wxDC &, const wxRect &, + const wxSheetCoords &, bool) + { + } - virtual bool IsAcceptedKey(wxKeyEvent& event); - virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); - virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); + virtual bool IsAcceptedKey(wxKeyEvent &event); + virtual void BeginEdit(const wxSheetCoords &coords, wxSheet *grid); + virtual bool EndEdit(const wxSheetCoords &coords, wxSheet *grid); - virtual void ResetValue(); - virtual void StartingKey(wxKeyEvent& event); - virtual void HandleReturn(wxKeyEvent& event); - virtual bool OnChar(wxKeyEvent& event); + virtual void ResetValue(); + virtual void StartingKey(wxKeyEvent &event); + virtual void HandleReturn(wxKeyEvent &event); + virtual bool OnChar(wxKeyEvent &event); - // parameters string format is "max_width" - virtual void SetParameters(const wxString& params); + // parameters string format is "max_width" + virtual void SetParameters(const wxString ¶ms); - virtual wxString GetValue() const; - virtual wxString GetInitValue() const { return m_startValue; } + virtual wxString GetValue() const; + virtual wxString GetInitValue() const { return m_startValue; } - bool Copy(const wxSheetCellTextEditorRefData& other) - { return wxSheetCellEditorRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellTextEditorRefData, - wxSheetCellEditorRefData) + bool Copy(const wxSheetCellTextEditorRefData &other) + { + return wxSheetCellEditorRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellTextEditorRefData, wxSheetCellEditorRefData) - // parts of our virtual functions reused by the derived classes - void DoBeginEdit(const wxString& startValue); - void DoResetValue(const wxString& startValue); + // parts of our virtual functions reused by the derived classes + void DoBeginEdit(const wxString &startValue); + void DoResetValue(const wxString &startValue); - wxTextCtrl *GetTextCtrl() const { return (wxTextCtrl *)GetControl(); } + wxTextCtrl *GetTextCtrl() const { return (wxTextCtrl *)GetControl(); } - size_t m_maxChars; // max number of chars allowed - wxString m_startValue; - int m_maxLength; // largest length in the textctrl yet + size_t m_maxChars; // max number of chars allowed + wxString m_startValue; + int m_maxLength; // largest length in the textctrl yet }; // ---------------------------------------------------------------------------- // wxSheetCellAutoWrapStringEditorRefData // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringEditorRefData : public wxSheetCellTextEditorRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringEditorRefData + : public wxSheetCellTextEditorRefData { public: - wxSheetCellAutoWrapStringEditorRefData() : wxSheetCellTextEditorRefData() { } + wxSheetCellAutoWrapStringEditorRefData() : wxSheetCellTextEditorRefData() {} - virtual void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); + virtual void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet); - bool Copy(const wxSheetCellAutoWrapStringEditorRefData& other) - { return wxSheetCellTextEditorRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellAutoWrapStringEditorRefData, - wxSheetCellEditorRefData) + bool Copy(const wxSheetCellAutoWrapStringEditorRefData &other) + { + return wxSheetCellTextEditorRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellAutoWrapStringEditorRefData, + wxSheetCellEditorRefData) }; #endif // wxUSE_TEXTCTRL @@ -284,81 +289,79 @@ class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringEditorRefData : public wxSheetC //----------------------------------------------------------------------------- #if defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) -class WXDLLIMPEXP_SHEET wxSheetCellNumberEditorRefData : public wxSheetCellTextEditorRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellNumberEditorRefData : public wxSheetCellTextEditorRefData { public: - // specify the range - if min == max == -1, no range checking is done - wxSheetCellNumberEditorRefData(int min = -1, int max = -1) - : m_min(min), m_max(max), m_startValue(0) {} + // specify the range - if min == max == -1, no range checking is done + wxSheetCellNumberEditorRefData(int min = -1, int max = -1) + : m_min(min), m_max(max), m_startValue(0) + { + } - virtual void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); + virtual void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet); - virtual bool IsAcceptedKey(wxKeyEvent& event); - virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); - virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); + virtual bool IsAcceptedKey(wxKeyEvent &event); + virtual void BeginEdit(const wxSheetCoords &coords, wxSheet *grid); + virtual bool EndEdit(const wxSheetCoords &coords, wxSheet *grid); - virtual void ResetValue(); - virtual void StartingKey(wxKeyEvent& event); + virtual void ResetValue(); + virtual void StartingKey(wxKeyEvent &event); - // parameters string format is "min,max" - virtual void SetParameters(const wxString& params); + // parameters string format is "min,max" + virtual void SetParameters(const wxString ¶ms); - virtual wxString GetValue() const; - int GetValueInt() const; - virtual wxString GetInitValue() const; + virtual wxString GetValue() const; + int GetValueInt() const; + virtual wxString GetInitValue() const; - // if HasRange(), we use wxSpinCtrl - otherwise wxTextCtrl - bool HasRange() const { return m_min != m_max; } + // if HasRange(), we use wxSpinCtrl - otherwise wxTextCtrl + bool HasRange() const { return m_min != m_max; } - bool Copy(const wxSheetCellNumberEditorRefData& other); - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellNumberEditorRefData, - wxSheetCellEditorRefData) + bool Copy(const wxSheetCellNumberEditorRefData &other); + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellNumberEditorRefData, wxSheetCellEditorRefData) - wxSpinCtrl *GetSpinCtrl() const { return (wxSpinCtrl *)GetControl(); } + wxSpinCtrl *GetSpinCtrl() const { return (wxSpinCtrl *)GetControl(); } - int m_min, - m_max; + int m_min, m_max; - long m_startValue; + long m_startValue; }; -#endif //defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) +#endif // defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) //----------------------------------------------------------------------------- // wxSheetCellFloatEditorRefData: the editor for floating point numbers (double) data //----------------------------------------------------------------------------- #if wxUSE_TEXTCTRL -class WXDLLIMPEXP_SHEET wxSheetCellFloatEditorRefData : public wxSheetCellTextEditorRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellFloatEditorRefData : public wxSheetCellTextEditorRefData { public: - wxSheetCellFloatEditorRefData(int width = -1, int precision = -1) - : m_width(width), m_precision(precision), m_startValue(0) {} + wxSheetCellFloatEditorRefData(int width = -1, int precision = -1) + : m_width(width), m_precision(precision), m_startValue(0) + { + } - virtual void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); + virtual void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet); - virtual bool IsAcceptedKey(wxKeyEvent& event); - virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); - virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); + virtual bool IsAcceptedKey(wxKeyEvent &event); + virtual void BeginEdit(const wxSheetCoords &coords, wxSheet *grid); + virtual bool EndEdit(const wxSheetCoords &coords, wxSheet *grid); - virtual void ResetValue(); - virtual void StartingKey(wxKeyEvent& event); + virtual void ResetValue(); + virtual void StartingKey(wxKeyEvent &event); - // parameters string format is "width,precision" - virtual void SetParameters(const wxString& params); + // parameters string format is "width,precision" + virtual void SetParameters(const wxString ¶ms); - // string representation of a double value - virtual wxString GetInitValue() const { return GetStringValue(m_startValue); } - virtual wxString GetStringValue(double value) const; + // string representation of a double value + virtual wxString GetInitValue() const { return GetStringValue(m_startValue); } + virtual wxString GetStringValue(double value) const; - bool Copy(const wxSheetCellFloatEditorRefData& other); - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellFloatEditorRefData, - wxSheetCellEditorRefData) + bool Copy(const wxSheetCellFloatEditorRefData &other); + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellFloatEditorRefData, wxSheetCellEditorRefData) - int m_width, - m_precision; - double m_startValue; + int m_width, m_precision; + double m_startValue; }; #endif // wxUSE_TEXTCTRL @@ -368,34 +371,34 @@ class WXDLLIMPEXP_SHEET wxSheetCellFloatEditorRefData : public wxSheetCellTextEd //----------------------------------------------------------------------------- #if wxUSE_CHECKBOX -class WXDLLIMPEXP_SHEET wxSheetCellBoolEditorRefData : public wxSheetCellEditorRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellBoolEditorRefData : public wxSheetCellEditorRefData { public: - wxSheetCellBoolEditorRefData() : m_startValue(false) {} + wxSheetCellBoolEditorRefData() : m_startValue(false) {} - virtual void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); + virtual void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet); - virtual void SetSize(const wxRect& rect, const wxSheetCellAttr &attr); - virtual void Show(bool show, const wxSheetCellAttr &attr); + virtual void SetSize(const wxRect &rect, const wxSheetCellAttr &attr); + virtual void Show(bool show, const wxSheetCellAttr &attr); - virtual bool IsAcceptedKey(wxKeyEvent& event); - virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); - virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); + virtual bool IsAcceptedKey(wxKeyEvent &event); + virtual void BeginEdit(const wxSheetCoords &coords, wxSheet *grid); + virtual bool EndEdit(const wxSheetCoords &coords, wxSheet *grid); - virtual void ResetValue(); - virtual void StartingClick(); + virtual void ResetValue(); + virtual void StartingClick(); - virtual wxString GetValue() const; + virtual wxString GetValue() const; - bool Copy(const wxSheetCellBoolEditorRefData& other) - { return wxSheetCellEditorRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBoolEditorRefData, - wxSheetCellEditorRefData) + bool Copy(const wxSheetCellBoolEditorRefData &other) + { + return wxSheetCellEditorRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBoolEditorRefData, wxSheetCellEditorRefData) - wxCheckBox *GetCheckBox() const { return (wxCheckBox *)GetControl(); } + wxCheckBox *GetCheckBox() const { return (wxCheckBox *)GetControl(); } - bool m_startValue; + bool m_startValue; }; #endif // wxUSE_CHECKBOX @@ -405,61 +408,56 @@ class WXDLLIMPEXP_SHEET wxSheetCellBoolEditorRefData : public wxSheetCellEditorR //----------------------------------------------------------------------------- #if wxUSE_COMBOBOX -class WXDLLIMPEXP_SHEET wxSheetCellChoiceEditorRefData : public wxSheetCellEditorRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellChoiceEditorRefData : public wxSheetCellEditorRefData { public: - // if !allowOthers, user can't type a string not in choices array - wxSheetCellChoiceEditorRefData(size_t count = 0, - const wxString choices[] = NULL, - bool allowOthers = false); - wxSheetCellChoiceEditorRefData(const wxArrayString& choices, - bool allowOthers = false); + // if !allowOthers, user can't type a string not in choices array + wxSheetCellChoiceEditorRefData(size_t count = 0, const wxString choices[] = NULL, + bool allowOthers = false); + wxSheetCellChoiceEditorRefData(const wxArrayString &choices, bool allowOthers = false); - virtual void CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet); + virtual void CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet); - virtual void PaintBackground(wxSheet& grid, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + virtual void PaintBackground(wxSheet &grid, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect, const wxSheetCoords &coords, bool isSelected); - virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); - virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); + virtual void BeginEdit(const wxSheetCoords &coords, wxSheet *grid); + virtual bool EndEdit(const wxSheetCoords &coords, wxSheet *grid); - virtual void ResetValue(); + virtual void ResetValue(); - // parameters string format is "item1[,item2[...,itemN]]" - virtual void SetParameters(const wxString& params); + // parameters string format is "item1[,item2[...,itemN]]" + virtual void SetParameters(const wxString ¶ms); - virtual wxString GetValue() const; + virtual wxString GetValue() const; - bool Copy(const wxSheetCellChoiceEditorRefData& other); - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellChoiceEditorRefData, - wxSheetCellEditorRefData) + bool Copy(const wxSheetCellChoiceEditorRefData &other); + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellChoiceEditorRefData, wxSheetCellEditorRefData) - wxComboBox *GetComboBox() const { return (wxComboBox *)GetControl(); } - wxString m_startValue; - wxArrayString m_choices; - bool m_allowOthers; + wxComboBox *GetComboBox() const { return (wxComboBox *)GetControl(); } + wxString m_startValue; + wxArrayString m_choices; + bool m_allowOthers; }; // ---------------------------------------------------------------------------- // wxSheetCellEnumEditorRefData // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellEnumEditorRefData : public wxSheetCellChoiceEditorRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellEnumEditorRefData : public wxSheetCellChoiceEditorRefData { public: - wxSheetCellEnumEditorRefData( const wxString& choices = wxEmptyString ); + wxSheetCellEnumEditorRefData(const wxString &choices = wxEmptyString); - virtual bool EndEdit(const wxSheetCoords& coords, wxSheet* grid); - virtual void BeginEdit(const wxSheetCoords& coords, wxSheet* grid); + virtual bool EndEdit(const wxSheetCoords &coords, wxSheet *grid); + virtual void BeginEdit(const wxSheetCoords &coords, wxSheet *grid); - bool Copy(const wxSheetCellEnumEditorRefData& other) - { return wxSheetCellChoiceEditorRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEnumEditorRefData, - wxSheetCellEditorRefData) + bool Copy(const wxSheetCellEnumEditorRefData &other) + { + return wxSheetCellChoiceEditorRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEnumEditorRefData, wxSheetCellEditorRefData) - long int m_startint; + long int m_startint; }; #endif // wxUSE_COMBOBOX diff --git a/src/labenski/include/wx/sheet/sheetren.h b/src/labenski/include/wx/sheet/sheetren.h index d5cef32b9..b2a76a1f7 100644 --- a/src/labenski/include/wx/sheet/sheetren.h +++ b/src/labenski/include/wx/sheet/sheetren.h @@ -29,45 +29,50 @@ class WXDLLIMPEXP_SHEET wxSheetCellRendererRefData; // wxSheetCellRendererRefData. All the functions are passed directly to the // ref counted renderer. // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellRenderer : public wxObject -{ +class WXDLLIMPEXP_SHEET wxSheetCellRenderer : public wxObject { public: - wxSheetCellRenderer(wxSheetCellRendererRefData *renderer = NULL); - wxSheetCellRenderer( const wxSheetCellRenderer& renderer ) { Ref(renderer); } + wxSheetCellRenderer(wxSheetCellRendererRefData *renderer = NULL); + wxSheetCellRenderer(const wxSheetCellRenderer &renderer) { Ref(renderer); } - void Destroy() { UnRef(); } + void Destroy() { UnRef(); } - bool Ok() const { return m_refData != NULL; } + bool Ok() const { return m_refData != NULL; } - // draw the given cell on the provided DC inside the given rectangle - // using the style specified by the attribute and the default or selected - // state corresponding to the isSelected value. - void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + // draw the given cell on the provided DC inside the given rectangle + // using the style specified by the attribute and the default or selected + // state corresponding to the isSelected value. + void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - // get the preferred size of the cell for its contents - wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxSheetCoords& coords); + // get the preferred size of the cell for its contents + wxSize GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords); - // interpret renderer parameters: arbitrary string whose interpretation is - // left to the derived classes - void SetParameters(const wxString& params); + // interpret renderer parameters: arbitrary string whose interpretation is + // left to the derived classes + void SetParameters(const wxString ¶ms); - bool Copy(const wxSheetCellRenderer& other); + bool Copy(const wxSheetCellRenderer &other); - // operators - bool operator == (const wxSheetCellRenderer& obj) const { return m_refData == obj.m_refData; } - bool operator != (const wxSheetCellRenderer& obj) const { return m_refData != obj.m_refData; } - wxSheetCellRenderer& operator = (const wxSheetCellRenderer& obj) - { - if ( (*this) != obj ) Ref(obj); - return *this; + // operators + bool operator==(const wxSheetCellRenderer &obj) const { return m_refData == obj.m_refData; } + bool operator!=(const wxSheetCellRenderer &obj) const { return m_refData != obj.m_refData; } + wxSheetCellRenderer &operator=(const wxSheetCellRenderer &obj) + { + if ((*this) != obj) { + Ref(obj); } - - wxSheetCellRenderer Clone() const { wxSheetCellRenderer obj; obj.Copy(*this); return obj; } - wxSheetCellRenderer* NewClone() const { return new wxSheetCellRenderer(Clone()); } - DECLARE_DYNAMIC_CLASS(wxSheetCellRenderer) + return *this; + } + + wxSheetCellRenderer Clone() const + { + wxSheetCellRenderer obj; + obj.Copy(*this); + return obj; + } + wxSheetCellRenderer *NewClone() const { return new wxSheetCellRenderer(Clone()); } + DECLARE_DYNAMIC_CLASS(wxSheetCellRenderer) }; WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellRenderer) wxNullSheetCellRenderer; @@ -75,33 +80,30 @@ WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCellRenderer) wxNullSheetCellRenderer // ---------------------------------------------------------------------------- // wxSheetCellRendererRefData - base class for rendering a cell // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellRendererRefData : public wxObjectRefData, public wxObject -{ +class WXDLLIMPEXP_SHEET wxSheetCellRendererRefData : public wxObjectRefData, public wxObject { public: - wxSheetCellRendererRefData() {} - - // this pure virtual function has a default implementation which will - // prepare the DC using the given attribute: it will draw the cell rectangle - // with the bg colour from attr and set the dc's text colour and font - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); - - // get the preferred size of the cell for its contents - virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxSheetCoords& coords); - - // Get a string representation of the cell value - virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); - - // interpret renderer parameters: arbitrary string whose interpretation is - // left to the derived classes - virtual void SetParameters(const wxString& WXUNUSED(params)) {} - - // always define Copy for DECLARE_SHEETOBJREFDATA_COPY_CLASS - bool Copy(const wxSheetCellRendererRefData& WXUNUSED(other)) { return true; } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellRendererRefData, - wxSheetCellRendererRefData) + wxSheetCellRendererRefData() {} + + // this pure virtual function has a default implementation which will + // prepare the DC using the given attribute: it will draw the cell rectangle + // with the bg colour from attr and set the dc's text colour and font + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); + + // get the preferred size of the cell for its contents + virtual wxSize GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords); + + // Get a string representation of the cell value + virtual wxString GetString(wxSheet &sheet, const wxSheetCoords &coords); + + // interpret renderer parameters: arbitrary string whose interpretation is + // left to the derived classes + virtual void SetParameters(const wxString &WXUNUSED(params)) {} + + // always define Copy for DECLARE_SHEETOBJREFDATA_COPY_CLASS + bool Copy(const wxSheetCellRendererRefData &WXUNUSED(other)) { return true; } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellRendererRefData, wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- @@ -109,61 +111,60 @@ class WXDLLIMPEXP_SHEET wxSheetCellRendererRefData : public wxObjectRefData, pub // ---------------------------------------------------------------------------- // the default renderer for the cells containing string data -class WXDLLIMPEXP_SHEET wxSheetCellStringRendererRefData : public wxSheetCellRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellStringRendererRefData : public wxSheetCellRendererRefData { public: - wxSheetCellStringRendererRefData(); + wxSheetCellStringRendererRefData(); - // draw the string - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + // draw the string + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - // return the string extent - virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxSheetCoords& coords); + // return the string extent + virtual wxSize GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords); - void DoDraw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + void DoDraw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - // set the text colours before drawing - void SetTextColoursAndFont(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, bool isSelected); + // set the text colours before drawing + void SetTextColoursAndFont(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + bool isSelected); - // calc the string extent for given string/font - wxSize DoGetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxString& text); + // calc the string extent for given string/font + wxSize DoGetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxString &text); - bool Copy(const wxSheetCellStringRendererRefData& other) - { return wxSheetCellRendererRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellStringRendererRefData, - wxSheetCellRendererRefData) + bool Copy(const wxSheetCellStringRendererRefData &other) + { + return wxSheetCellRendererRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellStringRendererRefData, wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- // wxSheetCellAutoWrapStringRendererRefData // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringRendererRefData : public wxSheetCellStringRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringRendererRefData + : public wxSheetCellStringRendererRefData { public: - wxSheetCellAutoWrapStringRendererRefData() : wxSheetCellStringRendererRefData() { } + wxSheetCellAutoWrapStringRendererRefData() : wxSheetCellStringRendererRefData() {} - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxSheetCoords& coords); + virtual wxSize GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords); - wxArrayString GetTextLines( wxSheet& sheet, wxDC& dc, const wxSheetCellAttr& attr, - const wxRect& rect, const wxSheetCoords& coords); + wxArrayString GetTextLines(wxSheet &sheet, wxDC &dc, const wxSheetCellAttr &attr, + const wxRect &rect, const wxSheetCoords &coords); - bool Copy(const wxSheetCellAutoWrapStringRendererRefData& other) - { return wxSheetCellStringRendererRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellAutoWrapStringRendererRefData, - wxSheetCellRendererRefData) + bool Copy(const wxSheetCellAutoWrapStringRendererRefData &other) + { + return wxSheetCellStringRendererRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellAutoWrapStringRendererRefData, + wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- @@ -171,131 +172,138 @@ class WXDLLIMPEXP_SHEET wxSheetCellAutoWrapStringRendererRefData : public wxShee // ---------------------------------------------------------------------------- // the default renderer for the cells containing numeric (long) data -class WXDLLIMPEXP_SHEET wxSheetCellNumberRendererRefData : public wxSheetCellStringRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellNumberRendererRefData + : public wxSheetCellStringRendererRefData { public: - wxSheetCellNumberRendererRefData() {} + wxSheetCellNumberRendererRefData() {} - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); + virtual wxString GetString(wxSheet &sheet, const wxSheetCoords &coords); - bool Copy(const wxSheetCellNumberRendererRefData& other) - { return wxSheetCellStringRendererRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellNumberRendererRefData, - wxSheetCellRendererRefData) + bool Copy(const wxSheetCellNumberRendererRefData &other) + { + return wxSheetCellStringRendererRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellNumberRendererRefData, wxSheetCellRendererRefData) }; // ---------------------------------------------------------------------------- // wxSheetCellFloatRendererRefData // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellFloatRendererRefData : public wxSheetCellStringRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellFloatRendererRefData : public wxSheetCellStringRendererRefData { public: - wxSheetCellFloatRendererRefData(int width = -1, int precision = -1) - : m_width(width), m_precision(precision) { } - - // get/change formatting parameters "%[width].[precision]f" - int GetWidth() const { return m_width; } - void SetWidth(int width) { m_width = width; m_format.clear(); } - int GetPrecision() const { return m_precision; } - void SetPrecision(int precision) { m_precision = precision; m_format.clear(); } - - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); - - // parameters string format is "width[,precision]" - virtual void SetParameters(const wxString& params); - - virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); - - bool Copy(const wxSheetCellFloatRendererRefData& other); - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellFloatRendererRefData, - wxSheetCellRendererRefData) + wxSheetCellFloatRendererRefData(int width = -1, int precision = -1) + : m_width(width), m_precision(precision) + { + } + + // get/change formatting parameters "%[width].[precision]f" + int GetWidth() const { return m_width; } + void SetWidth(int width) + { + m_width = width; + m_format.clear(); + } + int GetPrecision() const { return m_precision; } + void SetPrecision(int precision) + { + m_precision = precision; + m_format.clear(); + } + + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); + + // parameters string format is "width[,precision]" + virtual void SetParameters(const wxString ¶ms); + + virtual wxString GetString(wxSheet &sheet, const wxSheetCoords &coords); + + bool Copy(const wxSheetCellFloatRendererRefData &other); + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellFloatRendererRefData, wxSheetCellRendererRefData) protected: - int m_width, - m_precision; + int m_width, m_precision; - wxString m_format; + wxString m_format; }; // ---------------------------------------------------------------------------- // wxSheetCellBitmapRendererRefData // ---------------------------------------------------------------------------- -enum wxSHEET_BMPREN_Type -{ - // The position of the bitmap relative to the text (if any) - wxSHEET_BMPREN_BMPLEFT = 0x000000, - wxSHEET_BMPREN_BMPRIGHT = 0x010000, - wxSHEET_BMPREN_BMPABOVE = 0x020000, - wxSHEET_BMPREN_BMPBELOW = 0x040000 +enum wxSHEET_BMPREN_Type { + // The position of the bitmap relative to the text (if any) + wxSHEET_BMPREN_BMPLEFT = 0x000000, + wxSHEET_BMPREN_BMPRIGHT = 0x010000, + wxSHEET_BMPREN_BMPABOVE = 0x020000, + wxSHEET_BMPREN_BMPBELOW = 0x040000 }; -class WXDLLIMPEXP_SHEET wxSheetCellBitmapRendererRefData : public wxSheetCellStringRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellBitmapRendererRefData + : public wxSheetCellStringRendererRefData { public: - wxSheetCellBitmapRendererRefData(const wxBitmap& bitmap = wxNullBitmap, - int align = 0) : m_bitmap(bitmap), m_align(align) {} - - // draw a the bitmap - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); - - // return the bitmap size - virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxSheetCoords& coords); - - // Get/Set the bitmap to draw - wxBitmap GetBitmap() const { return m_bitmap; } - void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; } - // Get/Set the bitmap alignment, wxALIGN_XXX | wxSHEET_BMPREN_Type | wxGROW - // The wxSHEET_BMPREN_Type determines the relative positions of bmp and text - // The wxALIGN_XXX sets the alignment of the bitmap in it's area of the cell - // wxGROW will expand or shrink bitmap instead of clipping it - // The cell attribute's alignment sets the alignment of the text in it's area of the cell - int GetAlignment() const { return m_align; } - void SetAlignment(int align) { m_align = align; } - - bool Copy(const wxSheetCellBitmapRendererRefData& other) - { SetBitmap(other.GetBitmap()); return wxSheetCellStringRendererRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBitmapRendererRefData, - wxSheetCellRendererRefData) - - wxBitmap m_bitmap; - int m_align; + wxSheetCellBitmapRendererRefData(const wxBitmap &bitmap = wxNullBitmap, int align = 0) + : m_bitmap(bitmap), m_align(align) + { + } + + // draw a the bitmap + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); + + // return the bitmap size + virtual wxSize GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords); + + // Get/Set the bitmap to draw + wxBitmap GetBitmap() const { return m_bitmap; } + void SetBitmap(const wxBitmap &bitmap) { m_bitmap = bitmap; } + // Get/Set the bitmap alignment, wxALIGN_XXX | wxSHEET_BMPREN_Type | wxGROW + // The wxSHEET_BMPREN_Type determines the relative positions of bmp and text + // The wxALIGN_XXX sets the alignment of the bitmap in it's area of the cell + // wxGROW will expand or shrink bitmap instead of clipping it + // The cell attribute's alignment sets the alignment of the text in it's area of the cell + int GetAlignment() const { return m_align; } + void SetAlignment(int align) { m_align = align; } + + bool Copy(const wxSheetCellBitmapRendererRefData &other) + { + SetBitmap(other.GetBitmap()); + return wxSheetCellStringRendererRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBitmapRendererRefData, wxSheetCellRendererRefData) + + wxBitmap m_bitmap; + int m_align; }; // ---------------------------------------------------------------------------- // wxSheetCellBoolRendererRefData // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellBoolRendererRefData : public wxSheetCellRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellBoolRendererRefData : public wxSheetCellRendererRefData { public: - wxSheetCellBoolRendererRefData() {} + wxSheetCellBoolRendererRefData() {} - // draw a check mark or nothing - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + // draw a check mark or nothing + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - // return the checkmark size - virtual wxSize GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxSheetCoords& coords); + // return the checkmark size + virtual wxSize GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords); - bool Copy(const wxSheetCellBoolRendererRefData& other) - { return wxSheetCellRendererRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBoolRendererRefData, - wxSheetCellRendererRefData) + bool Copy(const wxSheetCellBoolRendererRefData &other) + { + return wxSheetCellRendererRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellBoolRendererRefData, wxSheetCellRendererRefData) protected: - static wxSize ms_sizeCheckMark; + static wxSize ms_sizeCheckMark; }; // ---------------------------------------------------------------------------- @@ -304,37 +312,38 @@ class WXDLLIMPEXP_SHEET wxSheetCellBoolRendererRefData : public wxSheetCellRende #if wxUSE_DATETIME // the default renderer for the cells containing Time and dates.. -class WXDLLIMPEXP_SHEET wxSheetCellDateTimeRendererRefData : public wxSheetCellStringRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellDateTimeRendererRefData + : public wxSheetCellStringRendererRefData { public: - wxSheetCellDateTimeRendererRefData(wxString outFormat = wxDefaultDateTimeFormat, //_T("%c"), - wxString inFormat = wxDefaultDateTimeFormat) - : m_outFormat(outFormat), m_inFormat(inFormat), - m_dateTime(wxDefaultDateTime), m_tz(wxDateTime::Local) {} + wxSheetCellDateTimeRendererRefData(wxString outFormat = wxDefaultDateTimeFormat, //_T("%c"), + wxString inFormat = wxDefaultDateTimeFormat) + : m_outFormat(outFormat), m_inFormat(inFormat), m_dateTime(wxDefaultDateTime), + m_tz(wxDateTime::Local) + { + } - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - // parameters string format is "width[,precision]" - virtual void SetParameters(const wxString& params); + // parameters string format is "width[,precision]" + virtual void SetParameters(const wxString ¶ms); - wxString GetInFormat() const { return m_inFormat; } - wxString GetOutFormat() const { return m_outFormat; } - void SetInFormat(const wxString& inFormat) { m_inFormat = inFormat; } - void SetOutFormat(const wxString& outFormat) { m_outFormat = outFormat; } + wxString GetInFormat() const { return m_inFormat; } + wxString GetOutFormat() const { return m_outFormat; } + void SetInFormat(const wxString &inFormat) { m_inFormat = inFormat; } + void SetOutFormat(const wxString &outFormat) { m_outFormat = outFormat; } - virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); + virtual wxString GetString(wxSheet &sheet, const wxSheetCoords &coords); - bool Copy(const wxSheetCellDateTimeRendererRefData& other); - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellDateTimeRendererRefData, - wxSheetCellRendererRefData) + bool Copy(const wxSheetCellDateTimeRendererRefData &other); + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellDateTimeRendererRefData, + wxSheetCellRendererRefData) protected: - wxString m_outFormat; - wxString m_inFormat; - wxDateTime m_dateTime; - wxDateTime::TimeZone m_tz; + wxString m_outFormat; + wxString m_inFormat; + wxDateTime m_dateTime; + wxDateTime::TimeZone m_tz; }; #endif // wxUSE_DATETIME @@ -342,26 +351,23 @@ class WXDLLIMPEXP_SHEET wxSheetCellDateTimeRendererRefData : public wxSheetCellS // ---------------------------------------------------------------------------- // wxSheetCellEnumRendererRefData - renderers Time and dates.. // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCellEnumRendererRefData : public wxSheetCellStringRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellEnumRendererRefData : public wxSheetCellStringRendererRefData { public: - wxSheetCellEnumRendererRefData( const wxString& choices = wxEmptyString ); + wxSheetCellEnumRendererRefData(const wxString &choices = wxEmptyString); - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - // parameters string format is "item1[,item2[...,itemN]]" - virtual void SetParameters(const wxString& params); + // parameters string format is "item1[,item2[...,itemN]]" + virtual void SetParameters(const wxString ¶ms); - wxArrayString& GetChoices() { return m_choices; } - virtual wxString GetString(wxSheet& sheet, const wxSheetCoords& coords); + wxArrayString &GetChoices() { return m_choices; } + virtual wxString GetString(wxSheet &sheet, const wxSheetCoords &coords); - bool Copy(const wxSheetCellEnumRendererRefData& other); - DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEnumRendererRefData, - wxSheetCellRendererRefData) + bool Copy(const wxSheetCellEnumRendererRefData &other); + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellEnumRendererRefData, wxSheetCellRendererRefData) protected: - wxArrayString m_choices; + wxArrayString m_choices; }; // ---------------------------------------------------------------------------- @@ -369,19 +375,20 @@ class WXDLLIMPEXP_SHEET wxSheetCellEnumRendererRefData : public wxSheetCellStrin // ---------------------------------------------------------------------------- // the default renderer for the cells containing string data -class WXDLLIMPEXP_SHEET wxSheetCellRolColLabelRendererRefData : public wxSheetCellStringRendererRefData -{ +class WXDLLIMPEXP_SHEET wxSheetCellRolColLabelRendererRefData + : public wxSheetCellStringRendererRefData { public: - wxSheetCellRolColLabelRendererRefData() {} + wxSheetCellRolColLabelRendererRefData() {} - virtual void Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected); + virtual void Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected); - bool Copy(const wxSheetCellRolColLabelRendererRefData& other) - { return wxSheetCellStringRendererRefData::Copy(other); } - DECLARE_SHEETOBJREFDATA_COPY_CLASS( wxSheetCellRolColLabelRendererRefData, - wxSheetCellRendererRefData) + bool Copy(const wxSheetCellRolColLabelRendererRefData &other) + { + return wxSheetCellStringRendererRefData::Copy(other); + } + DECLARE_SHEETOBJREFDATA_COPY_CLASS(wxSheetCellRolColLabelRendererRefData, + wxSheetCellRendererRefData) }; #endif //__WX_SHEETREN_H__ diff --git a/src/labenski/include/wx/sheet/sheetsel.h b/src/labenski/include/wx/sheet/sheetsel.h index 563af48dd..486896194 100644 --- a/src/labenski/include/wx/sheet/sheetsel.h +++ b/src/labenski/include/wx/sheet/sheetsel.h @@ -17,81 +17,124 @@ // ---------------------------------------------------------------------------- // wxSheetCoords: location of a cell in the grid // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetCoords -{ +class WXDLLIMPEXP_SHEET wxSheetCoords { public: - wxSheetCoords() : m_row(0), m_col(0) {} - wxSheetCoords( int row, int col ) : m_row(row), m_col(col) {} - - // default copy ctor is ok - - int GetRow() const { return m_row; } - int GetCol() const { return m_col; } - - void SetRow( int row ) { m_row = row; } - void SetCol( int col ) { m_col = col; } - void Set( int row, int col ) { m_row = row; m_col = col; } - - void ShiftRow( int row ) { m_row += row; } - void ShiftCol( int col ) { m_col += col; } - void Shift( int rows, int cols ) { m_row += rows; m_col += cols; } - void SwapRowCol() { int tmp = m_row; m_row = m_col; m_col = tmp; } - - // returns coords shifted by the # of rows and cols - wxSheetCoords GetShifted( int rows, int cols ) const { return wxSheetCoords(m_row+rows, m_col+cols); } - // return coords with row and col swapped - wxSheetCoords GetSwapped() const { return wxSheetCoords(m_col, m_row); } - - // Get the type of coords as enum for use in a switch statement - wxSheetCell_Type GetCellCoordsType() const; - - // helper functions to determine what type of cell it is, not check validity - bool IsGridCell() const { return (m_row >= 0) && (m_col >= 0); } - bool IsLabelCell() const { return (m_row >= -1) && (m_col >= -1) && - ((m_row == -1) || (m_col == -1)); } - bool IsRowLabelCell() const { return (m_row >= 0) && (m_col == -1); } - bool IsColLabelCell() const { return (m_row == -1) && (m_col >= 0); } - bool IsCornerLabelCell() const { return (m_row == -1) && (m_col == -1); } - - // Convert this sheet coords to a row/col/corner label coords - // eg. for row labels : sheetCell(-1, 5) -> rowLabelCell(0, 5) - wxSheetCoords SheetToRowLabel() const { return wxSheetCoords( m_row, -1-m_col); } - wxSheetCoords SheetToColLabel() const { return wxSheetCoords(-1-m_row, m_col); } - wxSheetCoords SheetToCornerLabel() const { return wxSheetCoords(-1-m_row, -1-m_col); } - - wxSheetCoords GetCellCoords(wxSheetCell_Type type) const; - wxSheetCoords& SetCellCoords(wxSheetCell_Type type); - - // Shift the cell if greater than row/col by numRows/numCols. - // if this row/col is < the update row/col do nothing, return false - // if this row/col is >= the update row/col + labs(num) then shift by num - // if this row/col is >= the update row/col && < row/col + labs(num) - // if num > 0 then shift it - // if num < 0 it should be deleted, but shift it to row/col - 1 - bool UpdateRows( size_t row, int numRows ); - bool UpdateCols( size_t col, int numCols ); - - // operators - wxSheetCoords& operator=(const wxSheetCoords& other) { m_row = other.m_row; m_col = other.m_col; return *this; } - - // arithmetic operations (component wise) - wxSheetCoords operator+(const wxSheetCoords& c) const { return wxSheetCoords(m_row + c.m_row, m_col + c.m_col); } - wxSheetCoords operator-(const wxSheetCoords& c) const { return wxSheetCoords(m_row - c.m_row, m_col - c.m_col); } - - wxSheetCoords& operator+=(const wxSheetCoords& c) { m_row += c.m_row; m_col += c.m_col; return *this; } - wxSheetCoords& operator-=(const wxSheetCoords& c) { m_row -= c.m_row; m_col -= c.m_col; return *this; } - - bool operator == (const wxSheetCoords& other) const { return (m_row == other.m_row) && (m_col == other.m_col); } - bool operator != (const wxSheetCoords& other) const { return !(*this == other); } - // > and < operators use row for first comparison then col - bool operator < (const wxSheetCoords& other) const - { return (m_row < other.m_row) || ((m_row == other.m_row) && (m_col < other.m_col)); } - bool operator <= (const wxSheetCoords& other) const { return (*this < other) || (*this == other); } - bool operator > (const wxSheetCoords& other) const { return !(*this <= other); } - bool operator >= (const wxSheetCoords& other) const { return !(*this < other); } - - int m_row; - int m_col; + wxSheetCoords() : m_row(0), m_col(0) {} + wxSheetCoords(int row, int col) : m_row(row), m_col(col) {} + + // default copy ctor is ok + + int GetRow() const { return m_row; } + int GetCol() const { return m_col; } + + void SetRow(int row) { m_row = row; } + void SetCol(int col) { m_col = col; } + void Set(int row, int col) + { + m_row = row; + m_col = col; + } + + void ShiftRow(int row) { m_row += row; } + void ShiftCol(int col) { m_col += col; } + void Shift(int rows, int cols) + { + m_row += rows; + m_col += cols; + } + void SwapRowCol() + { + int tmp = m_row; + m_row = m_col; + m_col = tmp; + } + + // returns coords shifted by the # of rows and cols + wxSheetCoords GetShifted(int rows, int cols) const + { + return wxSheetCoords(m_row + rows, m_col + cols); + } + // return coords with row and col swapped + wxSheetCoords GetSwapped() const { return wxSheetCoords(m_col, m_row); } + + // Get the type of coords as enum for use in a switch statement + wxSheetCell_Type GetCellCoordsType() const; + + // helper functions to determine what type of cell it is, not check validity + bool IsGridCell() const { return (m_row >= 0) && (m_col >= 0); } + bool IsLabelCell() const + { + return (m_row >= -1) && (m_col >= -1) && ((m_row == -1) || (m_col == -1)); + } + bool IsRowLabelCell() const { return (m_row >= 0) && (m_col == -1); } + bool IsColLabelCell() const { return (m_row == -1) && (m_col >= 0); } + bool IsCornerLabelCell() const { return (m_row == -1) && (m_col == -1); } + + // Convert this sheet coords to a row/col/corner label coords + // eg. for row labels : sheetCell(-1, 5) -> rowLabelCell(0, 5) + wxSheetCoords SheetToRowLabel() const { return wxSheetCoords(m_row, -1 - m_col); } + wxSheetCoords SheetToColLabel() const { return wxSheetCoords(-1 - m_row, m_col); } + wxSheetCoords SheetToCornerLabel() const { return wxSheetCoords(-1 - m_row, -1 - m_col); } + + wxSheetCoords GetCellCoords(wxSheetCell_Type type) const; + wxSheetCoords &SetCellCoords(wxSheetCell_Type type); + + // Shift the cell if greater than row/col by numRows/numCols. + // if this row/col is < the update row/col do nothing, return false + // if this row/col is >= the update row/col + labs(num) then shift by num + // if this row/col is >= the update row/col && < row/col + labs(num) + // if num > 0 then shift it + // if num < 0 it should be deleted, but shift it to row/col - 1 + bool UpdateRows(size_t row, int numRows); + bool UpdateCols(size_t col, int numCols); + + // operators + wxSheetCoords &operator=(const wxSheetCoords &other) + { + m_row = other.m_row; + m_col = other.m_col; + return *this; + } + + // arithmetic operations (component wise) + wxSheetCoords operator+(const wxSheetCoords &c) const + { + return wxSheetCoords(m_row + c.m_row, m_col + c.m_col); + } + wxSheetCoords operator-(const wxSheetCoords &c) const + { + return wxSheetCoords(m_row - c.m_row, m_col - c.m_col); + } + + wxSheetCoords &operator+=(const wxSheetCoords &c) + { + m_row += c.m_row; + m_col += c.m_col; + return *this; + } + wxSheetCoords &operator-=(const wxSheetCoords &c) + { + m_row -= c.m_row; + m_col -= c.m_col; + return *this; + } + + bool operator==(const wxSheetCoords &other) const + { + return (m_row == other.m_row) && (m_col == other.m_col); + } + bool operator!=(const wxSheetCoords &other) const { return !(*this == other); } + // > and < operators use row for first comparison then col + bool operator<(const wxSheetCoords &other) const + { + return (m_row < other.m_row) || ((m_row == other.m_row) && (m_col < other.m_col)); + } + bool operator<=(const wxSheetCoords &other) const { return (*this < other) || (*this == other); } + bool operator>(const wxSheetCoords &other) const { return !(*this <= other); } + bool operator>=(const wxSheetCoords &other) const { return !(*this < other); } + + int m_row; + int m_col; }; // wxArraySheetCoords - a wxObjectArray of wxSheetCoords @@ -100,182 +143,259 @@ WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetCoords, wxArraySheetCoords, class WXDLLIMPE // ---------------------------------------------------------------------------- // wxSheetBlock: a rectangular block of cells // ---------------------------------------------------------------------------- -enum wxSheetBlockExtra_Type -{ - wxSHEET_BLOCK_NONE = 0, - wxSHEET_BLOCK_TOP = 0x0001, - wxSHEET_BLOCK_BOTTOM = 0x0002, - wxSHEET_BLOCK_LEFT = 0x0004, - wxSHEET_BLOCK_RIGHT = 0x0008, - wxSHEET_BLOCK_ALL = 0x0010 +enum wxSheetBlockExtra_Type { + wxSHEET_BLOCK_NONE = 0, + wxSHEET_BLOCK_TOP = 0x0001, + wxSHEET_BLOCK_BOTTOM = 0x0002, + wxSHEET_BLOCK_LEFT = 0x0004, + wxSHEET_BLOCK_RIGHT = 0x0008, + wxSHEET_BLOCK_ALL = 0x0010 }; -class WXDLLIMPEXP_SHEET wxSheetBlock -{ +class WXDLLIMPEXP_SHEET wxSheetBlock { public: - wxSheetBlock() : m_row(0), m_col(0), m_height(0), m_width(0) {} - wxSheetBlock(int row, int col, int height, int width) - : m_row(row), m_col(col), m_height(height), m_width(width) {} - // make a block from two corner coords, block will be upright - wxSheetBlock( const wxSheetCoords& coords1, - const wxSheetCoords& coords2, bool make_upright = true ); - wxSheetBlock( const wxSheetCoords& tl, int height, int width ) - : m_row(tl.m_row), m_col(tl.m_col), m_height(height), m_width(width) {} - - // Get the coord values of the block - int GetLeft() const { return m_col; } - int GetRight() const { return m_col + m_width - 1; } - int GetTop() const { return m_row; } - int GetBottom() const { return m_row + m_height - 1; } - int GetWidth() const { return m_width; } - int GetHeight() const { return m_height; } - - wxSheetCoords GetLeftTop() const { return wxSheetCoords(m_row, m_col); } - wxSheetCoords GetLeftBottom() const { return wxSheetCoords(GetBottom(), m_col); } - wxSheetCoords GetRightTop() const { return wxSheetCoords(m_row, GetRight()); } - wxSheetCoords GetRightBottom() const { return wxSheetCoords(GetBottom(), GetRight()); } - - wxSheetCoords GetSize() const { return wxSheetCoords(m_height, m_width); } - - // get an array of coords going left to right, top to bottom - wxArraySheetCoords GetArrayCoords() const; - - // Set the coord values of the block - - // set the edges, the rest of the block stays in the same place - void SetLeft( int left ) { m_width += m_col - left; m_col = left; } - void SetTop( int top ) { m_height += m_row - top; m_row = top; } - void SetRight( int right ) { m_width = right - m_col + 1; } - void SetBottom( int bottom ) { m_height = bottom - m_row + 1; } - void SetWidth( int width ) { m_width = width; } - void SetHeight( int height ) { m_height = height; } - - void SetLeftTop(const wxSheetCoords& lt) { SetTop(lt.m_row); SetLeft(lt.m_col); } - void SetLeftBottom(const wxSheetCoords& lb) { SetBottom(lb.m_row); SetLeft(lb.m_col); } - void SetRightTop(const wxSheetCoords& rt) { SetTop(rt.m_row); SetRight(rt.m_col); } - void SetRightBottom(const wxSheetCoords& rb) { SetBottom(rb.m_row); SetRight(rb.m_col); } - - // Set the coords keeping the rest of the block the same - void SetLeftCoord( int left ) { m_col = left; } - void SetTopCoord( int top ) { m_row = top; } - void SetRightCoord( int right ) { m_col = right - m_width + 1; } - void SetBottomCoord( int bottom ) { m_row = bottom - m_height + 1; } - - void SetLeftTopCoords(const wxSheetCoords& lt) { SetTopCoord(lt.m_row); SetLeftCoord(lt.m_col); } - void SetLeftBottomCoords(const wxSheetCoords& lb) { SetBottomCoord(lb.m_row); SetLeftCoord(lb.m_col); } - void SetRightTopCoords(const wxSheetCoords& rt) { SetTopCoord(rt.m_row); SetRightCoord(rt.m_col); } - void SetRightBottomCoords(const wxSheetCoords& rb) { SetBottomCoord(rb.m_row); SetRightCoord(rb.m_col); } - - void Set( int row, int col, int height, int width ) - { m_row = row; m_col = col; m_height = height; m_width = width; } - void SetCoords( int top, int left, int bottom, int right ) - { m_row=top; m_col=left; m_height=bottom-top+1; m_width=right-left+1; } - void SetSize(const wxSheetCoords& size) { m_height = size.m_row; m_width = size.m_col; } - - // Get a block of this that is upright - wxSheetBlock GetAligned() const; - - bool IsEmpty() const { return (m_width < 1) || (m_height < 1); } - bool IsOneCell() const { return (m_width == 1) && (m_height == 1); } - - bool Contains( int row, int col ) const - { return (row >= m_row) && (col >= m_col) && - (row <= GetBottom()) && (col <= GetRight()); } - bool Contains( const wxSheetCoords &coord ) const { return Contains(coord.m_row, coord.m_col); } - bool Contains( const wxSheetBlock &b ) const - { return !IsEmpty() && !b.IsEmpty() && - (m_row <= b.m_row) && (m_col <= b.m_col) && - (b.GetBottom() <= GetBottom()) && (b.GetRight() <= GetRight()); } - - // do these two blocks intersect (overlap) each other - bool Intersects( const wxSheetBlock &b ) const - { return !Intersect(b).IsEmpty(); } - //!IsEmpty() && !b.IsEmpty() && - //(wxMax(m_col, b.m_col) <= wxMin(GetRight(), b.GetRight())) && - //(wxMax(m_row, b.m_row) <= wxMin(GetBottom(), b.GetBottom())); } - // returns a block that is an intersection of these two blocks - wxSheetBlock Intersect( const wxSheetBlock &other ) const; - - // union these two blocks - wxSheetBlock Union( const wxSheetBlock &other ) const; - - // expands the union of the two, if one block is empty, return other - wxSheetBlock ExpandUnion( const wxSheetBlock &other ) const; - - // Unlike Intersects this also includes just touching the other block - bool Touches(const wxSheetBlock &block) const - { return !IsEmpty() && !block.IsEmpty() && - block.Intersects(wxSheetBlock(m_row-1, m_col-1, m_height+2, m_width+2)); } - - // returns a mix of enum wxSheetBlockExtra_Type of what sides of the two - // blocks are matched - int SideMatches(const wxSheetBlock& block) const - { - return (m_row == block.m_row ? wxSHEET_BLOCK_TOP : 0) | - (m_col == block.m_col ? wxSHEET_BLOCK_LEFT : 0) | - (GetBottom() == block.GetBottom() ? wxSHEET_BLOCK_BOTTOM : 0) | - (GetRight() == block.GetRight() ? wxSHEET_BLOCK_RIGHT : 0); + wxSheetBlock() : m_row(0), m_col(0), m_height(0), m_width(0) {} + wxSheetBlock(int row, int col, int height, int width) + : m_row(row), m_col(col), m_height(height), m_width(width) + { + } + // make a block from two corner coords, block will be upright + wxSheetBlock(const wxSheetCoords &coords1, const wxSheetCoords &coords2, + bool make_upright = true); + wxSheetBlock(const wxSheetCoords &tl, int height, int width) + : m_row(tl.m_row), m_col(tl.m_col), m_height(height), m_width(width) + { + } + + // Get the coord values of the block + int GetLeft() const { return m_col; } + int GetRight() const { return m_col + m_width - 1; } + int GetTop() const { return m_row; } + int GetBottom() const { return m_row + m_height - 1; } + int GetWidth() const { return m_width; } + int GetHeight() const { return m_height; } + + wxSheetCoords GetLeftTop() const { return wxSheetCoords(m_row, m_col); } + wxSheetCoords GetLeftBottom() const { return wxSheetCoords(GetBottom(), m_col); } + wxSheetCoords GetRightTop() const { return wxSheetCoords(m_row, GetRight()); } + wxSheetCoords GetRightBottom() const { return wxSheetCoords(GetBottom(), GetRight()); } + + wxSheetCoords GetSize() const { return wxSheetCoords(m_height, m_width); } + + // get an array of coords going left to right, top to bottom + wxArraySheetCoords GetArrayCoords() const; + + // Set the coord values of the block + + // set the edges, the rest of the block stays in the same place + void SetLeft(int left) + { + m_width += m_col - left; + m_col = left; + } + void SetTop(int top) + { + m_height += m_row - top; + m_row = top; + } + void SetRight(int right) { m_width = right - m_col + 1; } + void SetBottom(int bottom) { m_height = bottom - m_row + 1; } + void SetWidth(int width) { m_width = width; } + void SetHeight(int height) { m_height = height; } + + void SetLeftTop(const wxSheetCoords <) + { + SetTop(lt.m_row); + SetLeft(lt.m_col); + } + void SetLeftBottom(const wxSheetCoords &lb) + { + SetBottom(lb.m_row); + SetLeft(lb.m_col); + } + void SetRightTop(const wxSheetCoords &rt) + { + SetTop(rt.m_row); + SetRight(rt.m_col); + } + void SetRightBottom(const wxSheetCoords &rb) + { + SetBottom(rb.m_row); + SetRight(rb.m_col); + } + + // Set the coords keeping the rest of the block the same + void SetLeftCoord(int left) { m_col = left; } + void SetTopCoord(int top) { m_row = top; } + void SetRightCoord(int right) { m_col = right - m_width + 1; } + void SetBottomCoord(int bottom) { m_row = bottom - m_height + 1; } + + void SetLeftTopCoords(const wxSheetCoords <) + { + SetTopCoord(lt.m_row); + SetLeftCoord(lt.m_col); + } + void SetLeftBottomCoords(const wxSheetCoords &lb) + { + SetBottomCoord(lb.m_row); + SetLeftCoord(lb.m_col); + } + void SetRightTopCoords(const wxSheetCoords &rt) + { + SetTopCoord(rt.m_row); + SetRightCoord(rt.m_col); + } + void SetRightBottomCoords(const wxSheetCoords &rb) + { + SetBottomCoord(rb.m_row); + SetRightCoord(rb.m_col); + } + + void Set(int row, int col, int height, int width) + { + m_row = row; + m_col = col; + m_height = height; + m_width = width; + } + void SetCoords(int top, int left, int bottom, int right) + { + m_row = top; + m_col = left; + m_height = bottom - top + 1; + m_width = right - left + 1; + } + void SetSize(const wxSheetCoords &size) + { + m_height = size.m_row; + m_width = size.m_col; + } + + // Get a block of this that is upright + wxSheetBlock GetAligned() const; + + bool IsEmpty() const { return (m_width < 1) || (m_height < 1); } + bool IsOneCell() const { return (m_width == 1) && (m_height == 1); } + + bool Contains(int row, int col) const + { + return (row >= m_row) && (col >= m_col) && (row <= GetBottom()) && (col <= GetRight()); + } + bool Contains(const wxSheetCoords &coord) const { return Contains(coord.m_row, coord.m_col); } + bool Contains(const wxSheetBlock &b) const + { + return !IsEmpty() && !b.IsEmpty() && (m_row <= b.m_row) && (m_col <= b.m_col) && + (b.GetBottom() <= GetBottom()) && (b.GetRight() <= GetRight()); + } + + // do these two blocks intersect (overlap) each other + bool Intersects(const wxSheetBlock &b) const { return !Intersect(b).IsEmpty(); } + //! IsEmpty() && !b.IsEmpty() && + //(wxMax(m_col, b.m_col) <= wxMin(GetRight(), b.GetRight())) && + //(wxMax(m_row, b.m_row) <= wxMin(GetBottom(), b.GetBottom())); } + // returns a block that is an intersection of these two blocks + wxSheetBlock Intersect(const wxSheetBlock &other) const; + + // union these two blocks + wxSheetBlock Union(const wxSheetBlock &other) const; + + // expands the union of the two, if one block is empty, return other + wxSheetBlock ExpandUnion(const wxSheetBlock &other) const; + + // Unlike Intersects this also includes just touching the other block + bool Touches(const wxSheetBlock &block) const + { + return !IsEmpty() && !block.IsEmpty() && + block.Intersects(wxSheetBlock(m_row - 1, m_col - 1, m_height + 2, m_width + 2)); + } + + // returns a mix of enum wxSheetBlockExtra_Type of what sides of the two + // blocks are matched + int SideMatches(const wxSheetBlock &block) const + { + return (m_row == block.m_row ? wxSHEET_BLOCK_TOP : 0) | + (m_col == block.m_col ? wxSHEET_BLOCK_LEFT : 0) | + (GetBottom() == block.GetBottom() ? wxSHEET_BLOCK_BOTTOM : 0) | + (GetRight() == block.GetRight() ? wxSHEET_BLOCK_RIGHT : 0); + } + + // Try to combine these blocks, they must touch and fit to make a single larger block + // this block is expanded if possible, returns success + bool Combine(const wxSheetBlock &block); + + // test combining the input block with this one, returning the + // remainder of block in top, bottom, left, right - each may be IsEmpty() + // returns enum wxSheetBlockExtra_Type Or'ed together specifying which + // blocks have been filled or all of the block may be combined + // returns false if blocks don't touch or this block already contains block + // |---------------------------| + // | top | + // |---------------------------| + // | left |block| right | + // |---------------------------| + // | bottom | + // |---------------------------| + + int Combine(const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, + wxSheetBlock &left, wxSheetBlock &right) const; + + // test removal of a portion or all of this contained in block returning the + // remainder of this in top, bottom, left, right - each may be IsEmpty() + // returns false if nothing to delete, this cell is not changed + int Delete(const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, + wxSheetBlock &left, wxSheetBlock &right) const; + + // shift the block if greater than row/col by numRows/numCols or empty it + // if it's inside the deletion + bool UpdateRows(size_t row, int numRows); + bool UpdateCols(size_t col, int numCols); + + // operators + bool operator==(const wxSheetBlock &b) const + { + return (m_row == b.m_row) && (m_height == b.m_height) && (m_col == b.m_col) && + (m_width == b.m_width); + } + bool operator!=(const wxSheetBlock &b) const { return !(*this == b); } + + // returns -1 if this block is more to the top left, 0 is equal, 1 if lower and to right + int CmpTopLeft(const wxSheetBlock &b) const; + // returns -1 if this block is more to the right then bottom, 0 is equal, 1 if to the left and + // higher + int CmpRightBottom(const wxSheetBlock &b) const; + + // goes top left to bottom right and then by height and width (allows sorting) + bool operator<(const wxSheetBlock &b) const + { + if (m_row < b.m_row) { + return true; } - - // Try to combine these blocks, they must touch and fit to make a single larger block - // this block is expanded if possible, returns success - bool Combine(const wxSheetBlock &block); - - // test combining the input block with this one, returning the - // remainder of block in top, bottom, left, right - each may be IsEmpty() - // returns enum wxSheetBlockExtra_Type Or'ed together specifying which - // blocks have been filled or all of the block may be combined - // returns false if blocks don't touch or this block already contains block - // |---------------------------| - // | top | - // |---------------------------| - // | left |block| right | - // |---------------------------| - // | bottom | - // |---------------------------| - - int Combine( const wxSheetBlock &block, - wxSheetBlock &top, wxSheetBlock &bottom, - wxSheetBlock &left, wxSheetBlock &right ) const; - - // test removal of a portion or all of this contained in block returning the - // remainder of this in top, bottom, left, right - each may be IsEmpty() - // returns false if nothing to delete, this cell is not changed - int Delete( const wxSheetBlock &block, - wxSheetBlock &top, wxSheetBlock &bottom, - wxSheetBlock &left, wxSheetBlock &right ) const; - - // shift the block if greater than row/col by numRows/numCols or empty it - // if it's inside the deletion - bool UpdateRows( size_t row, int numRows ); - bool UpdateCols( size_t col, int numCols ); - - // operators - bool operator == (const wxSheetBlock& b) const - { return (m_row == b.m_row) && (m_height == b.m_height) && - (m_col == b.m_col) && (m_width == b.m_width); } - bool operator != (const wxSheetBlock& b) const { return !(*this == b); } - - // returns -1 if this block is more to the top left, 0 is equal, 1 if lower and to right - int CmpTopLeft(const wxSheetBlock& b) const; - // returns -1 if this block is more to the right then bottom, 0 is equal, 1 if to the left and higher - int CmpRightBottom(const wxSheetBlock& b) const; - - // goes top left to bottom right and then by height and width (allows sorting) - bool operator < (const wxSheetBlock& b) const - { - if (m_row < b.m_row) return true; else if (m_row > b.m_row) return false; - if (m_col < b.m_col) return true; else if (m_col > b.m_col) return false; - if (m_height < b.m_height) return true; else if (m_height > b.m_height) return false; - if (m_width < b.m_width) return true; //else if (m_width > b.m_width) return false; - return false; + else if (m_row > b.m_row) { + return false; + } + if (m_col < b.m_col) { + return true; + } + else if (m_col > b.m_col) { + return false; + } + if (m_height < b.m_height) { + return true; + } + else if (m_height > b.m_height) { + return false; } - bool operator <= (const wxSheetBlock& other) const { return (*this == other) || (*this < other); } - bool operator > (const wxSheetBlock& other) const { return !(*this <= other); } - bool operator >= (const wxSheetBlock& other) const { return !(*this < other); } + if (m_width < b.m_width) { + return true; // else if (m_width > b.m_width) return false; + } + return false; + } + bool operator<=(const wxSheetBlock &other) const { return (*this == other) || (*this < other); } + bool operator>(const wxSheetBlock &other) const { return !(*this <= other); } + bool operator>=(const wxSheetBlock &other) const { return !(*this < other); } protected: - int m_row, m_col, m_height, m_width; + int m_row, m_col, m_height, m_width; }; // For comparisons... @@ -285,7 +405,7 @@ WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxRowLabelSheetCoords; // WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxColLabelSheetCoords; // (-1, 0) WXDLLIMPEXP_DATA_SHEET(extern const wxSheetCoords) wxCornerLabelSheetCoords; // (-1, -1) -WXDLLIMPEXP_DATA_SHEET(extern const wxSheetBlock) wxNullSheetBlock; // (0, 0, 0, 0) +WXDLLIMPEXP_DATA_SHEET(extern const wxSheetBlock) wxNullSheetBlock; // (0, 0, 0, 0) // wxArraySheetBlock - a wxObjectArray of wxSheetBlocks WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetBlock, wxArraySheetBlock, class WXDLLIMPEXP_SHEET); @@ -294,156 +414,168 @@ WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetBlock, wxArraySheetBlock, class WXDLLIMPEXP // wxSheetSelection // ---------------------------------------------------------------------------- -enum wxSheetSelection_Type -{ - wxSHEET_SELECTION_NONE = 0, - // allow multiple selections to occur, this will cause the - // wxSheetSelection::Index to return the first occurance of possible many - wxSHEET_SELECTION_MULTIPLE_SEL = 0x0001 +enum wxSheetSelection_Type { + wxSHEET_SELECTION_NONE = 0, + // allow multiple selections to occur, this will cause the + // wxSheetSelection::Index to return the first occurance of possible many + wxSHEET_SELECTION_MULTIPLE_SEL = 0x0001 }; -class WXDLLIMPEXP_SHEET wxSheetSelection -{ +class WXDLLIMPEXP_SHEET wxSheetSelection { public: - wxSheetSelection( int options = wxSHEET_SELECTION_NONE ); - wxSheetSelection( const wxSheetSelection& other ) { Copy( other ); } - wxSheetSelection( const wxSheetBlock& block, - int options = wxSHEET_SELECTION_NONE ); - - // Make a full copy of the source - void Copy(const wxSheetSelection &source); - - int GetOptions() const { return m_options; } - void SetOptions(int options) { m_options = options; } - - bool HasSelection() const { return GetCount() != 0; } - int GetCount() const { return m_blocks.GetCount(); } - bool IsMinimzed() const { return m_minimized; } - - bool Clear() { if (GetCount() != 0) { m_blocks.Clear(); return true; } return false; } - bool Empty() { if (GetCount() != 0) { m_blocks.Empty(); return true; } return false; } - - const wxArraySheetBlock& GetBlockArray() const { return m_blocks; } - - const wxSheetBlock& GetBlock( size_t index ) const; - const wxSheetBlock& Item( size_t index ) const { return GetBlock(index); } - - // Get a block that bounds the selection - const wxSheetBlock& GetBoundingBlock() const { return m_bounds; } - // Set the outer bounds of the selection, trimming it down as necessary - void SetBoundingBlock(const wxSheetBlock& block); - - // do any of the blocks contain the elements - bool Contains( int row, int col ) const { return Index(row,col) != wxNOT_FOUND; } - bool Contains( const wxSheetCoords &c ) const { return Contains(c.GetRow(), c.GetCol()); } - bool Contains( const wxSheetBlock &b ) const; - - // Get the index of a block that fully contains element or wxNOT_FOUND - int Index( int row, int col ) const; - int Index( const wxSheetCoords &c ) const { return Index(c.GetRow(), c.GetCol()); } - int Index( const wxSheetBlock &b ) const; - // Get the first index of the block that intersects input block or wxNOT_FOUND - int IndexIntersects( const wxSheetBlock &b ) const; - - // Add the block to the selection, returns false if nothing was done - // use combineNow=false to make quick additions, when done call Minimize() - // addedBlocks (if !NULL) will be filled with the actual changed selections - // by removing the previous selections from the input block - bool SelectBlock( const wxSheetBlock &block, bool combineNow = true, - wxArraySheetBlock *addedBlocks = NULL ); - - // Remove the block to the selection, return false if nothing was done - // use combineNow=false to make quick additions, when done call Minimize() - // deletedBlocks (if !NULL) contains the input block, FIXME - // [it should contain only the parts of the input block that were - // deleted in the selection, but the speed would greatly suffer, - // unlike SelectBlock which uses an array in the selection process] - bool DeselectBlock( const wxSheetBlock &block, bool combineNow = true, - wxArraySheetBlock *deletedBlocks = NULL ); - - // Update the number of rows/cols. In numRows/Cols > 0 insert them else - // remove them. - bool UpdateRows( size_t row, int numRows ); - bool UpdateCols( size_t col, int numCols ); - - // Operators - inline wxSheetBlock operator[](size_t index) const { return GetBlock(index); } - wxSheetSelection& operator = (const wxSheetSelection& other) { Copy(other); return *this; } - - // implementation - - // Find where to insert this block - int FindInsertIndex(const wxSheetBlock& block) const; - // Find the index in the array that starts at this row - int FindTopRow(int row) const; - - // Combine the blocks if possible and Sort() them, returns if any were combined - // only need to call this if you've called (De)SelectBlock(block, false) - bool Minimize(); - - // Calls DoDoMinimize on array until it returns false - bool DoMinimize( wxArraySheetBlock &blocks ) const; - // DoMinimize calls this internally so that it doesn't recurse - // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array - bool DoDoMinimize( wxArraySheetBlock &blocks ) const; + wxSheetSelection(int options = wxSHEET_SELECTION_NONE); + wxSheetSelection(const wxSheetSelection &other) { Copy(other); } + wxSheetSelection(const wxSheetBlock &block, int options = wxSHEET_SELECTION_NONE); + + // Make a full copy of the source + void Copy(const wxSheetSelection &source); + + int GetOptions() const { return m_options; } + void SetOptions(int options) { m_options = options; } + + bool HasSelection() const { return GetCount() != 0; } + int GetCount() const { return m_blocks.GetCount(); } + bool IsMinimzed() const { return m_minimized; } + + bool Clear() + { + if (GetCount() != 0) { + m_blocks.Clear(); + return true; + } + return false; + } + bool Empty() + { + if (GetCount() != 0) { + m_blocks.Empty(); + return true; + } + return false; + } + + const wxArraySheetBlock &GetBlockArray() const { return m_blocks; } + + const wxSheetBlock &GetBlock(size_t index) const; + const wxSheetBlock &Item(size_t index) const { return GetBlock(index); } + + // Get a block that bounds the selection + const wxSheetBlock &GetBoundingBlock() const { return m_bounds; } + // Set the outer bounds of the selection, trimming it down as necessary + void SetBoundingBlock(const wxSheetBlock &block); + + // do any of the blocks contain the elements + bool Contains(int row, int col) const { return Index(row, col) != wxNOT_FOUND; } + bool Contains(const wxSheetCoords &c) const { return Contains(c.GetRow(), c.GetCol()); } + bool Contains(const wxSheetBlock &b) const; + + // Get the index of a block that fully contains element or wxNOT_FOUND + int Index(int row, int col) const; + int Index(const wxSheetCoords &c) const { return Index(c.GetRow(), c.GetCol()); } + int Index(const wxSheetBlock &b) const; + // Get the first index of the block that intersects input block or wxNOT_FOUND + int IndexIntersects(const wxSheetBlock &b) const; + + // Add the block to the selection, returns false if nothing was done + // use combineNow=false to make quick additions, when done call Minimize() + // addedBlocks (if !NULL) will be filled with the actual changed selections + // by removing the previous selections from the input block + bool SelectBlock(const wxSheetBlock &block, bool combineNow = true, + wxArraySheetBlock *addedBlocks = NULL); + + // Remove the block to the selection, return false if nothing was done + // use combineNow=false to make quick additions, when done call Minimize() + // deletedBlocks (if !NULL) contains the input block, FIXME + // [it should contain only the parts of the input block that were + // deleted in the selection, but the speed would greatly suffer, + // unlike SelectBlock which uses an array in the selection process] + bool DeselectBlock(const wxSheetBlock &block, bool combineNow = true, + wxArraySheetBlock *deletedBlocks = NULL); + + // Update the number of rows/cols. In numRows/Cols > 0 insert them else + // remove them. + bool UpdateRows(size_t row, int numRows); + bool UpdateCols(size_t col, int numCols); + + // Operators + inline wxSheetBlock operator[](size_t index) const { return GetBlock(index); } + wxSheetSelection &operator=(const wxSheetSelection &other) + { + Copy(other); + return *this; + } + + // implementation + + // Find where to insert this block + int FindInsertIndex(const wxSheetBlock &block) const; + // Find the index in the array that starts at this row + int FindTopRow(int row) const; + + // Combine the blocks if possible and Sort() them, returns if any were combined + // only need to call this if you've called (De)SelectBlock(block, false) + bool Minimize(); + + // Calls DoDoMinimize on array until it returns false + bool DoMinimize(wxArraySheetBlock &blocks) const; + // DoMinimize calls this internally so that it doesn't recurse + // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array + bool DoDoMinimize(wxArraySheetBlock &blocks) const; protected: - int InsertBlock(const wxSheetBlock& block); - void CalculateBounds(); + int InsertBlock(const wxSheetBlock &block); + void CalculateBounds(); - wxArraySheetBlock m_blocks; - wxSheetBlock m_bounds; - bool m_minimized; - int m_options; + wxArraySheetBlock m_blocks; + wxSheetBlock m_bounds; + bool m_minimized; + int m_options; }; // ---------------------------------------------------------------------------- // wxSheetSelectionIterator - iterates through a wxSheetSelection cell by cell // ---------------------------------------------------------------------------- -enum wxSheetSelectionIter_Type -{ - wxSSI_FORWARD, // iterate left to right by cols and then down by rows - wxSSI_REVERSE // iterate bottom to top by rows and then left by cols +enum wxSheetSelectionIter_Type { + wxSSI_FORWARD, // iterate left to right by cols and then down by rows + wxSSI_REVERSE // iterate bottom to top by rows and then left by cols }; -enum wxSheetSelectionIterGet_Type -{ - wxSHEET_SELECTIONITER_GET_END = 0, - wxSHEET_SELECTIONITER_GET_LEFTTOP = 0x0001, - wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM = 0x0002, - wxSHEET_SELECTIONITER_GET_NEXTROW = 0x0004, - wxSHEET_SELECTIONITER_GET_NEXTCOL = 0x0008 +enum wxSheetSelectionIterGet_Type { + wxSHEET_SELECTIONITER_GET_END = 0, + wxSHEET_SELECTIONITER_GET_LEFTTOP = 0x0001, + wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM = 0x0002, + wxSHEET_SELECTIONITER_GET_NEXTROW = 0x0004, + wxSHEET_SELECTIONITER_GET_NEXTCOL = 0x0008 }; -class WXDLLIMPEXP_SHEET wxSheetSelectionIterator -{ -public : - wxSheetSelectionIterator( const wxSheetSelection &sel, - wxSheetSelectionIter_Type type = wxSSI_FORWARD ); - wxSheetSelectionIterator( const wxArraySheetBlock &blocks, - wxSheetSelectionIter_Type type = wxSSI_FORWARD ); - - // resets the iterating to start at the beginning - void Reset(wxSheetSelectionIter_Type type); - // What direction are we iterating in - wxSheetSelectionIter_Type GetIterType() const { return (wxSheetSelectionIter_Type)m_type; } - - // Get next cell in the selection, returns wxSheetSelectionIterGet_Type, 0 at end - wxSheetSelectionIterGet_Type GetNext(wxSheetCoords &coords); - - // checks if this row and col are in this selection - bool IsInSelection(const wxSheetCoords &c) const { return IsInSelection(c.m_row, c.m_col); } - bool IsInSelection( int row, int col ) const; - -protected : - wxSheetSelectionIterGet_Type GetNextForward(wxSheetCoords &coords); - wxSheetSelectionIterGet_Type GetNextReverse(wxSheetCoords &coords); - - int m_block_index; - int m_type; - wxSheetCoords m_coords; - wxArraySheetBlock m_blocks; +class WXDLLIMPEXP_SHEET wxSheetSelectionIterator { +public: + wxSheetSelectionIterator(const wxSheetSelection &sel, + wxSheetSelectionIter_Type type = wxSSI_FORWARD); + wxSheetSelectionIterator(const wxArraySheetBlock &blocks, + wxSheetSelectionIter_Type type = wxSSI_FORWARD); + + // resets the iterating to start at the beginning + void Reset(wxSheetSelectionIter_Type type); + // What direction are we iterating in + wxSheetSelectionIter_Type GetIterType() const { return (wxSheetSelectionIter_Type)m_type; } + + // Get next cell in the selection, returns wxSheetSelectionIterGet_Type, 0 at end + wxSheetSelectionIterGet_Type GetNext(wxSheetCoords &coords); + + // checks if this row and col are in this selection + bool IsInSelection(const wxSheetCoords &c) const { return IsInSelection(c.m_row, c.m_col); } + bool IsInSelection(int row, int col) const; + +protected: + wxSheetSelectionIterGet_Type GetNextForward(wxSheetCoords &coords); + wxSheetSelectionIterGet_Type GetNextReverse(wxSheetCoords &coords); + + int m_block_index; + int m_type; + wxSheetCoords m_coords; + wxArraySheetBlock m_blocks; }; -#endif // __WXSHEETSEL_H__ +#endif // __WXSHEETSEL_H__ diff --git a/src/labenski/include/wx/sheet/sheetspt.h b/src/labenski/include/wx/sheet/sheetspt.h index bf4a979e6..a58e7feeb 100644 --- a/src/labenski/include/wx/sheet/sheetspt.h +++ b/src/labenski/include/wx/sheet/sheetspt.h @@ -38,221 +38,245 @@ // 3) In your subclassed wxSheet override the virtual wxSheet* wxSheet::Clone // function to return a new instance of your wxSheet. // ---------------------------------------------------------------------------- -enum wxSheetSplitMode_Type -{ - wxSHEET_SPLIT_NONE = 0, - wxSHEET_SPLIT_VERTICAL, - wxSHEET_SPLIT_HORIZONTAL +enum wxSheetSplitMode_Type { + wxSHEET_SPLIT_NONE = 0, + wxSHEET_SPLIT_VERTICAL, + wxSHEET_SPLIT_HORIZONTAL }; // These window styles are used from wxSplitterWindow -//#define wxSP_NOBORDER 0x0000 -//#define wxSP_NOSASH 0x0010 -//#define wxSP_PERMIT_UNSPLIT 0x0040 -//#define wxSP_LIVE_UPDATE 0x0080 -//#define wxSP_3DSASH 0x0100 -//#define wxSP_3DBORDER 0x0200 -//#define wxSP_NO_XP_THEME 0x0400 -//#define wxSP_BORDER wxSP_3DBORDER -//#define wxSP_3D (wxSP_3DBORDER | wxSP_3DSASH) - -class WXDLLIMPEXP_SHEET wxSheetSplitter : public wxNavigationEnabled -{ +// #define wxSP_NOBORDER 0x0000 +// #define wxSP_NOSASH 0x0010 +// #define wxSP_PERMIT_UNSPLIT 0x0040 +// #define wxSP_LIVE_UPDATE 0x0080 +// #define wxSP_3DSASH 0x0100 +// #define wxSP_3DBORDER 0x0200 +// #define wxSP_NO_XP_THEME 0x0400 +// #define wxSP_BORDER wxSP_3DBORDER +// #define wxSP_3D (wxSP_3DBORDER | wxSP_3DSASH) + +class WXDLLIMPEXP_SHEET wxSheetSplitter : public wxNavigationEnabled { public: - wxSheetSplitter() : wxNavigationEnabled() { Init(); } - wxSheetSplitter(wxWindow *parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxSP_3D|wxSP_3DBORDER, - const wxString& name = wxT("wxSheetSplitter")) - { - Init(); - Create(parent, id, pos, size, style, name); - } - - bool Create(wxWindow *parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxSP_3D|wxSP_3DBORDER, - const wxString& name = wxT("wxSheetSplitter")); - - virtual ~wxSheetSplitter(); - virtual bool Destroy(); - - // Initialize the splitter with one window, the splitter must be sheet's parent - void Initialize(wxSheet* sheet); - - // Will the splitting buttons be shown for vert/horiz splitting - // you can still call SplitVertically/Horizontally however - bool GetEnableSplitVertically() const { return m_enable_split_vert; } - bool GetEnableSplitHorizontally() const { return m_enable_split_horiz; } - void EnableSplitVertically(bool can_split) { m_enable_split_vert = can_split; } - void EnableSplitHorizontally(bool can_split) { m_enable_split_horiz = can_split; } - - bool IsSplitHorizontally() const { return m_tlSheet && m_trSheet; } - bool IsSplitVertically() const { return m_tlSheet && m_blSheet; } - - // Split the windows either vertically or horizontally - virtual void SplitVertically(int y_pos, bool sendEvt = false); - virtual void SplitHorizontally(int x_pos, bool sendEvt = false); - // Unsplit the windows, note that the bottom/right window is the one - // that's actually removed, but the origin of the top/left will be set to - // that if !remove_bottom/right so it'll look like the top/left was removed - virtual void UnsplitVertically(bool remove_bottom = true, bool sendEvt = false); - virtual void UnsplitHorizontally(bool remove_right = true, bool sendEvt = false); - - // Get the position of the sash, 0 if not split - int GetHorizontalSplitPosition() const { return m_splitPos.x; } - int GetVerticalSplitPosition() const { return m_splitPos.y; } - // Split, unsplit, and set the sash position - // If pos <= 0 unsplit and set the origin of the left/top to val of right/bottom - // If pos >= GetClientSize().GetWidth/Height() unsplit - // If unsplit and pos in valid range then split - // If split then move the sash to the position - virtual void SetVerticalSplitPosition(int y_pos, bool sendEvt = false); - virtual void SetHorizontalSplitPosition(int x_pos, bool sendEvt = false); - - // The top left window is the window you Initialized this with - wxSheet* GetTopLeftSheet() const { return m_tlSheet; } - // The top right is valid when split vertically - wxSheet* GetTopRightSheet() const { return m_trSheet; } - // the bottom left sheet is valid when split horizontally - wxSheet* GetBottomLeftSheet() const { return m_blSheet; } - // The bottom right sheet is valid when split vertically and horizontally - wxSheet* GetBottomRightSheet() const { return m_brSheet; } - - // Get the width of the sash - int GetSashSize() const; - // Get the size of the border around the window - int GetBorderSize() const; - - // For the given sash position adjust it so that it's valid for the - // window given the min size and if it can unsplit. - int GetAdjustedVerticalSashPosition(int pos) const; - int GetAdjustedHorizontalSashPosition(int pos) const; - - // implementation - void OnViewChanged(wxSheetEvent& event); - void OnSplit(wxSheetSplitterEvent& event); - void OnMouse( wxMouseEvent& event ); - void OnPaint( wxPaintEvent& event ); - void DrawSash(wxDC &dc); - void DrawSashTracker(int x, int y); - - // returns wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL - int SashHitTest(const wxPoint& pt) const; - // Set the cursor to use wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL - void SetMouseCursor(int sheet_split_mode); - - // setup the configuration of the sheets (hide/show labels/scrollbars) - void ConfigureWindows(); - // Position the windows in this window - void LayoutWindows(); - // Send the event and returns true if it wasn't vetoed - bool SendEvent( wxEventType type, bool vert_split ); - bool DoSendEvent( wxSheetSplitterEvent& event ); + wxSheetSplitter() : wxNavigationEnabled() { Init(); } + wxSheetSplitter(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, long style = wxSP_3D | wxSP_3DBORDER, + const wxString &name = wxT("wxSheetSplitter")) + { + Init(); + Create(parent, id, pos, size, style, name); + } + + bool Create(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, long style = wxSP_3D | wxSP_3DBORDER, + const wxString &name = wxT("wxSheetSplitter")); + + virtual ~wxSheetSplitter(); + virtual bool Destroy(); + + // Initialize the splitter with one window, the splitter must be sheet's parent + void Initialize(wxSheet *sheet); + + // Will the splitting buttons be shown for vert/horiz splitting + // you can still call SplitVertically/Horizontally however + bool GetEnableSplitVertically() const { return m_enable_split_vert; } + bool GetEnableSplitHorizontally() const { return m_enable_split_horiz; } + void EnableSplitVertically(bool can_split) { m_enable_split_vert = can_split; } + void EnableSplitHorizontally(bool can_split) { m_enable_split_horiz = can_split; } + + bool IsSplitHorizontally() const { return m_tlSheet && m_trSheet; } + bool IsSplitVertically() const { return m_tlSheet && m_blSheet; } + + // Split the windows either vertically or horizontally + virtual void SplitVertically(int y_pos, bool sendEvt = false); + virtual void SplitHorizontally(int x_pos, bool sendEvt = false); + // Unsplit the windows, note that the bottom/right window is the one + // that's actually removed, but the origin of the top/left will be set to + // that if !remove_bottom/right so it'll look like the top/left was removed + virtual void UnsplitVertically(bool remove_bottom = true, bool sendEvt = false); + virtual void UnsplitHorizontally(bool remove_right = true, bool sendEvt = false); + + // Get the position of the sash, 0 if not split + int GetHorizontalSplitPosition() const { return m_splitPos.x; } + int GetVerticalSplitPosition() const { return m_splitPos.y; } + // Split, unsplit, and set the sash position + // If pos <= 0 unsplit and set the origin of the left/top to val of right/bottom + // If pos >= GetClientSize().GetWidth/Height() unsplit + // If unsplit and pos in valid range then split + // If split then move the sash to the position + virtual void SetVerticalSplitPosition(int y_pos, bool sendEvt = false); + virtual void SetHorizontalSplitPosition(int x_pos, bool sendEvt = false); + + // The top left window is the window you Initialized this with + wxSheet *GetTopLeftSheet() const { return m_tlSheet; } + // The top right is valid when split vertically + wxSheet *GetTopRightSheet() const { return m_trSheet; } + // the bottom left sheet is valid when split horizontally + wxSheet *GetBottomLeftSheet() const { return m_blSheet; } + // The bottom right sheet is valid when split vertically and horizontally + wxSheet *GetBottomRightSheet() const { return m_brSheet; } + + // Get the width of the sash + int GetSashSize() const; + // Get the size of the border around the window + int GetBorderSize() const; + + // For the given sash position adjust it so that it's valid for the + // window given the min size and if it can unsplit. + int GetAdjustedVerticalSashPosition(int pos) const; + int GetAdjustedHorizontalSashPosition(int pos) const; + + // implementation + void OnViewChanged(wxSheetEvent &event); + void OnSplit(wxSheetSplitterEvent &event); + void OnMouse(wxMouseEvent &event); + void OnPaint(wxPaintEvent &event); + void DrawSash(wxDC &dc); + void DrawSashTracker(int x, int y); + + // returns wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL + int SashHitTest(const wxPoint &pt) const; + // Set the cursor to use wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL + void SetMouseCursor(int sheet_split_mode); + + // setup the configuration of the sheets (hide/show labels/scrollbars) + void ConfigureWindows(); + // Position the windows in this window + void LayoutWindows(); + // Send the event and returns true if it wasn't vetoed + bool SendEvent(wxEventType type, bool vert_split); + bool DoSendEvent(wxSheetSplitterEvent &event); protected: - // Override this to return a derived wxSheet of your own making - // if you don't want to use the wxEVT_SHEET_SPLIT_CREATE_SHEET event - virtual wxSheet* CreateSheet(wxWindowID id = wxID_ANY); - // Overriding these functions are optional, they call CreateSheet to get a - // sheet to use and then properly initialize by hiding the labels and - // scrollbars as necessary. - virtual wxSheet* CreateTopRightSheet(wxWindowID id = wxID_ANY); - virtual wxSheet* CreateBottomLeftSheet(wxWindowID id = wxID_ANY); - virtual wxSheet* CreateBottomRightSheet(wxWindowID id = wxID_ANY); - - void OnSize( wxSizeEvent& event ); - - wxSheet *m_tlSheet; - wxSheet *m_trSheet; - wxSheet *m_blSheet; - wxSheet *m_brSheet; - - wxPoint m_mousePos; // mouse pos for sash tracker - wxPoint m_splitPos; // current position of the splitter - int m_splitMode; // currently active sash wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL - int m_splitCursor; // currently active cursor wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL - //int m_sash_width; FIXME maybe be backwards compatible to 2.4? - bool m_enable_split_vert; - bool m_enable_split_horiz; - wxSize m_minSize; + // Override this to return a derived wxSheet of your own making + // if you don't want to use the wxEVT_SHEET_SPLIT_CREATE_SHEET event + virtual wxSheet *CreateSheet(wxWindowID id = wxID_ANY); + // Overriding these functions are optional, they call CreateSheet to get a + // sheet to use and then properly initialize by hiding the labels and + // scrollbars as necessary. + virtual wxSheet *CreateTopRightSheet(wxWindowID id = wxID_ANY); + virtual wxSheet *CreateBottomLeftSheet(wxWindowID id = wxID_ANY); + virtual wxSheet *CreateBottomRightSheet(wxWindowID id = wxID_ANY); + + void OnSize(wxSizeEvent &event); + + wxSheet *m_tlSheet; + wxSheet *m_trSheet; + wxSheet *m_blSheet; + wxSheet *m_brSheet; + + wxPoint m_mousePos; // mouse pos for sash tracker + wxPoint m_splitPos; // current position of the splitter + int m_splitMode; // currently active sash wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL + int m_splitCursor; // currently active cursor wxSHEET_SPLIT_NONE/VERTICAL/HORIZONTAL + // int m_sash_width; FIXME maybe be backwards compatible to 2.4? + bool m_enable_split_vert; + bool m_enable_split_horiz; + wxSize m_minSize; private: - void Init(); + void Init(); - DECLARE_DYNAMIC_CLASS(wxSheetSplitter) - DECLARE_EVENT_TABLE() - DECLARE_NO_COPY_CLASS(wxSheetSplitter) + DECLARE_DYNAMIC_CLASS(wxSheetSplitter) + DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxSheetSplitter) }; // ---------------------------------------------------------------------------- // wxSheetSplitterEvent // ---------------------------------------------------------------------------- -class /* WXDLLEXPORT */ wxSheetSplitterEvent : public wxNotifyEvent -{ +class /* WXDLLEXPORT */ wxSheetSplitterEvent : public wxNotifyEvent { public: - wxSheetSplitterEvent(int id = 0, wxEventType type = wxEVT_NULL) - : wxNotifyEvent(type, id), m_sash_pos(0), m_vert_split(false) {} - - wxSheetSplitterEvent(const wxSheetSplitterEvent& event) : wxNotifyEvent(event), - m_sash_pos(event.m_sash_pos), m_vert_split(event.m_vert_split) { } - virtual ~wxSheetSplitterEvent() { } - - // Get the current sash position, see also IsVerticalSplit for which sash. - int GetSashPosition() const { return m_sash_pos; } - // Set the sash position, during a wxEVT_SHEET_SPLIT_CHANGING you may - // replace the current value with a different one to force a new position. - void SetSashPosition(int pos) { m_sash_pos = pos; } - // Does this event pertain to a vertical or horizontal splitting - bool IsVerticalSplit() const { return m_vert_split; } - - // The sheet is valid only for the wxEVT_SHEET_SPLIT_BEGIN event type - wxSheet* GetSheet() const { return wxDynamicCast(GetEventObject(), wxSheet); } - // The sheet splitter is valid for the rest of the splitter events - wxSheetSplitter* GetSheetSplitter() const { return wxDynamicCast(GetEventObject(), wxSheetSplitter); } - - // implementation - virtual wxEvent *Clone() const { return new wxSheetSplitterEvent(*this); } - - int m_sash_pos; - bool m_vert_split; + wxSheetSplitterEvent(int id = 0, wxEventType type = wxEVT_NULL) + : wxNotifyEvent(type, id), m_sash_pos(0), m_vert_split(false) + { + } + + wxSheetSplitterEvent(const wxSheetSplitterEvent &event) + : wxNotifyEvent(event), m_sash_pos(event.m_sash_pos), m_vert_split(event.m_vert_split) + { + } + virtual ~wxSheetSplitterEvent() {} + + // Get the current sash position, see also IsVerticalSplit for which sash. + int GetSashPosition() const { return m_sash_pos; } + // Set the sash position, during a wxEVT_SHEET_SPLIT_CHANGING you may + // replace the current value with a different one to force a new position. + void SetSashPosition(int pos) { m_sash_pos = pos; } + // Does this event pertain to a vertical or horizontal splitting + bool IsVerticalSplit() const { return m_vert_split; } + + // The sheet is valid only for the wxEVT_SHEET_SPLIT_BEGIN event type + wxSheet *GetSheet() const { return wxDynamicCast(GetEventObject(), wxSheet); } + // The sheet splitter is valid for the rest of the splitter events + wxSheetSplitter *GetSheetSplitter() const + { + return wxDynamicCast(GetEventObject(), wxSheetSplitter); + } + + // implementation + virtual wxEvent *Clone() const { return new wxSheetSplitterEvent(*this); } + + int m_sash_pos; + bool m_vert_split; }; BEGIN_DECLARE_EVENT_TYPES() - // The splitter buttons in the sheet have been clicked to begin splitting - // this event comes from the wxSheet itself when the begins to drag the - // mouse on the splitter boxes. - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_BEGIN, 1800) - // The splitter sash position is changing - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CHANGING, 1801) - // The splitter sash position has changed - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CHANGED, 1802) - // The splitter sash position has been double clicked on, will unsplit - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_DOUBLECLICKED, 1803) - // The splitter has been unsplit - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_UNSPLIT, 1804) - // The splitter is splitting and is about to create a new wxSheet. - // You can provide your own wxSheet derived class by calling - // event.SetEventObject(new MySheet(event.GetSheetSplitter(), ...)) - // where the parent of the sheet you provide is the wxSheetSplitter - // which is the original event.GetEventObject. The sender wxSheetSplitter - // takes ownership of the new wxSheet and destroys it when unsplit. - // Please see the function wxSheetSplitter::CreateSheet for more info. - // You cannot veto this event since it occurs too late in the chain of splitting, - // use veto on wxEVT_SHEET_SPLIT_BEGIN to stop it in the first place. - DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CREATE_SHEET, 1805) +// The splitter buttons in the sheet have been clicked to begin splitting +// this event comes from the wxSheet itself when the begins to drag the +// mouse on the splitter boxes. +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_BEGIN, 1800) +// The splitter sash position is changing +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CHANGING, 1801) +// The splitter sash position has changed +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CHANGED, 1802) +// The splitter sash position has been double clicked on, will unsplit +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_DOUBLECLICKED, 1803) +// The splitter has been unsplit +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_UNSPLIT, 1804) +// The splitter is splitting and is about to create a new wxSheet. +// You can provide your own wxSheet derived class by calling +// event.SetEventObject(new MySheet(event.GetSheetSplitter(), ...)) +// where the parent of the sheet you provide is the wxSheetSplitter +// which is the original event.GetEventObject. The sender wxSheetSplitter +// takes ownership of the new wxSheet and destroys it when unsplit. +// Please see the function wxSheetSplitter::CreateSheet for more info. +// You cannot veto this event since it occurs too late in the chain of splitting, +// use veto on wxEVT_SHEET_SPLIT_BEGIN to stop it in the first place. +DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_SHEET, wxEVT_SHEET_SPLIT_CREATE_SHEET, 1805) END_DECLARE_EVENT_TYPES() -typedef void (wxEvtHandler::*wxSheetSplitterEventFunction)(wxSheetSplitterEvent&); - -#define EVT_SHEET_SPLIT_BEGIN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_BEGIN, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), -#define EVT_SHEET_SPLIT_CHANGING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_CHANGING, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), -#define EVT_SHEET_SPLIT_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_CHANGED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), -#define EVT_SHEET_SPLIT_DOUBLECLICKED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_DOUBLECLICKED, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), -#define EVT_SHEET_SPLIT_UNSPLIT(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_UNSPLIT, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), -#define EVT_SHEET_SPLIT_CREATE_SHEET(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SHEET_SPLIT_CREATE_SHEET, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent(wxSheetSplitterEventFunction, &fn), NULL ), - -#endif // __WX_SHEETSPT_H__ +typedef void (wxEvtHandler::*wxSheetSplitterEventFunction)(wxSheetSplitterEvent &); + +#define EVT_SHEET_SPLIT_BEGIN(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_SPLIT_BEGIN, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetSplitterEventFunction, &fn), \ + NULL), +#define EVT_SHEET_SPLIT_CHANGING(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_SPLIT_CHANGING, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetSplitterEventFunction, &fn), \ + NULL), +#define EVT_SHEET_SPLIT_CHANGED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_SPLIT_CHANGED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetSplitterEventFunction, &fn), \ + NULL), +#define EVT_SHEET_SPLIT_DOUBLECLICKED(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_SPLIT_DOUBLECLICKED, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetSplitterEventFunction, &fn), \ + NULL), +#define EVT_SHEET_SPLIT_UNSPLIT(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_SPLIT_UNSPLIT, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetSplitterEventFunction, &fn), \ + NULL), +#define EVT_SHEET_SPLIT_CREATE_SHEET(id, fn) \ + DECLARE_EVENT_TABLE_ENTRY(wxEVT_SHEET_SPLIT_CREATE_SHEET, id, wxID_ANY, \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent( \ + wxSheetSplitterEventFunction, &fn), \ + NULL), + +#endif // __WX_SHEETSPT_H__ diff --git a/src/labenski/include/wx/sheet/sheettbl.h b/src/labenski/include/wx/sheet/sheettbl.h index b8b3a2125..61b30133f 100644 --- a/src/labenski/include/wx/sheet/sheettbl.h +++ b/src/labenski/include/wx/sheet/sheettbl.h @@ -27,18 +27,17 @@ // and not to the full extent, therefore an insert beyond the end of this // array should simply be ignored. // ---------------------------------------------------------------------------- -bool wxArrayStringUpdatePos(wxArrayString& arr, size_t pos, int num, bool no_error = false); +bool wxArrayStringUpdatePos(wxArrayString &arr, size_t pos, int num, bool no_error = false); // ---------------------------------------------------------------------------- // wxSheetStringArray (wxGridStringArray) a 2d array of wxStrings // ---------------------------------------------------------------------------- #if wxUSE_GRID - #include "wx/grid.h" // get wxGridStringArray from grid - typedef wxGridStringArray wxSheetStringArray; -#else // !wxUSE_GRID - WX_DECLARE_OBJARRAY_WITH_DECL(wxArrayString, wxSheetStringArray, - class WXDLLIMPEXP_SHEET); +#include "wx/grid.h" // get wxGridStringArray from grid +typedef wxGridStringArray wxSheetStringArray; +#else // !wxUSE_GRID +WX_DECLARE_OBJARRAY_WITH_DECL(wxArrayString, wxSheetStringArray, class WXDLLIMPEXP_SHEET); #endif // wxUSE_GRID // ---------------------------------------------------------------------------- @@ -47,65 +46,70 @@ bool wxArrayStringUpdatePos(wxArrayString& arr, size_t pos, int num, bool no_err // ---------------------------------------------------------------------------- // wxSheetCellValueProvider_Type - values for the wxSheetCellValueProvider options -enum wxSheetValueProvider_Type -{ - wxSHEET_ValueProviderColPref = 0x0001 // optimize for more cols than rows +enum wxSheetValueProvider_Type { + wxSHEET_ValueProviderColPref = 0x0001 // optimize for more cols than rows }; -class WXDLLIMPEXP_SHEET wxSheetValueProviderBase : public wxObject -{ +class WXDLLIMPEXP_SHEET wxSheetValueProviderBase : public wxObject { public: - wxSheetValueProviderBase(size_t numRows = 0u, size_t numCols = 0u, int options = 0) - :m_numRows(numRows), m_numCols(numCols), m_options(options) {} - virtual ~wxSheetValueProviderBase() {} - - // Get the size of the data structure (override this as necessary) - // note: these are called often so you may wish to set member vars as necessary - // all base class calls that require the number of rows/cols use these functions - // if you change the number you must alert the sheet - see wxSheetTable::UpdateSheetXXX - virtual int GetNumberRows() const { return m_numRows; } - virtual int GetNumberCols() const { return m_numCols; } - bool ContainsCell(const wxSheetCoords& coords) const - { return (coords.m_row >= 0) && (coords.m_col >= 0) && - (coords.m_row < GetNumberRows()) && - (coords.m_col < GetNumberCols()); } - - // Get/SetValue for a single cell - virtual wxString GetValue( const wxSheetCoords& coords ) const = 0; - virtual void SetValue( const wxSheetCoords& coords, const wxString& value ) = 0; - // Is this cell empty - defaults ueries if the string is empty - virtual bool HasValue( const wxSheetCoords& coords ) const - { return !GetValue(coords).IsEmpty(); } - // Get the first cell to the left that is not empty, or just return col - 1 - // this is used for optimizing redrawing - virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const - { return coords.m_col - 1; } - // Clear all values to be `empty` - virtual void ClearValues() {} - - // Clear all values and set the number of rows/cols to 0 - // default implementation uses UpdateRows/Cols(0, -numRows/Cols) - virtual void Clear(); - // Update number of rows/cols - virtual bool UpdateRows( size_t row, int numRows ) = 0; - virtual bool UpdateCols( size_t col, int numCols ) = 0; - - // Get/Set options - usage depends on the subclassed version - int GetOptions() const { return m_options; } - bool HasOption(int mask) const { return (GetOptions() & mask) != 0; } - virtual void SetOptions(int options) { m_options = options; } - - // make this an identical copy of other - // the default copies using Get/SetValue and sets only if HasValue - virtual void Copy(const wxSheetValueProviderBase& other); - - virtual wxSheetValueProviderBase& operator = (const wxSheetValueProviderBase& data) - { Copy(data); return *this; } + wxSheetValueProviderBase(size_t numRows = 0u, size_t numCols = 0u, int options = 0) + : m_numRows(numRows), m_numCols(numCols), m_options(options) + { + } + virtual ~wxSheetValueProviderBase() {} + + // Get the size of the data structure (override this as necessary) + // note: these are called often so you may wish to set member vars as necessary + // all base class calls that require the number of rows/cols use these functions + // if you change the number you must alert the sheet - see wxSheetTable::UpdateSheetXXX + virtual int GetNumberRows() const { return m_numRows; } + virtual int GetNumberCols() const { return m_numCols; } + bool ContainsCell(const wxSheetCoords &coords) const + { + return (coords.m_row >= 0) && (coords.m_col >= 0) && (coords.m_row < GetNumberRows()) && + (coords.m_col < GetNumberCols()); + } + + // Get/SetValue for a single cell + virtual wxString GetValue(const wxSheetCoords &coords) const = 0; + virtual void SetValue(const wxSheetCoords &coords, const wxString &value) = 0; + // Is this cell empty - defaults ueries if the string is empty + virtual bool HasValue(const wxSheetCoords &coords) const { return !GetValue(coords).IsEmpty(); } + // Get the first cell to the left that is not empty, or just return col - 1 + // this is used for optimizing redrawing + virtual int GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) const + { + return coords.m_col - 1; + } + // Clear all values to be `empty` + virtual void ClearValues() {} + + // Clear all values and set the number of rows/cols to 0 + // default implementation uses UpdateRows/Cols(0, -numRows/Cols) + virtual void Clear(); + // Update number of rows/cols + virtual bool UpdateRows(size_t row, int numRows) = 0; + virtual bool UpdateCols(size_t col, int numCols) = 0; + + // Get/Set options - usage depends on the subclassed version + int GetOptions() const { return m_options; } + bool HasOption(int mask) const { return (GetOptions() & mask) != 0; } + virtual void SetOptions(int options) { m_options = options; } + + // make this an identical copy of other + // the default copies using Get/SetValue and sets only if HasValue + virtual void Copy(const wxSheetValueProviderBase &other); + + virtual wxSheetValueProviderBase &operator=(const wxSheetValueProviderBase &data) + { + Copy(data); + return *this; + } protected: - int m_numRows, m_numCols; - int m_options; - DECLARE_ABSTRACT_CLASS(wxSheetValueProviderBase) + int m_numRows, m_numCols; + int m_options; + DECLARE_ABSTRACT_CLASS(wxSheetValueProviderBase) }; // ---------------------------------------------------------------------------- @@ -114,37 +118,40 @@ class WXDLLIMPEXP_SHEET wxSheetValueProviderBase : public wxObject // it takes the option wxSHEET_ValueProviderColPref // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetValueProviderString : public wxSheetValueProviderBase -{ +class WXDLLIMPEXP_SHEET wxSheetValueProviderString : public wxSheetValueProviderBase { public: - wxSheetValueProviderString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); + wxSheetValueProviderString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); - //virtual int GetNumberRows() const { return m_numRows; } - //virtual int GetNumberCols() const { return m_numCols; } + // virtual int GetNumberRows() const { return m_numRows; } + // virtual int GetNumberCols() const { return m_numCols; } - virtual wxString GetValue( const wxSheetCoords& coords ) const; - virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); - //virtual bool HasValue( const wxSheetCoords& coords ) const; - virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const; - virtual void ClearValues() { m_data.Clear(); } + virtual wxString GetValue(const wxSheetCoords &coords) const; + virtual void SetValue(const wxSheetCoords &coords, const wxString &value); + // virtual bool HasValue( const wxSheetCoords& coords ) const; + virtual int GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) const; + virtual void ClearValues() { m_data.Clear(); } - virtual void Clear() { m_data.Clear(); m_numRows = m_numCols = 0; } - virtual bool UpdateRows( size_t row, int numRows ); - virtual bool UpdateCols( size_t col, int numCols ); + virtual void Clear() + { + m_data.Clear(); + m_numRows = m_numCols = 0; + } + virtual bool UpdateRows(size_t row, int numRows); + virtual bool UpdateCols(size_t col, int numCols); - //int GetOptions() const { return m_options; } - //bool HasOptions(int mask) const { return (m_options & mask) != 0; } - virtual void SetOptions(int options); + // int GetOptions() const { return m_options; } + // bool HasOptions(int mask) const { return (m_options & mask) != 0; } + virtual void SetOptions(int options); - // implementation - const wxSheetStringArray& GetData() const { return m_data; } - wxSheetStringArray& GetData() { return m_data; } + // implementation + const wxSheetStringArray &GetData() const { return m_data; } + wxSheetStringArray &GetData() { return m_data; } protected: - bool DoUpdateRows( size_t row, int numRows ); - bool DoUpdateCols( size_t col, int numCols ); - wxSheetStringArray m_data; - DECLARE_ABSTRACT_CLASS(wxSheetValueProviderString) + bool DoUpdateRows(size_t row, int numRows); + bool DoUpdateCols(size_t col, int numCols); + wxSheetStringArray m_data; + DECLARE_ABSTRACT_CLASS(wxSheetValueProviderString) }; // ---------------------------------------------------------------------------- @@ -155,8 +162,8 @@ class WXDLLIMPEXP_SHEET wxSheetValueProviderString : public wxSheetValueProvider // stores the strings for the sparse table // ---------------------------------------------------------------------------- -DECLARE_PAIRED_INT_DATA_ARRAYS( wxString, wxArrayString, - wxPairArrayIntSheetString, class WXDLLIMPEXP_SHEET) +DECLARE_PAIRED_INT_DATA_ARRAYS(wxString, wxArrayString, wxPairArrayIntSheetString, + class WXDLLIMPEXP_SHEET) // ---------------------------------------------------------------------------- @@ -164,8 +171,8 @@ WX_DECLARE_OBJARRAY_WITH_DECL(wxPairArrayIntSheetString, wxArrayPairArrayIntShee class WXDLLIMPEXP_SHEET); // ---------------------------------------------------------------------------- -DECLARE_PAIRED_INT_DATA_ARRAYS( wxPairArrayIntSheetString, wxArrayPairArrayIntSheetString, - wxPairArrayIntPairArraySheetString, class WXDLLIMPEXP_SHEET) +DECLARE_PAIRED_INT_DATA_ARRAYS(wxPairArrayIntSheetString, wxArrayPairArrayIntSheetString, + wxPairArrayIntPairArraySheetString, class WXDLLIMPEXP_SHEET) // ---------------------------------------------------------------------------- // wxSheetCellStringSparseData - a sparse wxString data container class @@ -174,36 +181,39 @@ DECLARE_PAIRED_INT_DATA_ARRAYS( wxPairArrayIntSheetString, wxArrayPairArrayIntSh // it takes the option wxSHEET_ValueProviderColPref // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetValueProviderSparseString : public wxSheetValueProviderBase -{ +class WXDLLIMPEXP_SHEET wxSheetValueProviderSparseString : public wxSheetValueProviderBase { public: - wxSheetValueProviderSparseString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); + wxSheetValueProviderSparseString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); - //virtual int GetNumberRows() const { return m_numRows; } - //virtual int GetNumberCols() const { return m_numCols; } + // virtual int GetNumberRows() const { return m_numRows; } + // virtual int GetNumberCols() const { return m_numCols; } - virtual wxString GetValue( const wxSheetCoords& coords ) const; - virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); - virtual bool HasValue( const wxSheetCoords& coords ) const; - virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const; - virtual void ClearValues() { m_data.Clear(); } + virtual wxString GetValue(const wxSheetCoords &coords) const; + virtual void SetValue(const wxSheetCoords &coords, const wxString &value); + virtual bool HasValue(const wxSheetCoords &coords) const; + virtual int GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) const; + virtual void ClearValues() { m_data.Clear(); } - virtual void Clear() { m_data.Clear(); m_numRows = m_numCols = 0; } - virtual bool UpdateRows( size_t row, int numRows ); - virtual bool UpdateCols( size_t col, int numCols ); + virtual void Clear() + { + m_data.Clear(); + m_numRows = m_numCols = 0; + } + virtual bool UpdateRows(size_t row, int numRows); + virtual bool UpdateCols(size_t col, int numCols); - virtual void SetOptions(int options); + virtual void SetOptions(int options); - // implementation - void RemoveEmpty(); // if there are no cols then might as well remove row - const wxPairArrayIntPairArraySheetString& GetData() const { return m_data; } - wxPairArrayIntPairArraySheetString& GetData() { return m_data; } + // implementation + void RemoveEmpty(); // if there are no cols then might as well remove row + const wxPairArrayIntPairArraySheetString &GetData() const { return m_data; } + wxPairArrayIntPairArraySheetString &GetData() { return m_data; } protected: - bool DoUpdateRows( size_t row, int numRows ); - bool DoUpdateCols( size_t col, int numCols ); - wxPairArrayIntPairArraySheetString m_data; - DECLARE_ABSTRACT_CLASS(wxSheetValueProviderSparseString) + bool DoUpdateRows(size_t row, int numRows); + bool DoUpdateCols(size_t col, int numCols); + wxPairArrayIntPairArraySheetString m_data; + DECLARE_ABSTRACT_CLASS(wxSheetValueProviderSparseString) }; // The wxSheetValueProviderHashString is probably not for everyone @@ -220,38 +230,42 @@ class WXDLLIMPEXP_SHEET wxSheetValueProviderSparseString : public wxSheetValuePr // it takes the option wxSHEET_ValueProviderColPref // ---------------------------------------------------------------------------- #include "wx/hashmap.h" -WX_DECLARE_HASH_MAP( int, wxString, wxIntegerHash, wxIntegerEqual, wxSheetStringHash ); -WX_DECLARE_HASH_MAP( int, wxSheetStringHash, wxIntegerHash, wxIntegerEqual, wxSheetStringHashStringHash ); +WX_DECLARE_HASH_MAP(int, wxString, wxIntegerHash, wxIntegerEqual, wxSheetStringHash); +WX_DECLARE_HASH_MAP(int, wxSheetStringHash, wxIntegerHash, wxIntegerEqual, + wxSheetStringHashStringHash); -class WXDLLIMPEXP_SHEET wxSheetValueProviderHashString : public wxSheetValueProviderBase -{ +class WXDLLIMPEXP_SHEET wxSheetValueProviderHashString : public wxSheetValueProviderBase { public: - wxSheetValueProviderHashString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); + wxSheetValueProviderHashString(size_t numRows = 0u, size_t numCols = 0u, int options = 0); - //virtual int GetNumberRows() const { return m_numRows; } - //virtual int GetNumberCols() const { return m_numCols; } + // virtual int GetNumberRows() const { return m_numRows; } + // virtual int GetNumberCols() const { return m_numCols; } - virtual wxString GetValue( const wxSheetCoords& coords ) const; - virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); - virtual bool HasValue( const wxSheetCoords& coords ) const; - virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const; - virtual void ClearValues() { m_data.clear(); } + virtual wxString GetValue(const wxSheetCoords &coords) const; + virtual void SetValue(const wxSheetCoords &coords, const wxString &value); + virtual bool HasValue(const wxSheetCoords &coords) const; + virtual int GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) const; + virtual void ClearValues() { m_data.clear(); } - virtual void Clear() { m_data.clear(); m_numRows = m_numCols = 0; } - virtual bool UpdateRows( size_t row, int numRows ); - virtual bool UpdateCols( size_t col, int numCols ); + virtual void Clear() + { + m_data.clear(); + m_numRows = m_numCols = 0; + } + virtual bool UpdateRows(size_t row, int numRows); + virtual bool UpdateCols(size_t col, int numCols); - virtual void SetOptions(int options); + virtual void SetOptions(int options); - // implementation - const wxSheetStringHashStringHash& GetData() const { return m_data; } - wxSheetStringHashStringHash& GetData() { return m_data; } + // implementation + const wxSheetStringHashStringHash &GetData() const { return m_data; } + wxSheetStringHashStringHash &GetData() { return m_data; } protected: - bool DoUpdateRows( size_t row, int numRows ); - bool DoUpdateCols( size_t col, int numCols ); - wxSheetStringHashStringHash m_data; - DECLARE_ABSTRACT_CLASS(wxSheetValueProviderHashString) + bool DoUpdateRows(size_t row, int numRows); + bool DoUpdateCols(size_t col, int numCols); + wxSheetStringHashStringHash m_data; + DECLARE_ABSTRACT_CLASS(wxSheetValueProviderHashString) }; #endif // wxSHEET_USE_VALUE_PROVIDER_HASH @@ -259,195 +273,199 @@ class WXDLLIMPEXP_SHEET wxSheetValueProviderHashString : public wxSheetValueProv // wxSheetTable - data provider table for the wxSheet you may want to subclass // this to optimize it for your purposes // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetTable : public wxObject, public wxClientDataContainer -{ +class WXDLLIMPEXP_SHEET wxSheetTable : public wxObject, public wxClientDataContainer { public: - wxSheetTable( wxSheet *sheet = NULL ); - virtual ~wxSheetTable(); - - // Set/Get the wxSheet "owner" of this data - virtual void SetView( wxSheet *sheet ) { m_view = sheet; } - virtual wxSheet* GetView() const { return m_view; } - - // ------------------------------------------------------------------------ - // Get the number of rows and cols - // the default uses the number of rows/cols in GetCellData() - virtual int GetNumberRows(); - virtual int GetNumberCols(); - // determine if row/col/coords is in 0 to GetNumberRows/Cols-1 - bool ContainsGridRow( int row ) { return (row >= 0) && (row < GetNumberRows()); } - bool ContainsGridCol( int col ) { return (col >= 0) && (col < GetNumberCols()); } - bool ContainsGridCell(const wxSheetCoords& coords) - { return ContainsGridRow(coords.m_row) && ContainsGridCol(coords.m_col); } - // returns true if the coords are within the row/col label cells - bool ContainsRowLabelCell( const wxSheetCoords& coords ) - { return (coords.m_col == -1) && ContainsGridRow(coords.m_row); } - bool ContainsColLabelCell( const wxSheetCoords& coords ) - { return (coords.m_row == -1) && ContainsGridCol(coords.m_col); } - - // ------------------------------------------------------------------------ - // Cell value handling - - // GetValue as a string, coords use -1 notatation for label cells - // you must have set the value providers for cell values or subclass - // this and return values on the fly. - // the label will return a default value if no provider is set - virtual wxString GetValue( const wxSheetCoords& coords ); - // SetValue as a string, coords use -1 notatation for label cells - // you must have previously set containers - virtual void SetValue( const wxSheetCoords& coords, const wxString& value ); - // Is this cell empty, uses container's HasValue or !GetValue().IsEmpty() - virtual bool HasValue( const wxSheetCoords& coords ); - // renderer helper, returns first col < coords.m_col that's !empty - // or just return the previous col if you can't implement that - virtual int GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ); - - // Clear the values of the grid, the defaut can be used to clear - // ORed together different enum wxSheetUpdate_Type - virtual void ClearValues(int update = wxSHEET_UpdateValues); - - // default GetRow/ColLabelValue returns numbers for rows and A-AZ for cols - // GetValue is routed to these functions if no value providers for the - // labels are set. - wxString GetDefaultRowLabelValue( int row ) const; - wxString GetDefaultColLabelValue( int col ) const; - - // Specific data type determination and value access - - // try to return GetValue as a long, returns 0 on failure - virtual long GetValueAsLong( const wxSheetCoords& coords ); - // try to return GetValue as a double, returns 0 on failure - virtual double GetValueAsDouble( const wxSheetCoords& coords ); - // try to return GetValue as a bool, - // false is "", "0", "f", "false" w/ no case, true otherwise - virtual bool GetValueAsBool( const wxSheetCoords& coords ); - - // Set the cell's value as a long "%ld", double "%g", or bool "0" or "1" - // the default converts them to a string and calls SetValue - virtual void SetValueAsLong( const wxSheetCoords& coords, long value ); - virtual void SetValueAsDouble( const wxSheetCoords& coords, double value ); - virtual void SetValueAsBool( const wxSheetCoords& coords, bool value ); - - // For user defined types you must cast the void* pointer to your datatype - // as well as delete it. - // The default implementation does nothing and gives an error if used - virtual void* GetValueAsCustom( const wxSheetCoords& coords, const wxString& typeName ); - virtual void SetValueAsCustom( const wxSheetCoords& coords, const wxString& typeName, void* value ); - - // Returns whether the type is supported, default is wxSHEET_VALUE_STRING - virtual bool CanGetValueAs( const wxSheetCoords& coords, const wxString& typeName ); - // Can you set the value as type? default returns CanGetValueAs - virtual bool CanSetValueAs( const wxSheetCoords& coords, const wxString& typeName ); - - // Get the type name for the cell, default returns wxEmptyString, if you - // return one of wxSHEET_VALUE_XXX the attributes will return an - // appropriate renderer and editor - virtual wxString GetTypeName( const wxSheetCoords& coords ); - - // Get/Set value providers, may be NULL. - // The GridCellValueProvider is required unless you have subclassed - // the table and override GetValue yourself. The label providers - // are not necesary and GetDefaultRow/ColLabelValue will be called. - // The providers will be deleted when done if is_owner = true. - virtual wxSheetValueProviderBase* GetGridCellValueProvider() const { return m_gridCellValues; } - virtual wxSheetValueProviderBase* GetRowLabelValueProvider() const { return m_rowLabelValues; } - virtual wxSheetValueProviderBase* GetColLabelValueProvider() const { return m_colLabelValues; } - void SetGridCellValueProvider(wxSheetValueProviderBase* gridCellValues, bool is_owner); - void SetRowLabelValueProvider(wxSheetValueProviderBase* rowLabelValues, bool is_owner); - void SetColLabelValueProvider(wxSheetValueProviderBase* colLabelValues, bool is_owner); - - // ------------------------------------------------------------------------ - // Attribute handling - - // by default forwarded to wxSheetCellAttrProvider if any. May be - // overridden to handle attributes directly in the table. - // See wxSheetCellAttrProvider for coords and type meaning - virtual wxSheetCellAttr GetAttr( const wxSheetCoords& coords, - wxSheetAttr_Type kind ); - - // See wxSheetCellAttrProvider for coords and type meaning - virtual void SetAttr( const wxSheetCoords& coords, - const wxSheetCellAttr &attr, - wxSheetAttr_Type kind ); - - // get the currently used attr provider (may be NULL) - virtual wxSheetCellAttrProvider* GetAttrProvider() const { return m_attrProvider; } - // Set the attr provider to use - take ownership if is_owner - void SetAttrProvider(wxSheetCellAttrProvider *attrProvider, bool is_owner); - - // ------------------------------------------------------------------------ - // Cell spanning - cells may overlap neighbor cells to the right and below, - // hiding the cells they cover. - // By default, the internal selection is created for you, however in a - // subclassed table you may return NULL so long as you don't call - // SetCellSpan or handle it yourself. - - // Note: this code should be as efficient as possible since it's called - // numerous times during drawing. It would be nice to have two virtual - // functions Get/Set and use them exculsively, but direct access to the - // selection's array is decidedly faster under many circumstances. - // See DrawAllGridLines and ExpandSpannedBlock for examples - - // Are there any spanned cells at all? - virtual bool HasSpannedCells(); - // Get a block of the cell, unless a spanned cell it's of size 1,1 - // note: the top left of block is the 'owner' cell of coords - virtual wxSheetBlock GetCellBlock( const wxSheetCoords& coords ); - // Set the span of a cell, must be 1x1 or greater. - // To remove a spanned cell set it to a cell of size 1x1 - // For grid cells the whole block must be contained within the grid cells - // and if the block intersects a previously spanned cell block the top left - // corners must match up. - // Row and Col labels can span cells as well, spanned row labels must have a - // width of 1 and a height of >= 1, col labels a height of 1 and width >= 1 - virtual void SetCellSpan( const wxSheetBlock& block ); - - virtual wxSheetSelection* GetSpannedBlocks() const { return m_spannedCells; } - // Set the attr provider to use - take ownership if is_owner - void SetSpannedBlocks(wxSheetSelection *spannedCells, bool is_owner); - - // ------------------------------------------------------------------------ - - // Update the number of rows cols - // if numRows/Cols < 0 delete, else append if row/col == the current - // number of rows/cols, else insert at row/col - virtual bool UpdateRows( size_t row, int numRows, int update = wxSHEET_UpdateAll ); - virtual bool UpdateCols( size_t col, int numCols, int update = wxSHEET_UpdateAll ); - - // If you have a pure virtual table and you merely want to alert the sheet - // that the number of rows/cols have changed then call this function. - // It compares the wxSheetTable::GetNumberRows/Cols to - // wxSheet::GetNumberRows/Cols and either appends Rows/Cols or deletes - // them from the end. - // You probably won't want to use this if you've set attributes for - // particular cells since this only appends and deletes from the end. - bool UpdateSheetRowsCols(int update = wxSHEET_UpdateAll ); + wxSheetTable(wxSheet *sheet = NULL); + virtual ~wxSheetTable(); + + // Set/Get the wxSheet "owner" of this data + virtual void SetView(wxSheet *sheet) { m_view = sheet; } + virtual wxSheet *GetView() const { return m_view; } + + // ------------------------------------------------------------------------ + // Get the number of rows and cols + // the default uses the number of rows/cols in GetCellData() + virtual int GetNumberRows(); + virtual int GetNumberCols(); + // determine if row/col/coords is in 0 to GetNumberRows/Cols-1 + bool ContainsGridRow(int row) { return (row >= 0) && (row < GetNumberRows()); } + bool ContainsGridCol(int col) { return (col >= 0) && (col < GetNumberCols()); } + bool ContainsGridCell(const wxSheetCoords &coords) + { + return ContainsGridRow(coords.m_row) && ContainsGridCol(coords.m_col); + } + // returns true if the coords are within the row/col label cells + bool ContainsRowLabelCell(const wxSheetCoords &coords) + { + return (coords.m_col == -1) && ContainsGridRow(coords.m_row); + } + bool ContainsColLabelCell(const wxSheetCoords &coords) + { + return (coords.m_row == -1) && ContainsGridCol(coords.m_col); + } + + // ------------------------------------------------------------------------ + // Cell value handling + + // GetValue as a string, coords use -1 notatation for label cells + // you must have set the value providers for cell values or subclass + // this and return values on the fly. + // the label will return a default value if no provider is set + virtual wxString GetValue(const wxSheetCoords &coords); + // SetValue as a string, coords use -1 notatation for label cells + // you must have previously set containers + virtual void SetValue(const wxSheetCoords &coords, const wxString &value); + // Is this cell empty, uses container's HasValue or !GetValue().IsEmpty() + virtual bool HasValue(const wxSheetCoords &coords); + // renderer helper, returns first col < coords.m_col that's !empty + // or just return the previous col if you can't implement that + virtual int GetFirstNonEmptyColToLeft(const wxSheetCoords &coords); + + // Clear the values of the grid, the defaut can be used to clear + // ORed together different enum wxSheetUpdate_Type + virtual void ClearValues(int update = wxSHEET_UpdateValues); + + // default GetRow/ColLabelValue returns numbers for rows and A-AZ for cols + // GetValue is routed to these functions if no value providers for the + // labels are set. + wxString GetDefaultRowLabelValue(int row) const; + wxString GetDefaultColLabelValue(int col) const; + + // Specific data type determination and value access + + // try to return GetValue as a long, returns 0 on failure + virtual long GetValueAsLong(const wxSheetCoords &coords); + // try to return GetValue as a double, returns 0 on failure + virtual double GetValueAsDouble(const wxSheetCoords &coords); + // try to return GetValue as a bool, + // false is "", "0", "f", "false" w/ no case, true otherwise + virtual bool GetValueAsBool(const wxSheetCoords &coords); + + // Set the cell's value as a long "%ld", double "%g", or bool "0" or "1" + // the default converts them to a string and calls SetValue + virtual void SetValueAsLong(const wxSheetCoords &coords, long value); + virtual void SetValueAsDouble(const wxSheetCoords &coords, double value); + virtual void SetValueAsBool(const wxSheetCoords &coords, bool value); + + // For user defined types you must cast the void* pointer to your datatype + // as well as delete it. + // The default implementation does nothing and gives an error if used + virtual void *GetValueAsCustom(const wxSheetCoords &coords, const wxString &typeName); + virtual void SetValueAsCustom(const wxSheetCoords &coords, const wxString &typeName, + void *value); + + // Returns whether the type is supported, default is wxSHEET_VALUE_STRING + virtual bool CanGetValueAs(const wxSheetCoords &coords, const wxString &typeName); + // Can you set the value as type? default returns CanGetValueAs + virtual bool CanSetValueAs(const wxSheetCoords &coords, const wxString &typeName); + + // Get the type name for the cell, default returns wxEmptyString, if you + // return one of wxSHEET_VALUE_XXX the attributes will return an + // appropriate renderer and editor + virtual wxString GetTypeName(const wxSheetCoords &coords); + + // Get/Set value providers, may be NULL. + // The GridCellValueProvider is required unless you have subclassed + // the table and override GetValue yourself. The label providers + // are not necesary and GetDefaultRow/ColLabelValue will be called. + // The providers will be deleted when done if is_owner = true. + virtual wxSheetValueProviderBase *GetGridCellValueProvider() const { return m_gridCellValues; } + virtual wxSheetValueProviderBase *GetRowLabelValueProvider() const { return m_rowLabelValues; } + virtual wxSheetValueProviderBase *GetColLabelValueProvider() const { return m_colLabelValues; } + void SetGridCellValueProvider(wxSheetValueProviderBase *gridCellValues, bool is_owner); + void SetRowLabelValueProvider(wxSheetValueProviderBase *rowLabelValues, bool is_owner); + void SetColLabelValueProvider(wxSheetValueProviderBase *colLabelValues, bool is_owner); + + // ------------------------------------------------------------------------ + // Attribute handling + + // by default forwarded to wxSheetCellAttrProvider if any. May be + // overridden to handle attributes directly in the table. + // See wxSheetCellAttrProvider for coords and type meaning + virtual wxSheetCellAttr GetAttr(const wxSheetCoords &coords, wxSheetAttr_Type kind); + + // See wxSheetCellAttrProvider for coords and type meaning + virtual void SetAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr, + wxSheetAttr_Type kind); + + // get the currently used attr provider (may be NULL) + virtual wxSheetCellAttrProvider *GetAttrProvider() const { return m_attrProvider; } + // Set the attr provider to use - take ownership if is_owner + void SetAttrProvider(wxSheetCellAttrProvider *attrProvider, bool is_owner); + + // ------------------------------------------------------------------------ + // Cell spanning - cells may overlap neighbor cells to the right and below, + // hiding the cells they cover. + // By default, the internal selection is created for you, however in a + // subclassed table you may return NULL so long as you don't call + // SetCellSpan or handle it yourself. + + // Note: this code should be as efficient as possible since it's called + // numerous times during drawing. It would be nice to have two virtual + // functions Get/Set and use them exculsively, but direct access to the + // selection's array is decidedly faster under many circumstances. + // See DrawAllGridLines and ExpandSpannedBlock for examples + + // Are there any spanned cells at all? + virtual bool HasSpannedCells(); + // Get a block of the cell, unless a spanned cell it's of size 1,1 + // note: the top left of block is the 'owner' cell of coords + virtual wxSheetBlock GetCellBlock(const wxSheetCoords &coords); + // Set the span of a cell, must be 1x1 or greater. + // To remove a spanned cell set it to a cell of size 1x1 + // For grid cells the whole block must be contained within the grid cells + // and if the block intersects a previously spanned cell block the top left + // corners must match up. + // Row and Col labels can span cells as well, spanned row labels must have a + // width of 1 and a height of >= 1, col labels a height of 1 and width >= 1 + virtual void SetCellSpan(const wxSheetBlock &block); + + virtual wxSheetSelection *GetSpannedBlocks() const { return m_spannedCells; } + // Set the attr provider to use - take ownership if is_owner + void SetSpannedBlocks(wxSheetSelection *spannedCells, bool is_owner); + + // ------------------------------------------------------------------------ + + // Update the number of rows cols + // if numRows/Cols < 0 delete, else append if row/col == the current + // number of rows/cols, else insert at row/col + virtual bool UpdateRows(size_t row, int numRows, int update = wxSHEET_UpdateAll); + virtual bool UpdateCols(size_t col, int numCols, int update = wxSHEET_UpdateAll); + + // If you have a pure virtual table and you merely want to alert the sheet + // that the number of rows/cols have changed then call this function. + // It compares the wxSheetTable::GetNumberRows/Cols to + // wxSheet::GetNumberRows/Cols and either appends Rows/Cols or deletes + // them from the end. + // You probably won't want to use this if you've set attributes for + // particular cells since this only appends and deletes from the end. + bool UpdateSheetRowsCols(int update = wxSHEET_UpdateAll); protected: - // return update functions back to the sheet calling DoUpdateRows/Cols - // if you subclass this you must make sure this is called - bool UpdateSheetRows( size_t row, int numRows, int update = wxSHEET_UpdateAll ); - bool UpdateSheetCols( size_t col, int numCols, int update = wxSHEET_UpdateAll ); + // return update functions back to the sheet calling DoUpdateRows/Cols + // if you subclass this you must make sure this is called + bool UpdateSheetRows(size_t row, int numRows, int update = wxSHEET_UpdateAll); + bool UpdateSheetCols(size_t col, int numCols, int update = wxSHEET_UpdateAll); - wxSheet *m_view; // 'parent' wxSheet + wxSheet *m_view; // 'parent' wxSheet - wxSheetCellAttrProvider *m_attrProvider; // attribute provider, if any - bool m_own_attr_provider; + wxSheetCellAttrProvider *m_attrProvider; // attribute provider, if any + bool m_own_attr_provider; - wxSheetValueProviderBase *m_gridCellValues; // grid cell values - bool m_own_grid_cell_values; - wxSheetValueProviderBase *m_rowLabelValues; // row label values - bool m_own_row_label_values; - wxSheetValueProviderBase *m_colLabelValues; // col label values - bool m_own_col_label_values; + wxSheetValueProviderBase *m_gridCellValues; // grid cell values + bool m_own_grid_cell_values; + wxSheetValueProviderBase *m_rowLabelValues; // row label values + bool m_own_row_label_values; + wxSheetValueProviderBase *m_colLabelValues; // col label values + bool m_own_col_label_values; - wxString m_cornerLabelValue; // single corner label value + wxString m_cornerLabelValue; // single corner label value - wxSheetSelection* m_spannedCells; // spanned blocks - bool m_own_spanned_cells; + wxSheetSelection *m_spannedCells; // spanned blocks + bool m_own_spanned_cells; - DECLARE_ABSTRACT_CLASS(wxSheetTable) - DECLARE_NO_COPY_CLASS(wxSheetTable) + DECLARE_ABSTRACT_CLASS(wxSheetTable) + DECLARE_NO_COPY_CLASS(wxSheetTable) }; -#endif // __WX_SHEETTBL_H__ +#endif // __WX_SHEETTBL_H__ diff --git a/src/labenski/include/wx/wxthings/block.h b/src/labenski/include/wx/wxthings/block.h index e88631854..c934a43ff 100644 --- a/src/labenski/include/wx/wxthings/block.h +++ b/src/labenski/include/wx/wxthings/block.h @@ -13,10 +13,10 @@ #include "wx/geometry.h" #include "wx/wxthings/thingdef.h" -//#define USE_wxRANGE +// #define USE_wxRANGE #ifdef USE_wxRANGE - #include "wx/wxthings/range.h" +#include "wx/wxthings/range.h" #endif // Note: Why are these not just wxRect2DXXX with m_x and m_width? @@ -46,14 +46,13 @@ WXDLLIMPEXP_DATA_THINGS(extern const wxBlockDouble) wxEmptyBlockDouble; // wxBlockXXX sorting functions //============================================================================= -enum wxBlockSort_Type -{ - wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT, - wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT, - wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT, - wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT, - wxBLOCKSORT_SMALLEST_TO_LARGEST, - wxBLOCKSORT_LARGEST_TO_SMALLEST +enum wxBlockSort_Type { + wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT, + wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT, + wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT, + wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT, + wxBLOCKSORT_SMALLEST_TO_LARGEST, + wxBLOCKSORT_LARGEST_TO_SMALLEST }; // functions to sort an array of blocks from any corner @@ -68,218 +67,258 @@ extern void wxArrayBlockDoubleSort(wxArrayBlockDouble &blocks, // other wxBlockInts //============================================================================= -class WXDLLIMPEXP_THINGS wxBlockInt -{ +class WXDLLIMPEXP_THINGS wxBlockInt { public: - inline wxBlockInt(wxInt32 x1=0, wxInt32 y1=0, wxInt32 x2=0, wxInt32 y2=0) : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2) {} - inline wxBlockInt(const wxRect2DInt &rect) : m_x1(rect.m_x), m_y1(rect.m_y), m_x2(rect.GetRight()), m_y2(rect.GetBottom()) {} - - inline wxInt32 GetLeft() const { return m_x1; } - inline wxInt32 GetRight() const { return m_x2; } - inline wxInt32 GetTop() const { return m_y1; } - inline wxInt32 GetBottom() const { return m_y2; } - - inline wxInt32 GetWidth() const { return m_x2 - m_x1 + 1; } - inline wxInt32 GetHeight() const { return m_y2 - m_y1 + 1; } - - inline wxPoint2DInt GetLeftTop() const { return wxPoint2DInt(m_x1, m_y1); } - inline wxPoint2DInt GetLeftBottom() const { return wxPoint2DInt(m_x1, m_y2); } - inline wxPoint2DInt GetRightTop() const { return wxPoint2DInt(m_x2, m_y1); } - inline wxPoint2DInt GetRightBottom() const { return wxPoint2DInt(m_x2, m_y2); } - - inline wxRect2DInt GetRect2DInt() const { return wxRect2DInt(m_x1, m_y1, m_x2-m_x1+1, m_y2-m_y1+1); } - inline void SetRect2DInt(const wxRect2DInt &r) { m_x1=r.m_x; m_y1=r.m_y, m_x2=r.GetRight(); m_y2=r.GetBottom(); } - - inline bool Contains( wxInt32 x, wxInt32 y ) const - { return ((x >= m_x1) && (x <= m_x2) && (y >= m_y1) && (y <= m_y2)); } - inline bool Contains( const wxPoint2DInt &pt ) const { return Contains(pt.m_x, pt.m_y); } - inline bool Contains( const wxBlockInt &b ) const - { return ((m_x1 <= b.m_x1) && (b.m_x2 <= m_x2) && (m_y1 <= b.m_y1) && (b.m_y2 <= m_y2)); } - - inline bool Intersects( const wxBlockInt &b ) const - { return (wxMax(m_x1, b.m_x1)<=wxMin(m_x2, b.m_x2)) && (wxMax(m_y1, b.m_y1)<=wxMin(m_y2, b.m_y2)); } - inline void Intersect( const wxBlockInt &otherBlock ) { Intersect( *this, otherBlock, this ); } - inline void Intersect( const wxBlockInt &src1 , const wxBlockInt &src2 , wxBlockInt *dest ) const - { - dest->m_x1 = wxMax(src1.m_x1, src2.m_x1); - dest->m_x2 = wxMin(src1.m_x2, src2.m_x2); - dest->m_y1 = wxMax(src1.m_y1, src2.m_y1); - dest->m_y2 = wxMin(src1.m_y2, src2.m_y2); + inline wxBlockInt(wxInt32 x1 = 0, wxInt32 y1 = 0, wxInt32 x2 = 0, wxInt32 y2 = 0) + : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2) + { + } + inline wxBlockInt(const wxRect2DInt &rect) + : m_x1(rect.m_x), m_y1(rect.m_y), m_x2(rect.GetRight()), m_y2(rect.GetBottom()) + { + } + + inline wxInt32 GetLeft() const { return m_x1; } + inline wxInt32 GetRight() const { return m_x2; } + inline wxInt32 GetTop() const { return m_y1; } + inline wxInt32 GetBottom() const { return m_y2; } + + inline wxInt32 GetWidth() const { return m_x2 - m_x1 + 1; } + inline wxInt32 GetHeight() const { return m_y2 - m_y1 + 1; } + + inline wxPoint2DInt GetLeftTop() const { return wxPoint2DInt(m_x1, m_y1); } + inline wxPoint2DInt GetLeftBottom() const { return wxPoint2DInt(m_x1, m_y2); } + inline wxPoint2DInt GetRightTop() const { return wxPoint2DInt(m_x2, m_y1); } + inline wxPoint2DInt GetRightBottom() const { return wxPoint2DInt(m_x2, m_y2); } + + inline wxRect2DInt GetRect2DInt() const + { + return wxRect2DInt(m_x1, m_y1, m_x2 - m_x1 + 1, m_y2 - m_y1 + 1); + } + inline void SetRect2DInt(const wxRect2DInt &r) + { + m_x1 = r.m_x; + m_y1 = r.m_y, m_x2 = r.GetRight(); + m_y2 = r.GetBottom(); + } + + inline bool Contains(wxInt32 x, wxInt32 y) const + { + return ((x >= m_x1) && (x <= m_x2) && (y >= m_y1) && (y <= m_y2)); + } + inline bool Contains(const wxPoint2DInt &pt) const { return Contains(pt.m_x, pt.m_y); } + inline bool Contains(const wxBlockInt &b) const + { + return ((m_x1 <= b.m_x1) && (b.m_x2 <= m_x2) && (m_y1 <= b.m_y1) && (b.m_y2 <= m_y2)); + } + + inline bool Intersects(const wxBlockInt &b) const + { + return (wxMax(m_x1, b.m_x1) <= wxMin(m_x2, b.m_x2)) && + (wxMax(m_y1, b.m_y1) <= wxMin(m_y2, b.m_y2)); + } + inline void Intersect(const wxBlockInt &otherBlock) { Intersect(*this, otherBlock, this); } + inline void Intersect(const wxBlockInt &src1, const wxBlockInt &src2, wxBlockInt *dest) const + { + dest->m_x1 = wxMax(src1.m_x1, src2.m_x1); + dest->m_x2 = wxMin(src1.m_x2, src2.m_x2); + dest->m_y1 = wxMax(src1.m_y1, src2.m_y1); + dest->m_y2 = wxMin(src1.m_y2, src2.m_y2); + } + + inline void Union(const wxBlockInt &otherBlock) { Union(*this, otherBlock, this); } + inline void Union(const wxBlockInt &src1, const wxBlockInt &src2, wxBlockInt *dest) const + { + dest->m_x1 = wxMin(src1.m_x1, src2.m_x1); + dest->m_x2 = wxMax(src1.m_x2, src2.m_x2); + dest->m_y1 = wxMin(src1.m_y1, src2.m_y1); + dest->m_y2 = wxMax(src1.m_y2, src2.m_y2); + } + + // is this block larger than input block, return 1 = larger, 0 = equal, -1 = smaller + int IsLarger(const wxBlockInt &b) const + { + wxInt32 width = m_x2 - m_x1 + 1, height = m_y2 - m_y1 + 1, b_width = b.m_x2 - b.m_x1 + 1, + b_height = b.m_y2 - b.m_y1 + 1; + + if ((width <= 0) || (height <= 0)) { + return (b_width > 0) && (b_height > 0) ? -1 : 0; } - - inline void Union( const wxBlockInt &otherBlock ) { Union(*this, otherBlock, this); } - inline void Union( const wxBlockInt &src1, const wxBlockInt &src2, wxBlockInt *dest ) const - { - dest->m_x1 = wxMin(src1.m_x1, src2.m_x1); - dest->m_x2 = wxMax(src1.m_x2, src2.m_x2); - dest->m_y1 = wxMin(src1.m_y1, src2.m_y1); - dest->m_y2 = wxMax(src1.m_y2, src2.m_y2); - } - - // is this block larger than input block, return 1 = larger, 0 = equal, -1 = smaller - int IsLarger(const wxBlockInt &b) const - { - wxInt32 width = m_x2 - m_x1 + 1, - height = m_y2 - m_y1 + 1, - b_width = b.m_x2 - b.m_x1 + 1, - b_height = b.m_y2 - b.m_y1 + 1; - - if ((width <= 0) || (height <= 0)) - return (b_width > 0) && (b_height > 0) ? -1 : 0; - if ((b_width <= 0) || (b_height <= 0)) - return (width > 0) && (height > 0) ? 1 : 0; - - wxDouble w_bw = wxDouble(width)/b_width, - bh_h = wxDouble(b_height)/height; - return (w_bw == bh_h) ? 0 : ((w_bw > bh_h) ? 1 : -1); + if ((b_width <= 0) || (b_height <= 0)) { + return (width > 0) && (height > 0) ? 1 : 0; } - bool IsEmpty() const { return (m_x1 > m_x2) || (m_y1 > m_y2); } - - // Unlike Intersects this also includes just touching the other block - bool Touches(const wxBlockInt &block) const; - - // Try to combine these blocks, they must touch and fit to make a single larger block - // this block is expanded if possible - bool Combine(const wxBlockInt &block); - - // test combining the input block with this one, returning the - // remainder of block in top, bottom, left, right - each may be IsEmpty() - // returns false if blocks don't touch or this block already contains block - // |---------------------------| - // | top | - // |---------------------------| - // | left |block| right | - // |---------------------------| - // | bottom | - // |---------------------------| - bool Combine( const wxBlockInt &block, - wxBlockInt &top, wxBlockInt &bottom, - wxBlockInt &left, wxBlockInt &right) const; - - // test removal of a portion or all of this contained in block returning the - // remainder in top, bottom, left, right - each may be IsEmpty() - // returns false if nothing to delete, this cell is not changed - bool Delete(const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, - wxBlockInt &left, wxBlockInt &right) const; - - // operators - inline bool operator == (const wxBlockInt& b) - { return (m_x1==b.m_x1) && (m_y1==b.m_y1) && (m_x2==b.m_x2) && (m_y2==b.m_y2); } - inline bool operator != (const wxBlockInt& b) - { return !(*this == b); } - - wxInt32 m_x1, m_y1, m_x2, m_y2; + wxDouble w_bw = wxDouble(width) / b_width, bh_h = wxDouble(b_height) / height; + return (w_bw == bh_h) ? 0 : ((w_bw > bh_h) ? 1 : -1); + } + + bool IsEmpty() const { return (m_x1 > m_x2) || (m_y1 > m_y2); } + + // Unlike Intersects this also includes just touching the other block + bool Touches(const wxBlockInt &block) const; + + // Try to combine these blocks, they must touch and fit to make a single larger block + // this block is expanded if possible + bool Combine(const wxBlockInt &block); + + // test combining the input block with this one, returning the + // remainder of block in top, bottom, left, right - each may be IsEmpty() + // returns false if blocks don't touch or this block already contains block + // |---------------------------| + // | top | + // |---------------------------| + // | left |block| right | + // |---------------------------| + // | bottom | + // |---------------------------| + bool Combine(const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, wxBlockInt &left, + wxBlockInt &right) const; + + // test removal of a portion or all of this contained in block returning the + // remainder in top, bottom, left, right - each may be IsEmpty() + // returns false if nothing to delete, this cell is not changed + bool Delete(const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, wxBlockInt &left, + wxBlockInt &right) const; + + // operators + inline bool operator==(const wxBlockInt &b) + { + return (m_x1 == b.m_x1) && (m_y1 == b.m_y1) && (m_x2 == b.m_x2) && (m_y2 == b.m_y2); + } + inline bool operator!=(const wxBlockInt &b) { return !(*this == b); } + + wxInt32 m_x1, m_y1, m_x2, m_y2; }; //============================================================================= // wxBlockDouble //============================================================================= -class WXDLLIMPEXP_THINGS wxBlockDouble -{ +class WXDLLIMPEXP_THINGS wxBlockDouble { public: - inline wxBlockDouble(wxDouble x1=0, wxDouble y1=0, wxDouble x2=0, wxDouble y2=0) - : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2) {} - inline wxBlockDouble(const wxRect2DDouble &rect) - { m_x1=rect.m_x; m_y1=rect.m_y; m_x2=rect.GetRight(); m_y2=rect.GetBottom(); } - - inline wxDouble GetLeft() const { return m_x1; } - inline wxDouble GetRight() const { return m_x2; } - inline wxDouble GetTop() const { return m_y1; } - inline wxDouble GetBottom() const { return m_y2; } - - inline wxDouble GetWidth() const { return m_x2 - m_x1; } - inline wxDouble GetHeight() const { return m_y2 - m_y1; } - - inline wxPoint2DDouble GetLeftTop() const { return wxPoint2DDouble(m_x1, m_y1); } - inline wxPoint2DDouble GetLeftBottom() const { return wxPoint2DDouble(m_x1, m_y2); } - inline wxPoint2DDouble GetRightTop() const { return wxPoint2DDouble(m_x2, m_y1); } - inline wxPoint2DDouble GetRightBottom() const { return wxPoint2DDouble(m_x2, m_y2); } - - inline wxRect2DDouble GetRect2DDouble() const { return wxRect2DDouble(m_x1, m_y1, m_x2-m_x1, m_y2-m_y1); } - inline void SetRect2DDouble(const wxRect2DDouble &r) { m_x1=r.m_x; m_y1=r.m_y, m_x2=r.GetRight(); m_y2=r.GetBottom(); } - - inline bool Contains( wxDouble x, wxDouble y ) const - { return ((x >= m_x1) && (x <= m_x2) && (y >= m_y1) && (y <= m_y2)); } - inline bool Contains( const wxPoint2DDouble &pt ) const { return Contains(pt.m_x, pt.m_y); } - inline bool Contains( const wxBlockDouble &b ) const - { return ((m_x1 <= b.m_x1) && (b.m_x2 <= m_x2) && (m_y1 <= b.m_y1) && (b.m_y2 <= m_y2)); } - - inline bool Intersects( const wxBlockDouble &b ) const - { return (wxMax(m_x1, b.m_x1)m_x1 = wxMax(src1.m_x1, src2.m_x1); - dest->m_x2 = wxMin(src1.m_x2, src2.m_x2); - dest->m_y1 = wxMax(src1.m_y1, src2.m_y1); - dest->m_y2 = wxMin(src1.m_y2, src2.m_y2); + inline wxBlockDouble(wxDouble x1 = 0, wxDouble y1 = 0, wxDouble x2 = 0, wxDouble y2 = 0) + : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2) + { + } + inline wxBlockDouble(const wxRect2DDouble &rect) + { + m_x1 = rect.m_x; + m_y1 = rect.m_y; + m_x2 = rect.GetRight(); + m_y2 = rect.GetBottom(); + } + + inline wxDouble GetLeft() const { return m_x1; } + inline wxDouble GetRight() const { return m_x2; } + inline wxDouble GetTop() const { return m_y1; } + inline wxDouble GetBottom() const { return m_y2; } + + inline wxDouble GetWidth() const { return m_x2 - m_x1; } + inline wxDouble GetHeight() const { return m_y2 - m_y1; } + + inline wxPoint2DDouble GetLeftTop() const { return wxPoint2DDouble(m_x1, m_y1); } + inline wxPoint2DDouble GetLeftBottom() const { return wxPoint2DDouble(m_x1, m_y2); } + inline wxPoint2DDouble GetRightTop() const { return wxPoint2DDouble(m_x2, m_y1); } + inline wxPoint2DDouble GetRightBottom() const { return wxPoint2DDouble(m_x2, m_y2); } + + inline wxRect2DDouble GetRect2DDouble() const + { + return wxRect2DDouble(m_x1, m_y1, m_x2 - m_x1, m_y2 - m_y1); + } + inline void SetRect2DDouble(const wxRect2DDouble &r) + { + m_x1 = r.m_x; + m_y1 = r.m_y, m_x2 = r.GetRight(); + m_y2 = r.GetBottom(); + } + + inline bool Contains(wxDouble x, wxDouble y) const + { + return ((x >= m_x1) && (x <= m_x2) && (y >= m_y1) && (y <= m_y2)); + } + inline bool Contains(const wxPoint2DDouble &pt) const { return Contains(pt.m_x, pt.m_y); } + inline bool Contains(const wxBlockDouble &b) const + { + return ((m_x1 <= b.m_x1) && (b.m_x2 <= m_x2) && (m_y1 <= b.m_y1) && (b.m_y2 <= m_y2)); + } + + inline bool Intersects(const wxBlockDouble &b) const + { + return (wxMax(m_x1, b.m_x1) < wxMin(m_x2, b.m_x2)) && + (wxMax(m_y1, b.m_y1) < wxMin(m_y2, b.m_y2)); + } + inline void Intersect(const wxBlockDouble &otherBlock) { Intersect(*this, otherBlock, this); } + inline void Intersect(const wxBlockDouble &src1, const wxBlockDouble &src2, + wxBlockDouble *dest) const + { + dest->m_x1 = wxMax(src1.m_x1, src2.m_x1); + dest->m_x2 = wxMin(src1.m_x2, src2.m_x2); + dest->m_y1 = wxMax(src1.m_y1, src2.m_y1); + dest->m_y2 = wxMin(src1.m_y2, src2.m_y2); + } + + inline void Union(const wxBlockDouble &otherBlock) { Union(*this, otherBlock, this); } + inline void Union(const wxBlockDouble &src1, const wxBlockDouble &src2, + wxBlockDouble *dest) const + { + dest->m_x1 = wxMin(src1.m_x1, src2.m_x1); + dest->m_x2 = wxMax(src1.m_x2, src2.m_x2); + dest->m_y1 = wxMin(src1.m_y1, src2.m_y1); + dest->m_y2 = wxMax(src1.m_y2, src2.m_y2); + } + + // is this block larger than input block, return 1 - larger, 0 = equal, -1 smaller + int IsLarger(const wxBlockDouble &b) const + { + wxDouble width = m_x2 - m_x1, height = m_y2 - m_y1, b_width = b.m_x2 - b.m_x1, + b_height = b.m_y2 - b.m_y1; + + if ((width <= 0) || (height <= 0)) { + return (b_width > 0) && (b_height > 0) ? -1 : 0; } - - inline void Union( const wxBlockDouble &otherBlock ) { Union( *this, otherBlock, this ); } - inline void Union( const wxBlockDouble &src1, const wxBlockDouble &src2, wxBlockDouble *dest ) const - { - dest->m_x1 = wxMin(src1.m_x1, src2.m_x1); - dest->m_x2 = wxMax(src1.m_x2, src2.m_x2); - dest->m_y1 = wxMin(src1.m_y1, src2.m_y1); - dest->m_y2 = wxMax(src1.m_y2, src2.m_y2); + if ((b_width <= 0) || (b_height <= 0)) { + return (width > 0) && (height > 0) ? 1 : 0; } - // is this block larger than input block, return 1 - larger, 0 = equal, -1 smaller - int IsLarger(const wxBlockDouble &b) const - { - wxDouble width = m_x2 - m_x1, - height = m_y2 - m_y1, - b_width = b.m_x2 - b.m_x1, - b_height = b.m_y2 - b.m_y1; - - if ((width <= 0) || (height <= 0)) - return (b_width > 0) && (b_height > 0) ? -1 : 0; - if ((b_width <= 0) || (b_height <= 0)) - return (width > 0) && (height > 0) ? 1 : 0; - - wxDouble w_bw = width/b_width, - bh_h = b_height/height; - return (w_bw == bh_h) ? 0 : ((w_bw > bh_h) ? 1 : -1); - } - inline bool IsEmpty() const { return (m_x1 > m_x2) || (m_y1 > m_y2); } - - // Unlike Intersects this also includes just touching the other block - bool Touches(const wxBlockDouble &block) const; - - // Try to combine these blocks, they must touch and fit to make a single larger block - // this block is expanded if possible - bool Combine(const wxBlockDouble &block); - - // test combining the input block with this one, returning the - // remainder of block in top, bottom, left, right - each may be IsEmpty() - // returns false if blocks don't touch or this block already contains block - // |---------------------------| - // | top | - // |---------------------------| - // | left |block| right | - // |---------------------------| - // | bottom | - // |---------------------------| - bool Combine( const wxBlockDouble &block, - wxBlockDouble &top, wxBlockDouble &bottom, - wxBlockDouble &left, wxBlockDouble &right) const; - - // test removal of a portion or all of this contained in block returning the - // remainder in top, bottom, left, right - each may be IsEmpty() - // returns false if nothing to delete, this cell is not changed - bool Delete( const wxBlockDouble &block, - wxBlockDouble &top, wxBlockDouble &bottom, - wxBlockDouble &left, wxBlockDouble &right) const; - - // operators - inline bool operator == (const wxBlockDouble& b) - { return (m_x1==b.m_x1) && (m_y1==b.m_y1) && (m_x2==b.m_x2) && (m_y2==b.m_y2); } - inline bool operator != (const wxBlockDouble& b) - { return !(*this == b); } - - wxDouble m_x1, m_y1, m_x2, m_y2; + wxDouble w_bw = width / b_width, bh_h = b_height / height; + return (w_bw == bh_h) ? 0 : ((w_bw > bh_h) ? 1 : -1); + } + inline bool IsEmpty() const { return (m_x1 > m_x2) || (m_y1 > m_y2); } + + // Unlike Intersects this also includes just touching the other block + bool Touches(const wxBlockDouble &block) const; + + // Try to combine these blocks, they must touch and fit to make a single larger block + // this block is expanded if possible + bool Combine(const wxBlockDouble &block); + + // test combining the input block with this one, returning the + // remainder of block in top, bottom, left, right - each may be IsEmpty() + // returns false if blocks don't touch or this block already contains block + // |---------------------------| + // | top | + // |---------------------------| + // | left |block| right | + // |---------------------------| + // | bottom | + // |---------------------------| + bool Combine(const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, + wxBlockDouble &left, wxBlockDouble &right) const; + + // test removal of a portion or all of this contained in block returning the + // remainder in top, bottom, left, right - each may be IsEmpty() + // returns false if nothing to delete, this cell is not changed + bool Delete(const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, + wxBlockDouble &left, wxBlockDouble &right) const; + + // operators + inline bool operator==(const wxBlockDouble &b) + { + return (m_x1 == b.m_x1) && (m_y1 == b.m_y1) && (m_x2 == b.m_x2) && (m_y2 == b.m_y2); + } + inline bool operator!=(const wxBlockDouble &b) { return !(*this == b); } + + wxDouble m_x1, m_y1, m_x2, m_y2; }; //============================================================================= @@ -287,83 +326,89 @@ class WXDLLIMPEXP_THINGS wxBlockDouble // blocks never overlap each other //============================================================================= -class WXDLLIMPEXP_THINGS wxBlockIntSelection -{ -public : - wxBlockIntSelection(wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) - : m_sort(sort_type) {} - wxBlockIntSelection(const wxBlockIntSelection &blocks, - wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) - : m_sort(sort_type) { Copy(blocks); } - - // Make a full copy of the source - void Copy(const wxBlockIntSelection &source) - { - m_blocks.Clear(); - WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); - m_sort = source.GetSortType(); - } - - inline int GetCount() const { return m_blocks.GetCount(); } - - inline void Clear() { m_blocks.Clear(); } - - wxArrayBlockInt GetBlockArray() const { return m_blocks; } +class WXDLLIMPEXP_THINGS wxBlockIntSelection { +public: + wxBlockIntSelection(wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) + : m_sort(sort_type) + { + } + wxBlockIntSelection(const wxBlockIntSelection &blocks, + wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) + : m_sort(sort_type) + { + Copy(blocks); + } + + // Make a full copy of the source + void Copy(const wxBlockIntSelection &source) + { + m_blocks.Clear(); + WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); + m_sort = source.GetSortType(); + } + + inline int GetCount() const { return m_blocks.GetCount(); } + + inline void Clear() { m_blocks.Clear(); } + + wxArrayBlockInt GetBlockArray() const { return m_blocks; } #ifdef USE_wxRANGE - // Get an array of ranges cutting though these blocks - wxArrayRangeInt GetBlockCol(int col) const; - wxArrayRangeInt GetBlockRow(int row) const; + // Get an array of ranges cutting though these blocks + wxArrayRangeInt GetBlockCol(int col) const; + wxArrayRangeInt GetBlockRow(int row) const; #endif - wxBlockInt GetBlock( int index ) const; - inline wxBlockInt Item( int index ) const { return GetBlock(index); } + wxBlockInt GetBlock(int index) const; + inline wxBlockInt Item(int index) const { return GetBlock(index); } - // Get a block that bounds the selection - wxBlockInt GetBoundingBlock() const; + // Get a block that bounds the selection + wxBlockInt GetBoundingBlock() const; - // do any of the blocks contains elements - inline bool Contains( int x, int y ) const { return Index(x,y) != wxNOT_FOUND; } - inline bool Contains( const wxPoint2DInt &pt ) const { return Index(pt) != wxNOT_FOUND; } - inline bool Contains( const wxBlockInt &b ) const { return Index(b) != wxNOT_FOUND; } + // do any of the blocks contains elements + inline bool Contains(int x, int y) const { return Index(x, y) != wxNOT_FOUND; } + inline bool Contains(const wxPoint2DInt &pt) const { return Index(pt) != wxNOT_FOUND; } + inline bool Contains(const wxBlockInt &b) const { return Index(b) != wxNOT_FOUND; } - // what is the index of a block that contains element - int Index( int x, int y ) const; - inline int Index( const wxPoint2DInt &pt ) const { return Index(pt.m_x, pt.m_y); } - int Index( const wxBlockInt &b ) const; + // what is the index of a block that contains element + int Index(int x, int y) const; + inline int Index(const wxPoint2DInt &pt) const { return Index(pt.m_x, pt.m_y); } + int Index(const wxBlockInt &b) const; - // Sorts the blocks according to the wxBlockIntSort_Type - void Sort(wxBlockSort_Type type = wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT); - wxBlockSort_Type GetSortType() const { return m_sort; } + // Sorts the blocks according to the wxBlockIntSort_Type + void Sort(wxBlockSort_Type type = wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT); + wxBlockSort_Type GetSortType() const { return m_sort; } - // Add the block to the selection, returns false if nothing was done - // use combineNow=false to make quick additions, when done call Minimize() - // addedBlocks (if !NULL) will be filled with the actual changed selections - // by removing the previous selections from the input block - bool SelectBlock( const wxBlockInt &block, bool combineNow=true, wxArrayBlockInt *addedBlocks=NULL); + // Add the block to the selection, returns false if nothing was done + // use combineNow=false to make quick additions, when done call Minimize() + // addedBlocks (if !NULL) will be filled with the actual changed selections + // by removing the previous selections from the input block + bool SelectBlock(const wxBlockInt &block, bool combineNow = true, + wxArrayBlockInt *addedBlocks = NULL); - // Remove the block to the selection, return false if nothing was done - // use combineNow=false to make quick additions, when done call Minimize() - bool DeselectBlock( const wxBlockInt &block, bool combineNow=true); + // Remove the block to the selection, return false if nothing was done + // use combineNow=false to make quick additions, when done call Minimize() + bool DeselectBlock(const wxBlockInt &block, bool combineNow = true); - // Try to combine the blocks if possible, returns if anything was done - // only need to call this if you've called (De)SelectBlock(..., false) - bool Minimize(); + // Try to combine the blocks if possible, returns if anything was done + // only need to call this if you've called (De)SelectBlock(..., false) + bool Minimize(); - // Operators - inline wxBlockInt operator[](int index) const { return GetBlock(index); } + // Operators + inline wxBlockInt operator[](int index) const { return GetBlock(index); } - //wxBlockIntSelection& operator = (const wxBlockIntSelection& other) { Copy(other); return *this; } + // wxBlockIntSelection& operator = (const wxBlockIntSelection& other) { Copy(other); return + // *this; } - // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array - // sort top_left_bottom_right first (internal use) - static bool DoMinimize( wxArrayBlockInt &blocks ); - // DoMinimize calls this internally - static bool DoDoMinimize( wxArrayBlockInt &blocks ); + // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array + // sort top_left_bottom_right first (internal use) + static bool DoMinimize(wxArrayBlockInt &blocks); + // DoMinimize calls this internally + static bool DoDoMinimize(wxArrayBlockInt &blocks); -protected : - wxArrayBlockInt m_blocks; - wxBlockSort_Type m_sort; +protected: + wxArrayBlockInt m_blocks; + wxBlockSort_Type m_sort; }; //============================================================================= @@ -371,142 +416,151 @@ protected : // blocks never overlap each other //============================================================================= -class WXDLLIMPEXP_THINGS wxBlockDoubleSelection -{ -public : - wxBlockDoubleSelection(wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) - : m_sort(sort_type) {} - wxBlockDoubleSelection(const wxBlockDoubleSelection &blocks, - wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) - : m_sort(sort_type) { Copy(blocks); } - - // Make a full copy of the source - void Copy(const wxBlockDoubleSelection &source) - { - m_blocks.Clear(); - WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); - m_sort = source.GetSortType(); - } - - inline int GetCount() const { return m_blocks.GetCount(); } - - inline void Clear() { m_blocks.Clear(); } - - wxArrayBlockDouble GetBlockArray() const { return m_blocks; } +class WXDLLIMPEXP_THINGS wxBlockDoubleSelection { +public: + wxBlockDoubleSelection(wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) + : m_sort(sort_type) + { + } + wxBlockDoubleSelection(const wxBlockDoubleSelection &blocks, + wxBlockSort_Type sort_type = wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT) + : m_sort(sort_type) + { + Copy(blocks); + } + + // Make a full copy of the source + void Copy(const wxBlockDoubleSelection &source) + { + m_blocks.Clear(); + WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); + m_sort = source.GetSortType(); + } + + inline int GetCount() const { return m_blocks.GetCount(); } + + inline void Clear() { m_blocks.Clear(); } + + wxArrayBlockDouble GetBlockArray() const { return m_blocks; } #ifdef USE_wxRANGE - // Get an array of ranges cutting though these blocks - wxArrayRangeDouble GetBlockCol(wxDouble col) const; - wxArrayRangeDouble GetBlockRow(wxDouble row) const; + // Get an array of ranges cutting though these blocks + wxArrayRangeDouble GetBlockCol(wxDouble col) const; + wxArrayRangeDouble GetBlockRow(wxDouble row) const; #endif - wxBlockDouble GetBlock( int index ) const; - inline wxBlockDouble Item( int index ) const { return GetBlock(index); } + wxBlockDouble GetBlock(int index) const; + inline wxBlockDouble Item(int index) const { return GetBlock(index); } - // Get a block that bounds the selection - wxBlockDouble GetBoundingBlock() const; + // Get a block that bounds the selection + wxBlockDouble GetBoundingBlock() const; - // do any of the blocks contains elements - inline bool Contains( wxDouble x, wxDouble y ) const { return Index(wxPoint2DDouble(x,y)) != wxNOT_FOUND; } - inline bool Contains( const wxPoint2DInt &pt ) const { return Index(pt) != wxNOT_FOUND; } - inline bool Contains( const wxBlockDouble &b ) const { return Index(b) != wxNOT_FOUND; } + // do any of the blocks contains elements + inline bool Contains(wxDouble x, wxDouble y) const + { + return Index(wxPoint2DDouble(x, y)) != wxNOT_FOUND; + } + inline bool Contains(const wxPoint2DInt &pt) const { return Index(pt) != wxNOT_FOUND; } + inline bool Contains(const wxBlockDouble &b) const { return Index(b) != wxNOT_FOUND; } - // what is the index of a block that contains element - int Index( wxDouble x, wxDouble y ) const; - inline int Index( const wxPoint2DDouble &pt ) const { return Index(pt.m_x, pt.m_y); } - int Index( const wxBlockDouble &b ) const; + // what is the index of a block that contains element + int Index(wxDouble x, wxDouble y) const; + inline int Index(const wxPoint2DDouble &pt) const { return Index(pt.m_x, pt.m_y); } + int Index(const wxBlockDouble &b) const; - // Sorts the blocks according to the wxBlockIntSort_Type - void Sort(wxBlockSort_Type type = wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT); - wxBlockSort_Type GetSortType() const { return m_sort; } + // Sorts the blocks according to the wxBlockIntSort_Type + void Sort(wxBlockSort_Type type = wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT); + wxBlockSort_Type GetSortType() const { return m_sort; } - // Add the block to the selection, returns false if nothing was done - // use combineNow=false to make quick additions, when done call Minimize() - bool SelectBlock( const wxBlockDouble &block, bool combineNow=true); + // Add the block to the selection, returns false if nothing was done + // use combineNow=false to make quick additions, when done call Minimize() + bool SelectBlock(const wxBlockDouble &block, bool combineNow = true); - // Remove the block to the selection, return false if nothing was done - // use combineNow=false to make quick additions, when done call Minimize() - bool DeselectBlock( const wxBlockDouble &block, bool combineNow=true); + // Remove the block to the selection, return false if nothing was done + // use combineNow=false to make quick additions, when done call Minimize() + bool DeselectBlock(const wxBlockDouble &block, bool combineNow = true); - // Try to combine the blocks if possible, returns if anything was done - // only need to call this if you've called (De)SelectBlock(..., false) - bool Minimize(); + // Try to combine the blocks if possible, returns if anything was done + // only need to call this if you've called (De)SelectBlock(..., false) + bool Minimize(); - // Operators - inline wxBlockDouble operator[](int index) const { return GetBlock(index); } + // Operators + inline wxBlockDouble operator[](int index) const { return GetBlock(index); } - //wxBlockIntSelection& operator = (const wxBlockIntSelection& other) { Copy(other); return *this; } + // wxBlockIntSelection& operator = (const wxBlockIntSelection& other) { Copy(other); return + // *this; } - // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array - // sort top_left_bottom_right first (internal use) - static bool DoMinimize( wxArrayBlockDouble &blocks ); - // DoMinimize calls this internally - static bool DoDoMinimize( wxArrayBlockDouble &blocks ); + // generic routine using if (b1.Combine(b2)) remove b2 to cleanup array + // sort top_left_bottom_right first (internal use) + static bool DoMinimize(wxArrayBlockDouble &blocks); + // DoMinimize calls this internally + static bool DoDoMinimize(wxArrayBlockDouble &blocks); -protected : - wxArrayBlockDouble m_blocks; - wxBlockSort_Type m_sort; +protected: + wxArrayBlockDouble m_blocks; + wxBlockSort_Type m_sort; }; //============================================================================= // wxBlockIntSelectionIterator - iterates through a wxBlockIntSelection //============================================================================= -enum wxBISI_Type -{ - wxBISI_POINT, // wxBlockIntSelectionIterator::SetType go point by point - wxBISI_BLOCK // go block by block +enum wxBISI_Type { + wxBISI_POINT, // wxBlockIntSelectionIterator::SetType go point by point + wxBISI_BLOCK // go block by block }; -class WXDLLIMPEXP_THINGS wxBlockIntSelectionIterator -{ -public : - wxBlockIntSelectionIterator( const wxBlockIntSelection &sel, wxBISI_Type type = wxBISI_POINT ); - wxBlockIntSelectionIterator( const wxArrayBlockInt &blocks, wxBISI_Type type = wxBISI_POINT ); - - // resets the iterating to start at the beginning - void Reset(); - // Set the method to get the blocks, either point by point or each whole block - // also resets the iteration to the beginning - void SetType( wxBISI_Type type ) { m_type = type; Reset(); } - wxBISI_Type GetType() const { return m_type; } - - // Get next selection, returns false if at end (only valid for wxBISI_point) - bool GetNext(wxPoint2DInt &pt); - // Get next selection, returns false if at end (only valid for wxBISI_block) - bool GetNext(wxBlockInt &block); - - // checks if this row and col are in this selection - bool IsInSelection(const wxPoint2DInt &pt) const; - inline bool IsInSelection( int x, int y ) const { return IsInSelection(wxPoint2DInt(x,y)); } - -protected : - wxBISI_Type m_type; - int m_block_index; - wxPoint2DInt m_pt; - wxArrayBlockInt m_blocks; +class WXDLLIMPEXP_THINGS wxBlockIntSelectionIterator { +public: + wxBlockIntSelectionIterator(const wxBlockIntSelection &sel, wxBISI_Type type = wxBISI_POINT); + wxBlockIntSelectionIterator(const wxArrayBlockInt &blocks, wxBISI_Type type = wxBISI_POINT); + + // resets the iterating to start at the beginning + void Reset(); + // Set the method to get the blocks, either point by point or each whole block + // also resets the iteration to the beginning + void SetType(wxBISI_Type type) + { + m_type = type; + Reset(); + } + wxBISI_Type GetType() const { return m_type; } + + // Get next selection, returns false if at end (only valid for wxBISI_point) + bool GetNext(wxPoint2DInt &pt); + // Get next selection, returns false if at end (only valid for wxBISI_block) + bool GetNext(wxBlockInt &block); + + // checks if this row and col are in this selection + bool IsInSelection(const wxPoint2DInt &pt) const; + inline bool IsInSelection(int x, int y) const { return IsInSelection(wxPoint2DInt(x, y)); } + +protected: + wxBISI_Type m_type; + int m_block_index; + wxPoint2DInt m_pt; + wxArrayBlockInt m_blocks; }; //============================================================================= // wxBlockDoubleSelectionIterator - iterates through a wxBlockDoubleSelection //============================================================================= -class WXDLLIMPEXP_THINGS wxBlockDoubleSelectionIterator -{ -public : - wxBlockDoubleSelectionIterator( const wxBlockDoubleSelection &sel ); - wxBlockDoubleSelectionIterator( const wxArrayBlockDouble &blocks ); - - // resets the iterating to start at the beginning - void Reset(); - // Get next selection, returns false if at the end - bool GetNext(wxBlockDouble &block); - // checks if this row and col are in this selection - bool IsInSelection(const wxPoint2DDouble &pt) const; - inline bool IsInSelection( int x, int y ) const { return IsInSelection(wxPoint2DDouble(x,y)); } - -protected : - size_t m_block_index; - wxArrayBlockDouble m_blocks; +class WXDLLIMPEXP_THINGS wxBlockDoubleSelectionIterator { +public: + wxBlockDoubleSelectionIterator(const wxBlockDoubleSelection &sel); + wxBlockDoubleSelectionIterator(const wxArrayBlockDouble &blocks); + + // resets the iterating to start at the beginning + void Reset(); + // Get next selection, returns false if at the end + bool GetNext(wxBlockDouble &block); + // checks if this row and col are in this selection + bool IsInSelection(const wxPoint2DDouble &pt) const; + inline bool IsInSelection(int x, int y) const { return IsInSelection(wxPoint2DDouble(x, y)); } + +protected: + size_t m_block_index; + wxArrayBlockDouble m_blocks; }; #endif // __wxBLOCK_H__ diff --git a/src/labenski/include/wx/wxthings/bmpcombo.h b/src/labenski/include/wx/wxthings/bmpcombo.h index c2b8f0f79..2b54da1f7 100644 --- a/src/labenski/include/wx/wxthings/bmpcombo.h +++ b/src/labenski/include/wx/wxthings/bmpcombo.h @@ -38,182 +38,174 @@ class WXDLLIMPEXP_THINGS wxCustomButton; class WXDLLIMPEXP_THINGS wxBitmapComboPopupChild; class WXDLLIMPEXP_THINGS wxBitmapComboLabel; -enum wxBitmapComboBox_Style -{ - // Position of the labels relative to the bitmaps, use only one - wxBMPCOMBO_LEFT = wxCB_DROPDOWN, - wxBMPCOMBO_RIGHT = wxCB_SIMPLE +enum wxBitmapComboBox_Style { + // Position of the labels relative to the bitmaps, use only one + wxBMPCOMBO_LEFT = wxCB_DROPDOWN, + wxBMPCOMBO_RIGHT = wxCB_SIMPLE }; -class WXDLLIMPEXP_THINGS wxBitmapComboBox : public DropDownBase -{ +class WXDLLIMPEXP_THINGS wxBitmapComboBox : public DropDownBase { public: - wxBitmapComboBox() : DropDownBase() { Init(); } - - // Compatible with a wxComboBox, uses strings only - wxBitmapComboBox(wxWindow *parent, wxWindowID id, - const wxString& value = wxEmptyString, // used only if first choice is !null - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - int n = 0, const wxString choices[] = (const wxString *) NULL, - long style = wxBMPCOMBO_RIGHT, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("wxBitmapComboBox")) - :DropDownBase() - { - Init(); - if ((n > 0) || (!value.IsEmpty())) - { - if ((n > 0) && choices) - { - for (int i=0; i 0) || (!value.IsEmpty())) { + if ((n > 0) && choices) { + for (int i = 0; i < n; i++) { + Append(choices[i], wxNullBitmap); } - Create(parent, id, pos, size, style, val, name); + } + else { + Append(value, wxNullBitmap); + } } - - // Native constructor (only adds first item) you probably want to - // use the largest item first so that the size is correct from the start. - wxBitmapComboBox(wxWindow* parent, wxWindowID id, - const wxString& label, - const wxBitmap& bitmap, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxBMPCOMBO_RIGHT, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("wxBitmapComboBox")) - :DropDownBase() - { - Init(); - Append(label, bitmap); - Create(parent, id, pos, size, style, val, name); - } - - virtual ~wxBitmapComboBox(); - - bool Create(wxWindow* parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxBMPCOMBO_RIGHT, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("wxBitmapComboBox")); - - // Style is either wxBMPCOMBO_LEFT or wxBMPCOMBO_RIGHT - bool SetButtonStyle(long style); - - // Append/Insert an item, either label and bitmap may be empty/null - void Append( const wxString &label, const wxBitmap &bitmap, int count = 1 ); - void Insert( int n, const wxString &label, const wxBitmap &bitmap ); - - // Clear or delete a single or number of items starting from n - void Clear(); - void Delete( int n, int count = 1 ); - - int GetCount() const { return m_labels.GetCount(); } - - int GetSelection() const { return m_selection; } - void SetSelection( int n, bool send_event = false ); - void SetNextSelection(bool foward, bool send_event = false); - - wxString GetLabel( int n ) const; - wxBitmap GetBitmap( int n ) const; - - void SetBitmap(int n, const wxBitmap &bitmap); - void SetLabel(int n, const wxString &label); - void SetItem(int n, const wxString &label, const wxBitmap &bitmap) - { SetLabel(n, label); SetBitmap(n, bitmap); } - - virtual bool SetBackgroundColour(const wxColour &colour); - - virtual void HidePopup(); - - // When adding/deleting many items freeze it and thaw when done - void Freeze() { m_frozen = true; } - void Thaw(); - - // implementation - wxBitmapComboLabel* GetLabelWindow() { return m_labelWin; } - // Get the largest label, bitmap, item=(label+bitmap) size - wxSize GetLabelSize() const { return m_labelSize; } - wxSize GetBitmapSize() const { return m_bitmapSize; } - wxSize GetItemSize() const { return m_itemSize; } - void CalcLabelBitmapPos(int n, const wxSize &area, wxPoint &labelPos, wxPoint &bitmapPos) const; - void CalcLayout(); - void DrawItem(wxDC &dc, int n) const; + Create(parent, id, pos, size, style, val, name); + } + + // Native constructor (only adds first item) you probably want to + // use the largest item first so that the size is correct from the start. + wxBitmapComboBox(wxWindow *parent, wxWindowID id, const wxString &label, const wxBitmap &bitmap, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + long style = wxBMPCOMBO_RIGHT, const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("wxBitmapComboBox")) + : DropDownBase() + { + Init(); + Append(label, bitmap); + Create(parent, id, pos, size, style, val, name); + } + + virtual ~wxBitmapComboBox(); + + bool Create(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, long style = wxBMPCOMBO_RIGHT, + const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("wxBitmapComboBox")); + + // Style is either wxBMPCOMBO_LEFT or wxBMPCOMBO_RIGHT + bool SetButtonStyle(long style); + + // Append/Insert an item, either label and bitmap may be empty/null + void Append(const wxString &label, const wxBitmap &bitmap, int count = 1); + void Insert(int n, const wxString &label, const wxBitmap &bitmap); + + // Clear or delete a single or number of items starting from n + void Clear(); + void Delete(int n, int count = 1); + + int GetCount() const { return m_labels.GetCount(); } + + int GetSelection() const { return m_selection; } + void SetSelection(int n, bool send_event = false); + void SetNextSelection(bool foward, bool send_event = false); + + wxString GetLabel(int n) const; + wxBitmap GetBitmap(int n) const; + + void SetBitmap(int n, const wxBitmap &bitmap); + void SetLabel(int n, const wxString &label); + void SetItem(int n, const wxString &label, const wxBitmap &bitmap) + { + SetLabel(n, label); + SetBitmap(n, bitmap); + } + + virtual bool SetBackgroundColour(const wxColour &colour); + + virtual void HidePopup(); + + // When adding/deleting many items freeze it and thaw when done + void Freeze() { m_frozen = true; } + void Thaw(); + + // implementation + wxBitmapComboLabel *GetLabelWindow() { return m_labelWin; } + // Get the largest label, bitmap, item=(label+bitmap) size + wxSize GetLabelSize() const { return m_labelSize; } + wxSize GetBitmapSize() const { return m_bitmapSize; } + wxSize GetItemSize() const { return m_itemSize; } + void CalcLabelBitmapPos(int n, const wxSize &area, wxPoint &labelPos, wxPoint &bitmapPos) const; + void CalcLayout(); + void DrawItem(wxDC &dc, int n) const; protected: - virtual void DoSetSize(int x, int y, int width, int height, - int sizeFlags = wxSIZE_AUTO); + virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - void OnSize( wxSizeEvent& event ); - virtual wxSize DoGetBestSize() const; + void OnSize(wxSizeEvent &event); + virtual wxSize DoGetBestSize() const; - virtual int DoGetBestDropHeight(int max_height); - virtual bool DoShowPopup(); + virtual int DoGetBestDropHeight(int max_height); + virtual bool DoShowPopup(); - wxBitmapComboLabel *m_labelWin; + wxBitmapComboLabel *m_labelWin; - wxArrayPtrVoid m_bitmaps; // the individual bitmaps - wxArrayString m_labels; // the individual labels + wxArrayPtrVoid m_bitmaps; // the individual bitmaps + wxArrayString m_labels; // the individual labels - wxSize m_labelSize; // the max size of all the labels - wxSize m_bitmapSize; // the max size of all the bitmaps - wxSize m_itemSize; // the max size of all the items + wxSize m_labelSize; // the max size of all the labels + wxSize m_bitmapSize; // the max size of all the bitmaps + wxSize m_itemSize; // the max size of all the items - int m_selection; - int m_win_border; // the wxSUNKEN_BORDER size - long m_label_style; - bool m_frozen; + int m_selection; + int m_win_border; // the wxSUNKEN_BORDER size + long m_label_style; + bool m_frozen; private: - void Init(); - DECLARE_DYNAMIC_CLASS(wxBitmapComboBox) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_DYNAMIC_CLASS(wxBitmapComboBox) + DECLARE_EVENT_TABLE() }; // ========================================================================== // wxBitmapComboLabel - the main "window" to the left of the dropdown button // ========================================================================== -class WXDLLIMPEXP_THINGS wxBitmapComboLabel : public wxWindow -{ +class WXDLLIMPEXP_THINGS wxBitmapComboLabel : public wxWindow { public: - wxBitmapComboLabel(wxBitmapComboBox *parent = NULL, int style = wxSUNKEN_BORDER) - : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style), - m_bmpCombo(parent) {} + wxBitmapComboLabel(wxBitmapComboBox *parent = NULL, int style = wxSUNKEN_BORDER) + : wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style), m_bmpCombo(parent) + { + } protected: - void OnPaint( wxPaintEvent &event ); - void OnChar( wxKeyEvent &event ); + void OnPaint(wxPaintEvent &event); + void OnChar(wxKeyEvent &event); + + wxBitmapComboBox *m_bmpCombo; - wxBitmapComboBox *m_bmpCombo; private: - DECLARE_DYNAMIC_CLASS(wxBitmapComboLabel) - DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxBitmapComboLabel) + DECLARE_EVENT_TABLE() }; // ============================================================================ // wxBitmapComboPopupChild - the child of the popup window // ============================================================================ -class WXDLLIMPEXP_THINGS wxBitmapComboPopupChild : public wxScrolledWindow -{ +class WXDLLIMPEXP_THINGS wxBitmapComboPopupChild : public wxScrolledWindow { public: - wxBitmapComboPopupChild(wxWindow *parent, wxBitmapComboBox *owner); + wxBitmapComboPopupChild(wxWindow *parent, wxBitmapComboBox *owner); - void DrawSelection( int n, wxDC& dc ); + void DrawSelection(int n, wxDC &dc); - void OnMouse( wxMouseEvent &event ); - void OnPaint( wxPaintEvent &event ); - void OnKeyDown( wxKeyEvent &event ); + void OnMouse(wxMouseEvent &event); + void OnPaint(wxPaintEvent &event); + void OnKeyDown(wxKeyEvent &event); - wxBitmapComboBox *m_bmpCombo; - int m_last_selection; + wxBitmapComboBox *m_bmpCombo; + int m_last_selection; private: - DECLARE_EVENT_TABLE() + DECLARE_EVENT_TABLE() }; -#endif // _WX_BMPCOMBO_H_ +#endif // _WX_BMPCOMBO_H_ diff --git a/src/labenski/include/wx/wxthings/dropdown.h b/src/labenski/include/wx/wxthings/dropdown.h index 84b073cb4..43eaea2a8 100644 --- a/src/labenski/include/wx/wxthings/dropdown.h +++ b/src/labenski/include/wx/wxthings/dropdown.h @@ -41,123 +41,113 @@ class WXDLLEXPORT wxTimerEvent; class WXDLLEXPORT wxCustomButton; class WXDLLIMPEXP_THINGS DropDownPopup; -#define DROPDOWN_DROP_WIDTH 14 // these are the default sizes +#define DROPDOWN_DROP_WIDTH 14 // these are the default sizes #define DROPDOWN_DROP_HEIGHT 22 //----------------------------------------------------------------------------- // DropDownBase generic combobox type widget that drops down a DropDownPopup //----------------------------------------------------------------------------- -class WXDLLIMPEXP_THINGS DropDownBase : public wxControl -{ +class WXDLLIMPEXP_THINGS DropDownBase : public wxControl { public: - - DropDownBase() : wxControl() { Init(); } - - DropDownBase( wxWindow *parent, wxWindowID id = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("DropDownBase")) - : wxControl() - { - Init(); - Create(parent, id, pos, size, style, val, name); - } - - virtual ~DropDownBase(); - - bool Create(wxWindow* parent, - wxWindowID id = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("DropDownBase")); - - virtual bool ShowPopup(); - virtual void HidePopup(); - bool IsPopupShown(); - - // implementation - void OnDropButton( wxCommandEvent &event ); - wxCustomButton* GetDropDownButton() { return m_dropdownButton; } - // Get the popup window, NULL when not shown - DropDownPopup* GetPopupWindow() { return m_popupWin; } + DropDownBase() : wxControl() { Init(); } + + DropDownBase(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, long style = 0, + const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("DropDownBase")) + : wxControl() + { + Init(); + Create(parent, id, pos, size, style, val, name); + } + + virtual ~DropDownBase(); + + bool Create(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, long style = 0, + const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("DropDownBase")); + + virtual bool ShowPopup(); + virtual void HidePopup(); + bool IsPopupShown(); + + // implementation + void OnDropButton(wxCommandEvent &event); + wxCustomButton *GetDropDownButton() { return m_dropdownButton; } + // Get the popup window, NULL when not shown + DropDownPopup *GetPopupWindow() { return m_popupWin; } protected: - virtual void DoSetSize(int x, int y, int width, int height, - int sizeFlags = wxSIZE_AUTO); + virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - void OnSize( wxSizeEvent& event ); - virtual wxSize DoGetBestSize() const; + void OnSize(wxSizeEvent &event); + virtual wxSize DoGetBestSize() const; - virtual bool DoShowPopup(); + virtual bool DoShowPopup(); - // override to set the height of the dropdown box - // input max_height is height from bottom of ctrl to bottom of screen - // return < 1 to not have the popup displayed - virtual int DoGetBestDropHeight(int max_height) { return max_height; } + // override to set the height of the dropdown box + // input max_height is height from bottom of ctrl to bottom of screen + // return < 1 to not have the popup displayed + virtual int DoGetBestDropHeight(int max_height) { return max_height; } - wxCustomButton *m_dropdownButton; - DropDownPopup *m_popupWin; + wxCustomButton *m_dropdownButton; + DropDownPopup *m_popupWin; private: - void Init(); - DECLARE_DYNAMIC_CLASS(DropDownBase) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_DYNAMIC_CLASS(DropDownBase) + DECLARE_EVENT_TABLE() }; //----------------------------------------------------------------------------- // DropDownPopup generic popup window, call SetChild //----------------------------------------------------------------------------- -class WXDLLIMPEXP_THINGS DropDownPopup : public wxPopupTransientWindow -{ +class WXDLLIMPEXP_THINGS DropDownPopup : public wxPopupTransientWindow { public: - DropDownPopup() : wxPopupTransientWindow() { Init(); } - DropDownPopup(DropDownBase *parent, int style = wxBORDER_NONE) : wxPopupTransientWindow() - { - Init(); - Create(parent, style); - } - virtual ~DropDownPopup(); + DropDownPopup() : wxPopupTransientWindow() { Init(); } + DropDownPopup(DropDownBase *parent, int style = wxBORDER_NONE) : wxPopupTransientWindow() + { + Init(); + Create(parent, style); + } + virtual ~DropDownPopup(); - bool Create(DropDownBase *parent, int style = wxBORDER_NONE); + bool Create(DropDownBase *parent, int style = wxBORDER_NONE); - virtual void Popup(wxWindow *focus = NULL); - virtual void Dismiss(); - virtual bool ProcessLeftDown(wxMouseEvent& event); + virtual void Popup(wxWindow *focus = NULL); + virtual void Dismiss(); + virtual bool ProcessLeftDown(wxMouseEvent &event); - virtual void SetChild(wxWindow *child); - virtual wxWindow *GetChild() const { return m_childWin; } - bool m_ignore_popup; + virtual void SetChild(wxWindow *child); + virtual wxWindow *GetChild() const { return m_childWin; } + bool m_ignore_popup; protected: - - // start/stop timer shat pushes and pops handler when the mouse goes over - // the scrollbars (if any) of the child window - void StartTimer(); - void StopTimer(); - void PushPopupHandler(wxWindow* child); - void PopPopupHandler(wxWindow* child); - - void OnMouse( wxMouseEvent& event ); - void OnKeyDown( wxKeyEvent &event ); - void OnTimer( wxTimerEvent& event ); - void OnIdle( wxIdleEvent& event ); - - wxPoint m_mouse; // last/current mouse position - wxWindow *m_childWin; // store our own child pointer - DropDownBase *m_owner; - wxTimer *m_timer; // timer for tracking mouse position - bool m_popped_handler; // state of the event handler + // start/stop timer shat pushes and pops handler when the mouse goes over + // the scrollbars (if any) of the child window + void StartTimer(); + void StopTimer(); + void PushPopupHandler(wxWindow *child); + void PopPopupHandler(wxWindow *child); + + void OnMouse(wxMouseEvent &event); + void OnKeyDown(wxKeyEvent &event); + void OnTimer(wxTimerEvent &event); + void OnIdle(wxIdleEvent &event); + + wxPoint m_mouse; // last/current mouse position + wxWindow *m_childWin; // store our own child pointer + DropDownBase *m_owner; + wxTimer *m_timer; // timer for tracking mouse position + bool m_popped_handler; // state of the event handler private: - void Init(); - DECLARE_DYNAMIC_CLASS(DropDownPopup) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_DYNAMIC_CLASS(DropDownPopup) + DECLARE_EVENT_TABLE() }; -#endif // _WX_DROPDOWNBASE_H_ +#endif // _WX_DROPDOWNBASE_H_ diff --git a/src/labenski/include/wx/wxthings/genergdi.h b/src/labenski/include/wx/wxthings/genergdi.h index e57174b20..635e63742 100644 --- a/src/labenski/include/wx/wxthings/genergdi.h +++ b/src/labenski/include/wx/wxthings/genergdi.h @@ -22,121 +22,126 @@ class WXDLLIMPEXP_THINGS wxGenericBrush; // Uncreated and invalid versions of the generic colour, pen, and brush WXDLLIMPEXP_DATA_THINGS(extern const wxGenericColour) wxNullGenericColour; -WXDLLIMPEXP_DATA_THINGS(extern const wxGenericPen) wxNullGenericPen; -WXDLLIMPEXP_DATA_THINGS(extern const wxGenericBrush) wxNullGenericBrush; +WXDLLIMPEXP_DATA_THINGS(extern const wxGenericPen) wxNullGenericPen; +WXDLLIMPEXP_DATA_THINGS(extern const wxGenericBrush) wxNullGenericBrush; // Arrays of the generic colours, pens, and brushes #include "wx/dynarray.h" #ifndef WX_DECLARE_OBJARRAY_WITH_DECL // for wx2.4 backwards compatibility - #define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, expmode) WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_THINGS) +#define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, expmode) \ + WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_THINGS) #endif WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericColour, wxArrayGenericColour, class WXDLLIMPEXP_THINGS); -WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericPen, wxArrayGenericPen, class WXDLLIMPEXP_THINGS); -WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericBrush, wxArrayGenericBrush, class WXDLLIMPEXP_THINGS); +WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericPen, wxArrayGenericPen, class WXDLLIMPEXP_THINGS); +WX_DECLARE_OBJARRAY_WITH_DECL(wxGenericBrush, wxArrayGenericBrush, class WXDLLIMPEXP_THINGS); //---------------------------------------------------------------------------- // wxGenericColour - a RGBA colour that's converts from and to a wxColour. // You can have thousands of them without using up resources. (on MSW) //---------------------------------------------------------------------------- -class WXDLLIMPEXP_THINGS wxGenericColour : public wxObject -{ +class WXDLLIMPEXP_THINGS wxGenericColour : public wxObject { public: - wxGenericColour() : wxObject() {} - wxGenericColour( const wxGenericColour& c ) { Create(c); } - wxGenericColour( const wxColour& c ) { Create(c); } - wxGenericColour( unsigned char red, unsigned char green, - unsigned char blue, unsigned char alpha=255 ) - : wxObject() { Create(red, green, blue, alpha); } - wxGenericColour( unsigned long colABGR ) : wxObject() { CreateABGR(colABGR); } - - // Implicit conversion from the colour name - wxGenericColour( const wxString &colourName ) : wxObject() { Create(colourName); } - wxGenericColour( const char *colourName ) : wxObject() { Create(wxString::FromAscii(colourName)); } + wxGenericColour() : wxObject() {} + wxGenericColour(const wxGenericColour &c) { Create(c); } + wxGenericColour(const wxColour &c) { Create(c); } + wxGenericColour(unsigned char red, unsigned char green, unsigned char blue, + unsigned char alpha = 255) + : wxObject() + { + Create(red, green, blue, alpha); + } + wxGenericColour(unsigned long colABGR) : wxObject() { CreateABGR(colABGR); } + + // Implicit conversion from the colour name + wxGenericColour(const wxString &colourName) : wxObject() { Create(colourName); } + wxGenericColour(const char *colourName) : wxObject() { Create(wxString::FromAscii(colourName)); } #if wxUSE_UNICODE - wxGenericColour( const wxChar *colourName ) : wxObject() { Create(wxString(colourName)); } + wxGenericColour(const wxChar *colourName) : wxObject() { Create(wxString(colourName)); } #endif - virtual ~wxGenericColour() {} - // Destroy the refed data - void Destroy() { UnRef(); } - // Is this colour valid, has refed data - bool Ok() const { return m_refData != NULL; } - - // ----------------------------------------------------------------------- - // (re)Create this colour, unrefing this colour first. - // Use these to detach this colour from it's refed copies. - void Create( const wxGenericColour& c ); - void Create( const wxColour& c); - void Create( unsigned char red = 0, unsigned char green = 0, - unsigned char blue = 0, unsigned char alpha=255 ); - void CreateABGR( unsigned long colABGR ); - void CreateARGB( unsigned long colARGB ); - void Create( const wxString& colourName ); - - // ----------------------------------------------------------------------- - // Set the colour values of the refed data. - // Use these to adjust the values of all the refed copies. - void Set( const wxGenericColour &c ); - void Set( const wxColour& c ); - void Set( unsigned char red, unsigned char green, - unsigned char blue, unsigned char alpha=255 ); - void SetABGR( unsigned long colABGR ); - void SetARGB( unsigned long colARGB ); - void Set( const wxString& colourName ); - - void SetRed ( unsigned char r ); - void SetGreen( unsigned char g ); - void SetBlue ( unsigned char b ); - void SetAlpha( unsigned char a ); - - // ----------------------------------------------------------------------- - // Get the colour values - inline wxColour GetColour() const { return wxColour(GetRed(), GetGreen(), GetBlue()); } - - unsigned char GetRed() const; - unsigned char GetGreen() const; - unsigned char GetBlue() const; - unsigned char GetAlpha() const; - - // wxWidgets wxColour compatibility functions - unsigned char Red() const { return GetRed(); } - unsigned char Green() const { return GetGreen(); } - unsigned char Blue() const { return GetBlue(); } - unsigned char Alpha() const { return GetAlpha(); } - - // ----------------------------------------------------------------------- - // Equivalency tests - bool IsSameAs( const wxGenericColour& c ) const; - bool IsSameAs( const wxColour& c ) const; - - // Get a "hot to cold" colour where i ranges from 0 to 255 - wxGenericColour GetHotColdColour(double i) const; - - // Read colour to and from string - //wxString WriteString(const wxString& format = wxT("%d,%d,%d,%d")) const; - //bool ReadString(const wxString& str, const wxString& format = wxT("%d,%d,%d,%d")); - - // operators - bool operator == (const wxGenericColour& c) const - { return m_refData == c.m_refData; } - bool operator != (const wxGenericColour& c) const - { return m_refData != c.m_refData; } - - wxGenericColour& operator = (const wxGenericColour& c) - { - if ( (*this) != c ) - Ref(c); - return *this; + virtual ~wxGenericColour() {} + // Destroy the refed data + void Destroy() { UnRef(); } + // Is this colour valid, has refed data + bool Ok() const { return m_refData != NULL; } + + // ----------------------------------------------------------------------- + // (re)Create this colour, unrefing this colour first. + // Use these to detach this colour from it's refed copies. + void Create(const wxGenericColour &c); + void Create(const wxColour &c); + void Create(unsigned char red = 0, unsigned char green = 0, unsigned char blue = 0, + unsigned char alpha = 255); + void CreateABGR(unsigned long colABGR); + void CreateARGB(unsigned long colARGB); + void Create(const wxString &colourName); + + // ----------------------------------------------------------------------- + // Set the colour values of the refed data. + // Use these to adjust the values of all the refed copies. + void Set(const wxGenericColour &c); + void Set(const wxColour &c); + void Set(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha = 255); + void SetABGR(unsigned long colABGR); + void SetARGB(unsigned long colARGB); + void Set(const wxString &colourName); + + void SetRed(unsigned char r); + void SetGreen(unsigned char g); + void SetBlue(unsigned char b); + void SetAlpha(unsigned char a); + + // ----------------------------------------------------------------------- + // Get the colour values + inline wxColour GetColour() const { return wxColour(GetRed(), GetGreen(), GetBlue()); } + + unsigned char GetRed() const; + unsigned char GetGreen() const; + unsigned char GetBlue() const; + unsigned char GetAlpha() const; + + // wxWidgets wxColour compatibility functions + unsigned char Red() const { return GetRed(); } + unsigned char Green() const { return GetGreen(); } + unsigned char Blue() const { return GetBlue(); } + unsigned char Alpha() const { return GetAlpha(); } + + // ----------------------------------------------------------------------- + // Equivalency tests + bool IsSameAs(const wxGenericColour &c) const; + bool IsSameAs(const wxColour &c) const; + + // Get a "hot to cold" colour where i ranges from 0 to 255 + wxGenericColour GetHotColdColour(double i) const; + + // Read colour to and from string + // wxString WriteString(const wxString& format = wxT("%d,%d,%d,%d")) const; + // bool ReadString(const wxString& str, const wxString& format = wxT("%d,%d,%d,%d")); + + // operators + bool operator==(const wxGenericColour &c) const { return m_refData == c.m_refData; } + bool operator!=(const wxGenericColour &c) const { return m_refData != c.m_refData; } + + wxGenericColour &operator=(const wxGenericColour &c) + { + if ((*this) != c) { + Ref(c); } - wxGenericColour& operator = ( const wxColour& c ) { Create(c); return *this; } + return *this; + } + wxGenericColour &operator=(const wxColour &c) + { + Create(c); + return *this; + } private: - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxGenericColour) + DECLARE_DYNAMIC_CLASS(wxGenericColour) }; //---------------------------------------------------------------------------- @@ -148,93 +153,101 @@ class WXDLLIMPEXP_THINGS wxGenericColour : public wxObject /* Backwards compatibility */ #define wxPenCap int #define wxPenJoin int -#endif /* wxCHECK_VERSION */ +#endif /* wxCHECK_VERSION */ -class WXDLLIMPEXP_THINGS wxGenericPen : public wxObject -{ +class WXDLLIMPEXP_THINGS wxGenericPen : public wxObject { public: - wxGenericPen() : wxObject() {} - wxGenericPen( const wxGenericPen &pen ) : wxObject() { Create(pen); } - wxGenericPen( const wxPen &pen ) : wxObject() { Create(pen); } - wxGenericPen( const wxGenericColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, - wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND ) : wxObject() - { Create(colour, width, style, cap, join); } - wxGenericPen( const wxColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, - wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND ) : wxObject() - { Create(colour, width, style, cap, join); } - virtual ~wxGenericPen() {} - // Destroy the refed data - void Destroy() { UnRef(); } - // Is this colour valid, has refed data - bool Ok() const { return m_refData != NULL; } - - // ----------------------------------------------------------------------- - // (re)Create this pen, unrefing this pen first. - // Use these to detach this pen from it's refed copies. - void Create( const wxGenericPen &pen ); - void Create( const wxPen &pen ); - void Create( const wxGenericColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, - wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND ); - void Create( const wxColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, - wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND ); - - // ----------------------------------------------------------------------- - // Set the values of the refed data. - // Use these to adjust the values of all the refed copies. - void Set( const wxGenericPen& pen ); - void Set( const wxPen& pen ); - void SetColour( const wxGenericColour &colour ); - void SetColour( const wxColour &colour ); - void SetColour( int red, int green, int blue, int alpha=255 ); - void SetCap( wxPenCap capStyle ); - void SetJoin( wxPenJoin joinStyle ); - void SetStyle( wxPenStyle style ); - void SetWidth( int width ); - void SetDashes( int number_of_dashes, const wxDash *dash ); - - // ----------------------------------------------------------------------- - // Get the pen values - wxPen GetPen() const; - - wxGenericColour GetGenericColour() const; - wxColour GetColour() const; - int GetWidth() const; - wxPenStyle GetStyle() const; - wxPenCap GetCap() const; - wxPenJoin GetJoin() const; - int GetDashes(wxDash **ptr) const; - int GetDashCount() const; - wxDash* GetDash() const; - - // ----------------------------------------------------------------------- - // Equivalency tests - bool IsSameAs(const wxGenericPen& pen) const; - bool IsSameAs(const wxPen& pen) const; - - // Read pen to and from string - //wxString WriteString() const; - //bool ReadString(const wxString& str); - - // operators - bool operator == (const wxGenericPen& pen) const - { return m_refData == pen.m_refData; } - bool operator != (const wxGenericPen& pen) const - { return m_refData != pen.m_refData; } - - wxGenericPen& operator = (const wxGenericPen& pen) - { - if ( (*this) != pen ) - Ref(pen); - return *this; + wxGenericPen() : wxObject() {} + wxGenericPen(const wxGenericPen &pen) : wxObject() { Create(pen); } + wxGenericPen(const wxPen &pen) : wxObject() { Create(pen); } + wxGenericPen(const wxGenericColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, + wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND) + : wxObject() + { + Create(colour, width, style, cap, join); + } + wxGenericPen(const wxColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, + wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND) + : wxObject() + { + Create(colour, width, style, cap, join); + } + virtual ~wxGenericPen() {} + // Destroy the refed data + void Destroy() { UnRef(); } + // Is this colour valid, has refed data + bool Ok() const { return m_refData != NULL; } + + // ----------------------------------------------------------------------- + // (re)Create this pen, unrefing this pen first. + // Use these to detach this pen from it's refed copies. + void Create(const wxGenericPen &pen); + void Create(const wxPen &pen); + void Create(const wxGenericColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, + wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND); + void Create(const wxColour &colour, int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, + wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND); + + // ----------------------------------------------------------------------- + // Set the values of the refed data. + // Use these to adjust the values of all the refed copies. + void Set(const wxGenericPen &pen); + void Set(const wxPen &pen); + void SetColour(const wxGenericColour &colour); + void SetColour(const wxColour &colour); + void SetColour(int red, int green, int blue, int alpha = 255); + void SetCap(wxPenCap capStyle); + void SetJoin(wxPenJoin joinStyle); + void SetStyle(wxPenStyle style); + void SetWidth(int width); + void SetDashes(int number_of_dashes, const wxDash *dash); + + // ----------------------------------------------------------------------- + // Get the pen values + wxPen GetPen() const; + + wxGenericColour GetGenericColour() const; + wxColour GetColour() const; + int GetWidth() const; + wxPenStyle GetStyle() const; + wxPenCap GetCap() const; + wxPenJoin GetJoin() const; + int GetDashes(wxDash **ptr) const; + int GetDashCount() const; + wxDash *GetDash() const; + + // ----------------------------------------------------------------------- + // Equivalency tests + bool IsSameAs(const wxGenericPen &pen) const; + bool IsSameAs(const wxPen &pen) const; + + // Read pen to and from string + // wxString WriteString() const; + // bool ReadString(const wxString& str); + + // operators + bool operator==(const wxGenericPen &pen) const { return m_refData == pen.m_refData; } + bool operator!=(const wxGenericPen &pen) const { return m_refData != pen.m_refData; } + + wxGenericPen &operator=(const wxGenericPen &pen) + { + if ((*this) != pen) { + Ref(pen); } - wxGenericPen& operator = ( const wxPen& pen ) { Create(pen); return *this; } + return *this; + } + wxGenericPen &operator=(const wxPen &pen) + { + Create(pen); + return *this; + } private: - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxGenericPen) + DECLARE_DYNAMIC_CLASS(wxGenericPen) }; //---------------------------------------------------------------------------- @@ -242,81 +255,90 @@ class WXDLLIMPEXP_THINGS wxGenericPen : public wxObject // You can have thousands of them without using up resources. (on MSW) //---------------------------------------------------------------------------- -class WXDLLIMPEXP_THINGS wxGenericBrush : public wxObject -{ +class WXDLLIMPEXP_THINGS wxGenericBrush : public wxObject { public: - wxGenericBrush() : wxObject() {} - wxGenericBrush( const wxGenericBrush &brush ) : wxObject() { Create(brush); } - wxGenericBrush( const wxBrush &brush ) : wxObject() { Create(brush); } - wxGenericBrush( const wxGenericColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID) - : wxObject() { Create(colour, style); } - wxGenericBrush( const wxColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID) - : wxObject() { Create(colour, style); } - wxGenericBrush( const wxBitmap& stipple ) : wxObject() { Create(stipple); } - - virtual ~wxGenericBrush() {} - // Destroy the refed data - void Destroy() { UnRef(); } - // Is this colour valid, has refed data - bool Ok() const { return m_refData != NULL; } - - // ----------------------------------------------------------------------- - // (re)Create this brush, unrefing this pen first. - // Use these to detach this pen from it's refed copies. - void Create( const wxGenericBrush &brush ); - void Create( const wxBrush &brush ); - void Create( const wxGenericColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID ); - void Create( const wxColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID ); - void Create( const wxBitmap &stipple ); - - // ----------------------------------------------------------------------- - // Set the values of the refed data. - // Use these to adjust the values of all the refed copies. - void Set( const wxGenericBrush& brush ); - void Set( const wxBrush& brush ); - void SetColour( const wxGenericColour &colour ); - void SetColour( const wxColour &colour ); - void SetColour( int red, int green, int blue, int alpha=255 ); - void SetStyle( wxBrushStyle style ); - void SetStipple( const wxBitmap& stipple ); - - // ----------------------------------------------------------------------- - // Get the brush values - wxBrush GetBrush() const; - - wxGenericColour GetGenericColour() const; - wxColour GetColour() const; - wxBrushStyle GetStyle() const; - wxBitmap* GetStipple() const; - - bool IsHatch() const - { return (GetStyle()>=wxBRUSHSTYLE_FIRST_HATCH) && (GetStyle()<=wxBRUSHSTYLE_LAST_HATCH); } - - // ----------------------------------------------------------------------- - // Equivalency tests - bool IsSameAs(const wxGenericBrush& brush) const; - bool IsSameAs(const wxBrush& brush) const; - - // operators - bool operator == (const wxGenericBrush& brush) const - { return m_refData == brush.m_refData; } - bool operator != (const wxGenericBrush& brush) const - { return m_refData != brush.m_refData; } - - wxGenericBrush& operator = (const wxGenericBrush& brush) - { - if ( (*this) != brush ) - Ref(brush); - return *this; + wxGenericBrush() : wxObject() {} + wxGenericBrush(const wxGenericBrush &brush) : wxObject() { Create(brush); } + wxGenericBrush(const wxBrush &brush) : wxObject() { Create(brush); } + wxGenericBrush(const wxGenericColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID) + : wxObject() + { + Create(colour, style); + } + wxGenericBrush(const wxColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID) : wxObject() + { + Create(colour, style); + } + wxGenericBrush(const wxBitmap &stipple) : wxObject() { Create(stipple); } + + virtual ~wxGenericBrush() {} + // Destroy the refed data + void Destroy() { UnRef(); } + // Is this colour valid, has refed data + bool Ok() const { return m_refData != NULL; } + + // ----------------------------------------------------------------------- + // (re)Create this brush, unrefing this pen first. + // Use these to detach this pen from it's refed copies. + void Create(const wxGenericBrush &brush); + void Create(const wxBrush &brush); + void Create(const wxGenericColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID); + void Create(const wxColour &colour, wxBrushStyle style = wxBRUSHSTYLE_SOLID); + void Create(const wxBitmap &stipple); + + // ----------------------------------------------------------------------- + // Set the values of the refed data. + // Use these to adjust the values of all the refed copies. + void Set(const wxGenericBrush &brush); + void Set(const wxBrush &brush); + void SetColour(const wxGenericColour &colour); + void SetColour(const wxColour &colour); + void SetColour(int red, int green, int blue, int alpha = 255); + void SetStyle(wxBrushStyle style); + void SetStipple(const wxBitmap &stipple); + + // ----------------------------------------------------------------------- + // Get the brush values + wxBrush GetBrush() const; + + wxGenericColour GetGenericColour() const; + wxColour GetColour() const; + wxBrushStyle GetStyle() const; + wxBitmap *GetStipple() const; + + bool IsHatch() const + { + return (GetStyle() >= wxBRUSHSTYLE_FIRST_HATCH) && (GetStyle() <= wxBRUSHSTYLE_LAST_HATCH); + } + + // ----------------------------------------------------------------------- + // Equivalency tests + bool IsSameAs(const wxGenericBrush &brush) const; + bool IsSameAs(const wxBrush &brush) const; + + // operators + bool operator==(const wxGenericBrush &brush) const { return m_refData == brush.m_refData; } + bool operator!=(const wxGenericBrush &brush) const { return m_refData != brush.m_refData; } + + wxGenericBrush &operator=(const wxGenericBrush &brush) + { + if ((*this) != brush) { + Ref(brush); } - wxGenericBrush& operator = ( const wxBrush& brush ) { Create(brush); return *this; } + return *this; + } + wxGenericBrush &operator=(const wxBrush &brush) + { + Create(brush); + return *this; + } private: - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxGenericBrush) + DECLARE_DYNAMIC_CLASS(wxGenericBrush) }; #endif // _WX_GENERGDI_H_ diff --git a/src/labenski/include/wx/wxthings/geometry.h b/src/labenski/include/wx/wxthings/geometry.h index a25e560a0..01003316a 100644 --- a/src/labenski/include/wx/wxthings/geometry.h +++ b/src/labenski/include/wx/wxthings/geometry.h @@ -21,142 +21,269 @@ // y = mx+b, m=(x-x0)/(y-y0) //----------------------------------------------------------------------------- -class WXDLLEXPORT wxRay2DDouble : public wxPoint2DDouble -{ -public : - - inline wxRay2DDouble(wxDouble x=0, wxDouble y=0, wxDouble slope=0) - { m_x = x; m_y = y; m_slope = slope; } - inline wxRay2DDouble(const wxPoint2DDouble &pt, wxDouble slope) - { m_x = pt.m_x; m_y = pt.m_y; m_slope = slope; } - inline wxRay2DDouble(wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2) - { m_x = x1; m_y = y1; m_slope = GetSlope(x1, y1, x2, y2); } - inline wxRay2DDouble(const wxPoint2DDouble &pt1, const wxPoint2DDouble &pt2) - { m_x = pt1.m_x; m_y = pt1.m_y; m_slope = GetSlope(pt1, pt2); } - inline wxRay2DDouble(const wxRay2DDouble &line) - { m_x = line.m_x; m_y = line.m_y; m_slope = line.m_slope; } - - inline wxDouble GetX() const { return m_x; } - inline wxDouble GetY() const { return m_y; } - inline wxPoint2DDouble GetPoint() const { return (wxPoint2DDouble)(*this); } - inline wxDouble GetSlope() const { return m_slope; } - - inline void SetX(wxDouble x) { m_x = x; } - inline void SetY(wxDouble y) { m_y = y; } - inline void SetPoint(const wxPoint2DDouble &pt ) { m_x = pt.m_x; m_y = pt.m_y; } - inline void SetSlope(wxDouble slope) { m_slope = slope; } - - inline wxDouble GetYFromX(wxDouble x) const {return m_slope*(x-m_x) + m_y;} - inline wxDouble GetXFromY(wxDouble y) const {return (y-m_y)/m_slope + m_x;} - - // Get a point along the line at pos x or y - inline wxPoint2DDouble GetPointOnRayFromX(wxDouble x) const { return wxPoint2DDouble(x, GetYFromX(x)); } - inline wxPoint2DDouble GetPointOnRayFromY(wxDouble y) const - { if (m_slope == 0) return (*this); - return wxPoint2DDouble(GetXFromY(y), y); } - - // Translate the point m_pt along the line to pos x or y - inline void TranslatePointByX(wxDouble x) { m_y = GetYFromX(x); m_x = x; } - inline void TranslatePointByY(wxDouble y) { m_x = GetXFromY(y); m_y = y; } - inline wxRay2DDouble GetTranslatedLineByX(wxDouble x) const { return wxRay2DDouble(x, GetYFromX(x), m_slope); } - inline wxRay2DDouble GetTranslatedLineByY(wxDouble y) const { return wxRay2DDouble(GetXFromY(y), y, m_slope); } - - inline wxDouble GetDistanceToPoint(const wxPoint2DDouble &pt, wxPoint2DDouble *closestPt=NULL) const - { - wxPoint2DDouble l1(m_x, m_y); - wxPoint2DDouble l2(GetPointOnRayFromX(m_x+pt.m_x)); - wxPoint2DDouble v = l2 - l1; - wxPoint2DDouble w = pt - l1; - wxDouble c1 = w.GetDotProduct(v); - wxDouble c2 = v.GetDotProduct(v); - wxDouble b = c1 / c2; - wxPoint2DDouble pb = l1 + b*v; - if (closestPt) *closestPt = pb; - return pb.GetDistance( pt ); - -/* - wxPoint2DDouble ll2 = l2; - double l = ll2.GetDistanceSquare(l1); - double u = ((p.m_x-l1.m_x)*(l2.m_x-l1.m_x)+(p.m_y-l1.m_y)*(l2.m_y-l1.m_y))/l; - wxPoint2DDouble i = l1 + u*(l2-l1); - - //printf("distance %.9lf %.9lf %d\n\n", i.GetDistance(p), pb.GetDistance(p), int(pb==i)); -*/ - - // this x for y on this line - // y(on this line) = m_slope*(x-m_pt.m_x) + m_pt.m_y - // = (-1/m_slope)(x-pt.m_x) + pt.m_y - // so - // x(on this line) = (y-m_pt.m_y)/m_slope + m_pt.m_x - // = (y-pt.m_y)/(-1/m_slope) + m_pt.m_x - - //(y-m_pt.m_y)/m_slope + m_pt.m_x = (y-pt.m_y)(-1/m_slope) + m_pt.m_x - //(y-m_pt.m_y)/m_slope - m_slope*(y-pt.m_y) = + m_pt.m_x - m_pt.m_x - //y*(1/m_slope - m_slope) = + m_pt.m_x - m_pt.m_x +m_slope*pt.m_y + m_slope*m_pt.m_y - //y = (m_pt.m_x - m_pt.m_x +m_slope*pt.m_y + m_slope*m_pt.m_y)/(1/m_slope - m_slope) -/* - wxDouble x = (m_x + m_slope*m_slope*m_x - m_slope*(m_y - m_y))/(m_slope*m_slope+1.0); - wxPoint2DDouble pl(x, m_slope*(x-m_x) + m_y); - if (closestPt) *closestPt = pl; - return pl.GetDistance(pt); -*/ +class WXDLLEXPORT wxRay2DDouble : public wxPoint2DDouble { +public: + inline wxRay2DDouble(wxDouble x = 0, wxDouble y = 0, wxDouble slope = 0) + { + m_x = x; + m_y = y; + m_slope = slope; + } + inline wxRay2DDouble(const wxPoint2DDouble &pt, wxDouble slope) + { + m_x = pt.m_x; + m_y = pt.m_y; + m_slope = slope; + } + inline wxRay2DDouble(wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2) + { + m_x = x1; + m_y = y1; + m_slope = GetSlope(x1, y1, x2, y2); + } + inline wxRay2DDouble(const wxPoint2DDouble &pt1, const wxPoint2DDouble &pt2) + { + m_x = pt1.m_x; + m_y = pt1.m_y; + m_slope = GetSlope(pt1, pt2); + } + inline wxRay2DDouble(const wxRay2DDouble &line) + { + m_x = line.m_x; + m_y = line.m_y; + m_slope = line.m_slope; + } + + inline wxDouble GetX() const { return m_x; } + inline wxDouble GetY() const { return m_y; } + inline wxPoint2DDouble GetPoint() const { return (wxPoint2DDouble)(*this); } + inline wxDouble GetSlope() const { return m_slope; } + + inline void SetX(wxDouble x) { m_x = x; } + inline void SetY(wxDouble y) { m_y = y; } + inline void SetPoint(const wxPoint2DDouble &pt) + { + m_x = pt.m_x; + m_y = pt.m_y; + } + inline void SetSlope(wxDouble slope) { m_slope = slope; } + + inline wxDouble GetYFromX(wxDouble x) const { return m_slope * (x - m_x) + m_y; } + inline wxDouble GetXFromY(wxDouble y) const { return (y - m_y) / m_slope + m_x; } + + // Get a point along the line at pos x or y + inline wxPoint2DDouble GetPointOnRayFromX(wxDouble x) const + { + return wxPoint2DDouble(x, GetYFromX(x)); + } + inline wxPoint2DDouble GetPointOnRayFromY(wxDouble y) const + { + if (m_slope == 0) { + return (*this); } - - inline wxDouble GetDistanceToRay( const wxRay2DDouble &ray ) const - { - // FIXME - unchecked, just quickly translated from some other code - if (m_slope != ray.m_slope) return 0; - if (m_slope == 0) return fabs(m_y - ray.m_y); - wxPoint2DDouble p1 = GetPointOnRayFromX(0); - wxPoint2DDouble p2 = ray.GetPointOnRayFromX(0); - // y = (-1/s1)*x+p1.m_y = s2*x + p2.m_y - wxDouble dx = (p1.m_y - p2.m_y)/(m_slope + (1.0/m_slope)); - wxDouble dy = (m_slope*dx+p2.m_y) - p1.m_y; - return sqrt(dx*dx + dy*dy); - } - - inline static wxDouble GetSlope(wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2) - { return (y2 - y1)/(x2 - x1); } - inline static wxDouble GetSlope(const wxPoint2DDouble &pt1, const wxPoint2DDouble &pt2) - { return (pt2.m_y-pt1.m_y)/(pt2.m_x-pt1.m_x); } - - // find the point where the two rays meet, return false if parallel - bool Intersect(const wxRay2DDouble& other, wxPoint2DDouble& pt) const - { - // (y1-y0)/(x1-x0)=m for both lines, equate y1's first - if (m_slope == other.m_slope) return false; - pt.m_x = (m_slope*m_x - other.m_slope*other.m_x + other.m_y - m_y)/(m_slope - other.m_slope); - pt.m_y = GetYFromX(pt.m_x); - return true; + return wxPoint2DDouble(GetXFromY(y), y); + } + + // Translate the point m_pt along the line to pos x or y + inline void TranslatePointByX(wxDouble x) + { + m_y = GetYFromX(x); + m_x = x; + } + inline void TranslatePointByY(wxDouble y) + { + m_x = GetXFromY(y); + m_y = y; + } + inline wxRay2DDouble GetTranslatedLineByX(wxDouble x) const + { + return wxRay2DDouble(x, GetYFromX(x), m_slope); + } + inline wxRay2DDouble GetTranslatedLineByY(wxDouble y) const + { + return wxRay2DDouble(GetXFromY(y), y, m_slope); + } + + inline wxDouble GetDistanceToPoint(const wxPoint2DDouble &pt, + wxPoint2DDouble *closestPt = NULL) const + { + wxPoint2DDouble l1(m_x, m_y); + wxPoint2DDouble l2(GetPointOnRayFromX(m_x + pt.m_x)); + wxPoint2DDouble v = l2 - l1; + wxPoint2DDouble w = pt - l1; + wxDouble c1 = w.GetDotProduct(v); + wxDouble c2 = v.GetDotProduct(v); + wxDouble b = c1 / c2; + wxPoint2DDouble pb = l1 + b * v; + if (closestPt) { + *closestPt = pb; } - - // Operators - - inline wxRay2DDouble operator=(const wxRay2DDouble& r) { m_x = r.m_x; m_y = r.m_y; m_slope = r.m_slope; return *this; } - inline bool operator==(const wxRay2DDouble& r) const { return (m_x == r.m_x)&&(m_y == r.m_y)&&(m_slope == r.m_slope); } - inline bool operator!=(const wxRay2DDouble& r) const { return !(*this == r); } - - inline wxRay2DDouble operator+(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x+rel_pos.m_x, m_y+rel_pos.m_y, m_slope); } - inline wxRay2DDouble operator-(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x-rel_pos.m_x, m_y-rel_pos.m_y, m_slope); } - inline wxRay2DDouble operator*(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x*rel_pos.m_x, m_y*rel_pos.m_y, m_slope); } - inline wxRay2DDouble operator/(const wxPoint2DDouble& rel_pos) const { return wxRay2DDouble(m_x/rel_pos.m_x, m_y/rel_pos.m_y, m_slope); } - - inline wxRay2DDouble& operator+=(const wxPoint2DDouble& rel_pos) { m_x += rel_pos.m_x; m_y += rel_pos.m_y; return *this; } - inline wxRay2DDouble& operator-=(const wxPoint2DDouble& rel_pos) { m_x -= rel_pos.m_x; m_y -= rel_pos.m_y; return *this; } - inline wxRay2DDouble& operator*=(const wxPoint2DDouble& rel_pos) { m_x *= rel_pos.m_x; m_y *= rel_pos.m_y; return *this; } - inline wxRay2DDouble& operator/=(const wxPoint2DDouble& rel_pos) { m_x /= rel_pos.m_x; m_y /= rel_pos.m_y; return *this; } - - inline wxRay2DDouble operator+(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope+rel_slope); } - inline wxRay2DDouble operator-(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope-rel_slope); } - inline wxRay2DDouble operator*(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope*rel_slope); } - inline wxRay2DDouble operator/(const wxDouble& rel_slope) const { return wxRay2DDouble(m_x, m_y, m_slope/rel_slope); } - - inline wxRay2DDouble& operator+=(const wxDouble& rel_slope) { m_slope += rel_slope; return *this; } - inline wxRay2DDouble& operator-=(const wxDouble& rel_slope) { m_slope -= rel_slope; return *this; } - inline wxRay2DDouble& operator*=(const wxDouble& rel_slope) { m_slope *= rel_slope; return *this; } - inline wxRay2DDouble& operator/=(const wxDouble& rel_slope) { m_slope /= rel_slope; return *this; } - - wxDouble m_slope; + return pb.GetDistance(pt); + + /* + wxPoint2DDouble ll2 = l2; + double l = ll2.GetDistanceSquare(l1); + double u = ((p.m_x-l1.m_x)*(l2.m_x-l1.m_x)+(p.m_y-l1.m_y)*(l2.m_y-l1.m_y))/l; + wxPoint2DDouble i = l1 + u*(l2-l1); + + //printf("distance %.9lf %.9lf %d\n\n", i.GetDistance(p), pb.GetDistance(p), + int(pb==i)); + */ + + // this x for y on this line + // y(on this line) = m_slope*(x-m_pt.m_x) + m_pt.m_y + // = (-1/m_slope)(x-pt.m_x) + pt.m_y + // so + // x(on this line) = (y-m_pt.m_y)/m_slope + m_pt.m_x + // = (y-pt.m_y)/(-1/m_slope) + m_pt.m_x + + //(y-m_pt.m_y)/m_slope + m_pt.m_x = (y-pt.m_y)(-1/m_slope) + m_pt.m_x + //(y-m_pt.m_y)/m_slope - m_slope*(y-pt.m_y) = + m_pt.m_x - m_pt.m_x + // y*(1/m_slope - m_slope) = + m_pt.m_x - m_pt.m_x +m_slope*pt.m_y + m_slope*m_pt.m_y + // y = (m_pt.m_x - m_pt.m_x +m_slope*pt.m_y + m_slope*m_pt.m_y)/(1/m_slope - m_slope) + /* + wxDouble x = (m_x + m_slope*m_slope*m_x - m_slope*(m_y - m_y))/(m_slope*m_slope+1.0); + wxPoint2DDouble pl(x, m_slope*(x-m_x) + m_y); + if (closestPt) *closestPt = pl; + return pl.GetDistance(pt); + */ + } + + inline wxDouble GetDistanceToRay(const wxRay2DDouble &ray) const + { + // FIXME - unchecked, just quickly translated from some other code + if (m_slope != ray.m_slope) { + return 0; + } + if (m_slope == 0) { + return fabs(m_y - ray.m_y); + } + wxPoint2DDouble p1 = GetPointOnRayFromX(0); + wxPoint2DDouble p2 = ray.GetPointOnRayFromX(0); + // y = (-1/s1)*x+p1.m_y = s2*x + p2.m_y + wxDouble dx = (p1.m_y - p2.m_y) / (m_slope + (1.0 / m_slope)); + wxDouble dy = (m_slope * dx + p2.m_y) - p1.m_y; + return sqrt(dx * dx + dy * dy); + } + + inline static wxDouble GetSlope(wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2) + { + return (y2 - y1) / (x2 - x1); + } + inline static wxDouble GetSlope(const wxPoint2DDouble &pt1, const wxPoint2DDouble &pt2) + { + return (pt2.m_y - pt1.m_y) / (pt2.m_x - pt1.m_x); + } + + // find the point where the two rays meet, return false if parallel + bool Intersect(const wxRay2DDouble &other, wxPoint2DDouble &pt) const + { + // (y1-y0)/(x1-x0)=m for both lines, equate y1's first + if (m_slope == other.m_slope) { + return false; + } + pt.m_x = + (m_slope * m_x - other.m_slope * other.m_x + other.m_y - m_y) / (m_slope - other.m_slope); + pt.m_y = GetYFromX(pt.m_x); + return true; + } + + // Operators + + inline wxRay2DDouble operator=(const wxRay2DDouble &r) + { + m_x = r.m_x; + m_y = r.m_y; + m_slope = r.m_slope; + return *this; + } + inline bool operator==(const wxRay2DDouble &r) const + { + return (m_x == r.m_x) && (m_y == r.m_y) && (m_slope == r.m_slope); + } + inline bool operator!=(const wxRay2DDouble &r) const { return !(*this == r); } + + inline wxRay2DDouble operator+(const wxPoint2DDouble &rel_pos) const + { + return wxRay2DDouble(m_x + rel_pos.m_x, m_y + rel_pos.m_y, m_slope); + } + inline wxRay2DDouble operator-(const wxPoint2DDouble &rel_pos) const + { + return wxRay2DDouble(m_x - rel_pos.m_x, m_y - rel_pos.m_y, m_slope); + } + inline wxRay2DDouble operator*(const wxPoint2DDouble &rel_pos) const + { + return wxRay2DDouble(m_x * rel_pos.m_x, m_y * rel_pos.m_y, m_slope); + } + inline wxRay2DDouble operator/(const wxPoint2DDouble &rel_pos) const + { + return wxRay2DDouble(m_x / rel_pos.m_x, m_y / rel_pos.m_y, m_slope); + } + + inline wxRay2DDouble &operator+=(const wxPoint2DDouble &rel_pos) + { + m_x += rel_pos.m_x; + m_y += rel_pos.m_y; + return *this; + } + inline wxRay2DDouble &operator-=(const wxPoint2DDouble &rel_pos) + { + m_x -= rel_pos.m_x; + m_y -= rel_pos.m_y; + return *this; + } + inline wxRay2DDouble &operator*=(const wxPoint2DDouble &rel_pos) + { + m_x *= rel_pos.m_x; + m_y *= rel_pos.m_y; + return *this; + } + inline wxRay2DDouble &operator/=(const wxPoint2DDouble &rel_pos) + { + m_x /= rel_pos.m_x; + m_y /= rel_pos.m_y; + return *this; + } + + inline wxRay2DDouble operator+(const wxDouble &rel_slope) const + { + return wxRay2DDouble(m_x, m_y, m_slope + rel_slope); + } + inline wxRay2DDouble operator-(const wxDouble &rel_slope) const + { + return wxRay2DDouble(m_x, m_y, m_slope - rel_slope); + } + inline wxRay2DDouble operator*(const wxDouble &rel_slope) const + { + return wxRay2DDouble(m_x, m_y, m_slope * rel_slope); + } + inline wxRay2DDouble operator/(const wxDouble &rel_slope) const + { + return wxRay2DDouble(m_x, m_y, m_slope / rel_slope); + } + + inline wxRay2DDouble &operator+=(const wxDouble &rel_slope) + { + m_slope += rel_slope; + return *this; + } + inline wxRay2DDouble &operator-=(const wxDouble &rel_slope) + { + m_slope -= rel_slope; + return *this; + } + inline wxRay2DDouble &operator*=(const wxDouble &rel_slope) + { + m_slope *= rel_slope; + return *this; + } + inline wxRay2DDouble &operator/=(const wxDouble &rel_slope) + { + m_slope /= rel_slope; + return *this; + } + + wxDouble m_slope; }; //----------------------------------------------------------------------------- @@ -172,9 +299,9 @@ public : inline wxLine2DInt(wxInt32 x1=0, wxInt32 y1=0, wxInt32 x2=0, wxInt32 y2=0) { m_x = x1; m_y = y1; m_width = x2 - x1; m_height = y2 - y1; } inline wxLine2DInt(const wxPoint2DInt &pt1, const wxPoint2DInt &pt2) - { m_x = pt1.m_x; m_y = pt1.m_y; m_width = pt2.m_x - pt1.m_x; m_height = pt2.m_y - pt1.m_y; } - inline wxLine2DInt(const wxLine2DInt &line) - { m_x = line.m_x; m_y = line.m_y; m_width = line.m_width; m_height = line.m_height; } + { m_x = pt1.m_x; m_y = pt1.m_y; m_width = pt2.m_x - pt1.m_x; m_height = pt2.m_y - pt1.m_y; +} inline wxLine2DInt(const wxLine2DInt &line) { m_x = line.m_x; m_y = line.m_y; m_width = +line.m_width; m_height = line.m_height; } inline wxInt32 GetX1() const { return m_x; } inline wxInt32 GetY1() const { return m_y; } @@ -191,8 +318,9 @@ public : inline void SetPoint1(const wxPoint2DInt &pt ) { SetTopLeft(pt); } inline void SetPoint2(const wxPoint2DInt &pt ) { SetBottomRight(pt); } - inline wxDouble GetYFromX(wxDouble x) const {return (wxDouble(m_height)/m_width)*(x-m_x) + m_y;} - inline wxDouble GetXFromY(wxDouble y) const {return (y-m_y)*(wxDouble(m_height)/m_width) + m_x;} + inline wxDouble GetYFromX(wxDouble x) const {return (wxDouble(m_height)/m_width)*(x-m_x) + +m_y;} inline wxDouble GetXFromY(wxDouble y) const {return (y-m_y)*(wxDouble(m_height)/m_width) + +m_x;} // Get a point along the line at pos x or y inline wxPoint2DInt GetPointOnLineFromX(wxInt32 x) const @@ -210,7 +338,8 @@ public : inline wxLine2DInt GetTranslatedLineByY(wxDouble y) { return wxLine2DInt(GetXFromY(y), y, m_slope); } - inline wxDouble GetDistanceToPoint(const wxPoint2DDouble &pt, wxPoint2DDouble *closestPt=NULL) const + inline wxDouble GetDistanceToPoint(const wxPoint2DDouble &pt, wxPoint2DDouble *closestPt=NULL) +const { wxPoint2DDouble l1(m_pt); wxPoint2DDouble l2(GetPointOnLineFromX(m_pt.m_x+pt.m_x)); @@ -243,217 +372,433 @@ public : // wxCircleDouble m_r*m_r = (x-m_origin.m_x)^2 + (y-m_origin.m_y)^2 //----------------------------------------------------------------------------- -class WXDLLIMPEXP_THINGS wxCircleDouble : public wxPoint2DDouble -{ -public : - - inline wxCircleDouble(const wxCircleDouble &circle) - { m_x = circle.m_x; m_y = circle.m_y; m_r = circle.m_r; } - - inline wxCircleDouble(wxDouble x=0, wxDouble y=0, wxDouble r=0) - { m_x = x; m_y = y; m_r = r; } - - inline wxCircleDouble(const wxPoint2DDouble &origin, wxDouble r) - { m_x = origin.m_x; m_y = origin.m_y; m_r = r; } - - inline wxCircleDouble(const wxPoint2DDouble &p1, - const wxPoint2DDouble &p2, - const wxPoint2DDouble &p3); - - inline bool IsEmpty() const { return m_r <= 0; } - - inline wxDouble GetX() const { return m_x; } - inline wxDouble GetY() const { return m_y; } - inline wxPoint2DDouble GetOrigin() const { return wxPoint2DDouble(m_x, m_y); } - inline wxDouble GetRadius() const { return m_r; } - - // Get a bounding rect - inline wxRect2DDouble GetRect() const - { return wxRect2DDouble(m_x-m_r, m_y-m_r, 2.0*m_r, 2.0*m_r); } - - inline void SetX(wxDouble x) { m_x = x; } - inline void SetY(wxDouble y) { m_y = y; } - inline void SetOrigin(const wxPoint2DDouble &origin) { m_x = origin.m_x; m_y = origin.m_y; } - inline void SetRadius(wxDouble r) { m_r = r; } - - inline bool GetPointInCircle(wxDouble x, wxDouble y) const - { if (IsEmpty()) return false; - return ((x-m_x)*(x-m_x) + (y-m_y)*(y-m_y) <= m_r*m_r); } - - inline bool GetPointInCircle(const wxPoint2DDouble &pt) const - { return GetPointInCircle(pt.m_x, pt.m_y); } - - inline bool Intersects(const wxCircleDouble &circle) const - { return GetDistance(circle) <= m_r + circle.m_r; } - - int IntersectLine( const wxRay2DDouble &line, - wxPoint2DDouble *pt1=NULL, - wxPoint2DDouble *pt2=NULL ) const; - - // Operators - - inline wxCircleDouble operator=(const wxCircleDouble& c) { m_x = c.m_x; m_y = c.m_y; m_r = c.m_r; return *this; } - inline bool operator==(const wxCircleDouble& c) const { return (m_x == c.m_x)&&(m_y == c.m_y)&&(m_r == c.m_r); } - inline bool operator!=(const wxCircleDouble& c) const { return !(*this == c); } - - inline wxCircleDouble operator+(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x+rel_origin.m_x, m_y+rel_origin.m_y, m_r); } - inline wxCircleDouble operator-(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x-rel_origin.m_x, m_y-rel_origin.m_y, m_r); } - inline wxCircleDouble operator*(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x*rel_origin.m_x, m_y*rel_origin.m_y, m_r); } - inline wxCircleDouble operator/(const wxPoint2DDouble& rel_origin) const { return wxCircleDouble(m_x/rel_origin.m_x, m_y/rel_origin.m_y, m_r); } - - inline wxCircleDouble& operator+=(const wxPoint2DDouble& rel_origin) { m_x += rel_origin.m_x; m_y += rel_origin.m_y; return *this; } - inline wxCircleDouble& operator-=(const wxPoint2DDouble& rel_origin) { m_x -= rel_origin.m_x; m_y -= rel_origin.m_y; return *this; } - inline wxCircleDouble& operator*=(const wxPoint2DDouble& rel_origin) { m_x *= rel_origin.m_x; m_y *= rel_origin.m_y; return *this; } - inline wxCircleDouble& operator/=(const wxPoint2DDouble& rel_origin) { m_x /= rel_origin.m_x; m_y /= rel_origin.m_y; return *this; } - - inline wxCircleDouble operator+(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r+rel_radius); } - inline wxCircleDouble operator-(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r-rel_radius); } - inline wxCircleDouble operator*(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r*rel_radius); } - inline wxCircleDouble operator/(const wxDouble& rel_radius) const { return wxCircleDouble(m_x, m_y, m_r/rel_radius); } - - inline wxCircleDouble& operator+=(const wxDouble& rel_radius) { m_r += rel_radius; return *this; } - inline wxCircleDouble& operator-=(const wxDouble& rel_radius) { m_r -= rel_radius; return *this; } - inline wxCircleDouble& operator*=(const wxDouble& rel_radius) { m_r *= rel_radius; return *this; } - inline wxCircleDouble& operator/=(const wxDouble& rel_radius) { m_r /= rel_radius; return *this; } - - wxDouble m_r; +class WXDLLIMPEXP_THINGS wxCircleDouble : public wxPoint2DDouble { +public: + inline wxCircleDouble(const wxCircleDouble &circle) + { + m_x = circle.m_x; + m_y = circle.m_y; + m_r = circle.m_r; + } + + inline wxCircleDouble(wxDouble x = 0, wxDouble y = 0, wxDouble r = 0) + { + m_x = x; + m_y = y; + m_r = r; + } + + inline wxCircleDouble(const wxPoint2DDouble &origin, wxDouble r) + { + m_x = origin.m_x; + m_y = origin.m_y; + m_r = r; + } + + inline wxCircleDouble(const wxPoint2DDouble &p1, const wxPoint2DDouble &p2, + const wxPoint2DDouble &p3); + + inline bool IsEmpty() const { return m_r <= 0; } + + inline wxDouble GetX() const { return m_x; } + inline wxDouble GetY() const { return m_y; } + inline wxPoint2DDouble GetOrigin() const { return wxPoint2DDouble(m_x, m_y); } + inline wxDouble GetRadius() const { return m_r; } + + // Get a bounding rect + inline wxRect2DDouble GetRect() const + { + return wxRect2DDouble(m_x - m_r, m_y - m_r, 2.0 * m_r, 2.0 * m_r); + } + + inline void SetX(wxDouble x) { m_x = x; } + inline void SetY(wxDouble y) { m_y = y; } + inline void SetOrigin(const wxPoint2DDouble &origin) + { + m_x = origin.m_x; + m_y = origin.m_y; + } + inline void SetRadius(wxDouble r) { m_r = r; } + + inline bool GetPointInCircle(wxDouble x, wxDouble y) const + { + if (IsEmpty()) { + return false; + } + return ((x - m_x) * (x - m_x) + (y - m_y) * (y - m_y) <= m_r * m_r); + } + + inline bool GetPointInCircle(const wxPoint2DDouble &pt) const + { + return GetPointInCircle(pt.m_x, pt.m_y); + } + + inline bool Intersects(const wxCircleDouble &circle) const + { + return GetDistance(circle) <= m_r + circle.m_r; + } + + int IntersectLine(const wxRay2DDouble &line, wxPoint2DDouble *pt1 = NULL, + wxPoint2DDouble *pt2 = NULL) const; + + // Operators + + inline wxCircleDouble operator=(const wxCircleDouble &c) + { + m_x = c.m_x; + m_y = c.m_y; + m_r = c.m_r; + return *this; + } + inline bool operator==(const wxCircleDouble &c) const + { + return (m_x == c.m_x) && (m_y == c.m_y) && (m_r == c.m_r); + } + inline bool operator!=(const wxCircleDouble &c) const { return !(*this == c); } + + inline wxCircleDouble operator+(const wxPoint2DDouble &rel_origin) const + { + return wxCircleDouble(m_x + rel_origin.m_x, m_y + rel_origin.m_y, m_r); + } + inline wxCircleDouble operator-(const wxPoint2DDouble &rel_origin) const + { + return wxCircleDouble(m_x - rel_origin.m_x, m_y - rel_origin.m_y, m_r); + } + inline wxCircleDouble operator*(const wxPoint2DDouble &rel_origin) const + { + return wxCircleDouble(m_x * rel_origin.m_x, m_y * rel_origin.m_y, m_r); + } + inline wxCircleDouble operator/(const wxPoint2DDouble &rel_origin) const + { + return wxCircleDouble(m_x / rel_origin.m_x, m_y / rel_origin.m_y, m_r); + } + + inline wxCircleDouble &operator+=(const wxPoint2DDouble &rel_origin) + { + m_x += rel_origin.m_x; + m_y += rel_origin.m_y; + return *this; + } + inline wxCircleDouble &operator-=(const wxPoint2DDouble &rel_origin) + { + m_x -= rel_origin.m_x; + m_y -= rel_origin.m_y; + return *this; + } + inline wxCircleDouble &operator*=(const wxPoint2DDouble &rel_origin) + { + m_x *= rel_origin.m_x; + m_y *= rel_origin.m_y; + return *this; + } + inline wxCircleDouble &operator/=(const wxPoint2DDouble &rel_origin) + { + m_x /= rel_origin.m_x; + m_y /= rel_origin.m_y; + return *this; + } + + inline wxCircleDouble operator+(const wxDouble &rel_radius) const + { + return wxCircleDouble(m_x, m_y, m_r + rel_radius); + } + inline wxCircleDouble operator-(const wxDouble &rel_radius) const + { + return wxCircleDouble(m_x, m_y, m_r - rel_radius); + } + inline wxCircleDouble operator*(const wxDouble &rel_radius) const + { + return wxCircleDouble(m_x, m_y, m_r * rel_radius); + } + inline wxCircleDouble operator/(const wxDouble &rel_radius) const + { + return wxCircleDouble(m_x, m_y, m_r / rel_radius); + } + + inline wxCircleDouble &operator+=(const wxDouble &rel_radius) + { + m_r += rel_radius; + return *this; + } + inline wxCircleDouble &operator-=(const wxDouble &rel_radius) + { + m_r -= rel_radius; + return *this; + } + inline wxCircleDouble &operator*=(const wxDouble &rel_radius) + { + m_r *= rel_radius; + return *this; + } + inline wxCircleDouble &operator/=(const wxDouble &rel_radius) + { + m_r /= rel_radius; + return *this; + } + + wxDouble m_r; }; //----------------------------------------------------------------------------- // wxCircleInt m_r*m_r = (x-m_origin.m_x)^2 + (y-m_origin.m_y)^2 //----------------------------------------------------------------------------- -class WXDLLEXPORT wxCircleInt : public wxPoint2DInt -{ -public : - - inline wxCircleInt(wxInt32 x=0, wxInt32 y=0, wxInt32 r=0) - { m_x = x; m_y = y; m_r = r; } - inline wxCircleInt(const wxPoint2DInt &origin, wxInt32 r) - { m_x = origin.m_x; m_y = origin.m_y; m_r = r; } - inline wxCircleInt(const wxCircleInt &circle) - { m_x = circle.m_x; m_y = circle.m_y; m_r = circle.m_r; } - - inline bool IsEmpty() const { return m_r <= 0; } - - inline wxInt32 GetX() const { return m_x; } - inline wxInt32 GetY() const { return m_y; } - inline wxPoint2DInt GetOrigin() const { return wxPoint2DInt(m_x, m_y); } - inline wxInt32 GetRadius() const { return m_r; } - - // Get a bounding rect - inline wxRect2DInt GetRect() const - { return wxRect2DInt(m_x-m_r, m_y-m_r, 2*m_r, 2*m_r); } - - inline void SetX(wxInt32 x) { m_x = x; } - inline void SetY(wxInt32 y) { m_y = y; } - inline void SetOrigin(const wxPoint2DInt &origin) { m_x = origin.m_x; m_y = origin.m_y; } - inline void SetRadius(wxInt32 r) { m_r = r; } - - inline bool GetPointInCircle(wxInt32 x, wxInt32 y) const - { if (IsEmpty()) return false; - return ((x-m_x)*(x-m_x) + (y-m_y)*(y-m_y) <= m_r*m_r); } - - inline bool GetPointInCircle(const wxPoint2DInt &pt) const - { return GetPointInCircle(pt.m_x, pt.m_y); } - - inline bool Intersects(const wxCircleInt &circle) const - { return GetDistance(circle) <= m_r + circle.m_r; } - -// int IntersectLine( const wxRay2DDouble &line, -// wxPoint2DInt *pt1=NULL, -// wxPoint2DInt *pt2=NULL ) const; - - // Operators - - inline wxCircleInt operator=(const wxCircleInt& c) { m_x = c.m_x; m_y = c.m_y; m_r = c.m_r; return *this; } - inline bool operator==(const wxCircleInt& c) const { return (m_x == c.m_x)&&(m_y == c.m_y)&&(m_r == c.m_r); } - inline bool operator!=(const wxCircleInt& c) const { return !(*this == c); } - - inline wxCircleInt operator+(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x+rel_origin.m_x, m_y+rel_origin.m_y, m_r); } - inline wxCircleInt operator-(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x-rel_origin.m_x, m_y-rel_origin.m_y, m_r); } - inline wxCircleInt operator*(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x*rel_origin.m_x, m_y*rel_origin.m_y, m_r); } - inline wxCircleInt operator/(const wxPoint2DInt& rel_origin) const { return wxCircleInt(m_x/rel_origin.m_x, m_y/rel_origin.m_y, m_r); } - - inline wxCircleInt& operator+=(const wxPoint2DInt& rel_origin) { m_x += rel_origin.m_x; m_y += rel_origin.m_y; return *this; } - inline wxCircleInt& operator-=(const wxPoint2DInt& rel_origin) { m_x -= rel_origin.m_x; m_y -= rel_origin.m_y; return *this; } - inline wxCircleInt& operator*=(const wxPoint2DInt& rel_origin) { m_x *= rel_origin.m_x; m_y *= rel_origin.m_y; return *this; } - inline wxCircleInt& operator/=(const wxPoint2DInt& rel_origin) { m_x /= rel_origin.m_x; m_y /= rel_origin.m_y; return *this; } - - inline wxCircleInt operator+(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r+rel_radius); } - inline wxCircleInt operator-(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r-rel_radius); } - inline wxCircleInt operator*(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r*rel_radius); } - inline wxCircleInt operator/(const wxInt32& rel_radius) const { return wxCircleInt(m_x, m_y, m_r/rel_radius); } - - inline wxCircleInt& operator+=(const wxInt32& rel_radius) { m_r += rel_radius; return *this; } - inline wxCircleInt& operator-=(const wxInt32& rel_radius) { m_r -= rel_radius; return *this; } - inline wxCircleInt& operator*=(const wxInt32& rel_radius) { m_r *= rel_radius; return *this; } - inline wxCircleInt& operator/=(const wxInt32& rel_radius) { m_r /= rel_radius; return *this; } - - wxInt32 m_r; +class WXDLLEXPORT wxCircleInt : public wxPoint2DInt { +public: + inline wxCircleInt(wxInt32 x = 0, wxInt32 y = 0, wxInt32 r = 0) + { + m_x = x; + m_y = y; + m_r = r; + } + inline wxCircleInt(const wxPoint2DInt &origin, wxInt32 r) + { + m_x = origin.m_x; + m_y = origin.m_y; + m_r = r; + } + inline wxCircleInt(const wxCircleInt &circle) + { + m_x = circle.m_x; + m_y = circle.m_y; + m_r = circle.m_r; + } + + inline bool IsEmpty() const { return m_r <= 0; } + + inline wxInt32 GetX() const { return m_x; } + inline wxInt32 GetY() const { return m_y; } + inline wxPoint2DInt GetOrigin() const { return wxPoint2DInt(m_x, m_y); } + inline wxInt32 GetRadius() const { return m_r; } + + // Get a bounding rect + inline wxRect2DInt GetRect() const + { + return wxRect2DInt(m_x - m_r, m_y - m_r, 2 * m_r, 2 * m_r); + } + + inline void SetX(wxInt32 x) { m_x = x; } + inline void SetY(wxInt32 y) { m_y = y; } + inline void SetOrigin(const wxPoint2DInt &origin) + { + m_x = origin.m_x; + m_y = origin.m_y; + } + inline void SetRadius(wxInt32 r) { m_r = r; } + + inline bool GetPointInCircle(wxInt32 x, wxInt32 y) const + { + if (IsEmpty()) { + return false; + } + return ((x - m_x) * (x - m_x) + (y - m_y) * (y - m_y) <= m_r * m_r); + } + + inline bool GetPointInCircle(const wxPoint2DInt &pt) const + { + return GetPointInCircle(pt.m_x, pt.m_y); + } + + inline bool Intersects(const wxCircleInt &circle) const + { + return GetDistance(circle) <= m_r + circle.m_r; + } + + // int IntersectLine( const wxRay2DDouble &line, + // wxPoint2DInt *pt1=NULL, + // wxPoint2DInt *pt2=NULL ) const; + + // Operators + + inline wxCircleInt operator=(const wxCircleInt &c) + { + m_x = c.m_x; + m_y = c.m_y; + m_r = c.m_r; + return *this; + } + inline bool operator==(const wxCircleInt &c) const + { + return (m_x == c.m_x) && (m_y == c.m_y) && (m_r == c.m_r); + } + inline bool operator!=(const wxCircleInt &c) const { return !(*this == c); } + + inline wxCircleInt operator+(const wxPoint2DInt &rel_origin) const + { + return wxCircleInt(m_x + rel_origin.m_x, m_y + rel_origin.m_y, m_r); + } + inline wxCircleInt operator-(const wxPoint2DInt &rel_origin) const + { + return wxCircleInt(m_x - rel_origin.m_x, m_y - rel_origin.m_y, m_r); + } + inline wxCircleInt operator*(const wxPoint2DInt &rel_origin) const + { + return wxCircleInt(m_x * rel_origin.m_x, m_y * rel_origin.m_y, m_r); + } + inline wxCircleInt operator/(const wxPoint2DInt &rel_origin) const + { + return wxCircleInt(m_x / rel_origin.m_x, m_y / rel_origin.m_y, m_r); + } + + inline wxCircleInt &operator+=(const wxPoint2DInt &rel_origin) + { + m_x += rel_origin.m_x; + m_y += rel_origin.m_y; + return *this; + } + inline wxCircleInt &operator-=(const wxPoint2DInt &rel_origin) + { + m_x -= rel_origin.m_x; + m_y -= rel_origin.m_y; + return *this; + } + inline wxCircleInt &operator*=(const wxPoint2DInt &rel_origin) + { + m_x *= rel_origin.m_x; + m_y *= rel_origin.m_y; + return *this; + } + inline wxCircleInt &operator/=(const wxPoint2DInt &rel_origin) + { + m_x /= rel_origin.m_x; + m_y /= rel_origin.m_y; + return *this; + } + + inline wxCircleInt operator+(const wxInt32 &rel_radius) const + { + return wxCircleInt(m_x, m_y, m_r + rel_radius); + } + inline wxCircleInt operator-(const wxInt32 &rel_radius) const + { + return wxCircleInt(m_x, m_y, m_r - rel_radius); + } + inline wxCircleInt operator*(const wxInt32 &rel_radius) const + { + return wxCircleInt(m_x, m_y, m_r * rel_radius); + } + inline wxCircleInt operator/(const wxInt32 &rel_radius) const + { + return wxCircleInt(m_x, m_y, m_r / rel_radius); + } + + inline wxCircleInt &operator+=(const wxInt32 &rel_radius) + { + m_r += rel_radius; + return *this; + } + inline wxCircleInt &operator-=(const wxInt32 &rel_radius) + { + m_r -= rel_radius; + return *this; + } + inline wxCircleInt &operator*=(const wxInt32 &rel_radius) + { + m_r *= rel_radius; + return *this; + } + inline wxCircleInt &operator/=(const wxInt32 &rel_radius) + { + m_r /= rel_radius; + return *this; + } + + wxInt32 m_r; }; //----------------------------------------------------------------------------- // wxEllipseInt m_r*m_r = (x-m_origin.m_x)^2 + (y-m_origin.m_y)^2 //----------------------------------------------------------------------------- -class WXDLLEXPORT wxEllipseInt -{ -public : - - inline wxEllipseInt(wxInt32 x=0, wxInt32 y=0, wxInt32 r_x=0, wxInt32 r_y=0) - { m_origin.m_x=x; m_origin.m_y=y; m_radius.m_x=r_x; m_radius.m_y=r_y; } - inline wxEllipseInt(const wxPoint2DInt &origin, const wxPoint2DInt radius) - { m_origin = origin; m_radius = radius; } - inline wxEllipseInt(const wxEllipseInt &ellipse) - { m_origin = ellipse.m_origin; m_radius = ellipse.m_radius; } - - inline bool IsEmpty() const { return m_radius.m_x<=0 || m_radius.m_y<=0; } - - inline wxInt32 GetX() const { return m_origin.m_x; } - inline wxInt32 GetY() const { return m_origin.m_y; } - inline wxPoint2DInt GetOrigin() const { return m_origin; } - inline wxInt32 GetXRadius() const { return m_radius.m_x; } - inline wxInt32 GetYRadius() const { return m_radius.m_y; } - inline wxPoint2DInt GetRadius() const { return m_radius; } - - // Get a bounding rect - inline wxRect2DInt GetRect() const - { return wxRect2DInt(m_origin.m_x-m_radius.m_x, - m_origin.m_y-m_radius.m_y, - 2*m_radius.m_x, 2*m_radius.m_y); } - - inline void SetX(wxInt32 x) { m_origin.m_x = x; } - inline void SetY(wxInt32 y) { m_origin.m_y = y; } - inline void SetOrigin(const wxPoint2DInt &origin) { m_origin = origin; } - inline void SetXRadius(wxInt32 r_x) { m_radius.m_x = r_x; } - inline void SetYRadius(wxInt32 r_y) { m_radius.m_y = r_y; } - inline void SetRadius(const wxPoint2DInt &radius) { m_radius = radius; } - - inline bool GetPointInEllipse(wxInt32 x, wxInt32 y) const - { if (IsEmpty()) return false; - return (((x-m_origin.m_x)*(x-m_origin.m_x))/m_radius.m_x + - ((y-m_origin.m_y)*(y-m_origin.m_y))/m_radius.m_y <= 1); } - - inline bool GetPointInEllipse(const wxPoint2DInt &pt) const - { return GetPointInEllipse(pt.m_x, pt.m_y); } - -// int IntersectLine( const wxRay2DDouble &line, -// wxPoint2DInt *pt1=NULL, -// wxPoint2DInt *pt2=NULL ) const; - - - inline bool operator==(const wxEllipseInt& c) const { return (m_origin == c.m_origin)&&(m_radius == c.m_radius); } - inline bool operator!=(const wxEllipseInt& c) const { return !(*this == c); } - - inline wxEllipseInt operator+(const wxPoint2DInt& rel_origin) const { return wxEllipseInt(m_origin+rel_origin, m_radius); } - inline wxEllipseInt& operator+=(const wxPoint2DInt& rel_origin) { m_origin += rel_origin; return *this; } - inline wxEllipseInt operator-(const wxPoint2DInt& rel_origin) const { return wxEllipseInt(m_origin-rel_origin, m_radius); } - inline wxEllipseInt& operator-=(const wxPoint2DInt& rel_origin) { m_origin -= rel_origin; return *this; } - - wxPoint2DInt m_radius; - wxPoint2DInt m_origin; +class WXDLLEXPORT wxEllipseInt { +public: + inline wxEllipseInt(wxInt32 x = 0, wxInt32 y = 0, wxInt32 r_x = 0, wxInt32 r_y = 0) + { + m_origin.m_x = x; + m_origin.m_y = y; + m_radius.m_x = r_x; + m_radius.m_y = r_y; + } + inline wxEllipseInt(const wxPoint2DInt &origin, const wxPoint2DInt radius) + { + m_origin = origin; + m_radius = radius; + } + inline wxEllipseInt(const wxEllipseInt &ellipse) + { + m_origin = ellipse.m_origin; + m_radius = ellipse.m_radius; + } + + inline bool IsEmpty() const { return m_radius.m_x <= 0 || m_radius.m_y <= 0; } + + inline wxInt32 GetX() const { return m_origin.m_x; } + inline wxInt32 GetY() const { return m_origin.m_y; } + inline wxPoint2DInt GetOrigin() const { return m_origin; } + inline wxInt32 GetXRadius() const { return m_radius.m_x; } + inline wxInt32 GetYRadius() const { return m_radius.m_y; } + inline wxPoint2DInt GetRadius() const { return m_radius; } + + // Get a bounding rect + inline wxRect2DInt GetRect() const + { + return wxRect2DInt(m_origin.m_x - m_radius.m_x, m_origin.m_y - m_radius.m_y, 2 * m_radius.m_x, + 2 * m_radius.m_y); + } + + inline void SetX(wxInt32 x) { m_origin.m_x = x; } + inline void SetY(wxInt32 y) { m_origin.m_y = y; } + inline void SetOrigin(const wxPoint2DInt &origin) { m_origin = origin; } + inline void SetXRadius(wxInt32 r_x) { m_radius.m_x = r_x; } + inline void SetYRadius(wxInt32 r_y) { m_radius.m_y = r_y; } + inline void SetRadius(const wxPoint2DInt &radius) { m_radius = radius; } + + inline bool GetPointInEllipse(wxInt32 x, wxInt32 y) const + { + if (IsEmpty()) { + return false; + } + return (((x - m_origin.m_x) * (x - m_origin.m_x)) / m_radius.m_x + + ((y - m_origin.m_y) * (y - m_origin.m_y)) / m_radius.m_y <= + 1); + } + + inline bool GetPointInEllipse(const wxPoint2DInt &pt) const + { + return GetPointInEllipse(pt.m_x, pt.m_y); + } + + // int IntersectLine( const wxRay2DDouble &line, + // wxPoint2DInt *pt1=NULL, + // wxPoint2DInt *pt2=NULL ) const; + + inline bool operator==(const wxEllipseInt &c) const + { + return (m_origin == c.m_origin) && (m_radius == c.m_radius); + } + inline bool operator!=(const wxEllipseInt &c) const { return !(*this == c); } + + inline wxEllipseInt operator+(const wxPoint2DInt &rel_origin) const + { + return wxEllipseInt(m_origin + rel_origin, m_radius); + } + inline wxEllipseInt &operator+=(const wxPoint2DInt &rel_origin) + { + m_origin += rel_origin; + return *this; + } + inline wxEllipseInt operator-(const wxPoint2DInt &rel_origin) const + { + return wxEllipseInt(m_origin - rel_origin, m_radius); + } + inline wxEllipseInt &operator-=(const wxPoint2DInt &rel_origin) + { + m_origin -= rel_origin; + return *this; + } + + wxPoint2DInt m_radius; + wxPoint2DInt m_origin; }; - #endif // __WXIMAGER_GEOMETRY_H__ diff --git a/src/labenski/include/wx/wxthings/medsort.h b/src/labenski/include/wx/wxthings/medsort.h index b33b51454..e0992bfe6 100644 --- a/src/labenski/include/wx/wxthings/medsort.h +++ b/src/labenski/include/wx/wxthings/medsort.h @@ -38,7 +38,6 @@ IMPLEMENT_WIRTHS_MEDIAN(int, arr, n, &median) */ - /*--------------------------------------------------------------------------- * This Quickselect routine is based on the algorithm described in * "Numerical recipes in C", Second Edition, @@ -56,58 +55,91 @@ ---------------------------------------------------------------------------*/ -#define DECLARE_QUICK_SELECT( name, elem_type ) \ - elem_type name( elem_type *arr, int n, elem_type &median ); - -#define DEFINE_QUICK_SELECT( name, elem_type ) \ - elem_type name( elem_type *arr, int n, elem_type &median ) \ - IMPLEMENT_QUICK_SELECT( elem_type, arr, n, median ) - -#define IMPLEMENT_QUICK_SELECT(elem_type, arr, n, median) \ -{ \ - int low=0, high=n-1, half=(low+high)/2, middle, ll, hh; \ - \ - for (;;) { \ - if (high <= low) /* One element only */ \ - break; /*return arr[half] ; */ \ - \ - if (high == low + 1) { /* Two elements only */ \ - if (arr[low] > arr[high]) \ - { register elem_type t=arr[low];arr[low]=arr[high];arr[high]=t; } \ - break; /* return arr[half] ; */ \ - } \ - \ - /* Find median of low, middle and high items; swap into low */ \ - middle = (low + high) / 2; \ - if (arr[middle] > arr[high]) { register elem_type t=arr[middle];arr[middle]=arr[high];arr[high]=t; } \ - if (arr[low] > arr[high]) { register elem_type t=arr[low]; arr[low] =arr[high];arr[high]=t; } \ - if (arr[middle] > arr[low] ) { register elem_type t=arr[middle];arr[middle]=arr[low]; arr[low] =t; } \ - \ - /* Swap low item (now in position middle) into position (low+1) */ \ - { register elem_type t=arr[middle];arr[middle]=arr[low+1];arr[low+1]=t; } \ - \ - /* Nibble from ends towards middle, swapping items when stuck */ \ - ll = low + 1; \ - hh = high; \ - for (;;) { \ - do ll++; while (arr[low] > arr[ll] ); \ - do hh--; while (arr[hh] > arr[low]); \ - \ - if (hh < ll) break; \ - \ - { register elem_type t=arr[ll];arr[ll]=arr[hh];arr[hh]=t;} \ - } \ - \ - /* Swap middle item (in position low) back into correct position */ \ - { register elem_type t=arr[low];arr[low]=arr[hh];arr[hh]=t; } \ - \ - /* Re-set active partition */ \ - if (hh <= half) low = ll; \ - if (hh >= half) high = hh - 1; \ - } \ - median = arr[half]; \ -} - +#define DECLARE_QUICK_SELECT(name, elem_type) \ + elem_type name(elem_type *arr, int n, elem_type &median); + +#define DEFINE_QUICK_SELECT(name, elem_type) \ + elem_type name(elem_type *arr, int n, elem_type &median) \ + IMPLEMENT_QUICK_SELECT(elem_type, arr, n, median) + +#define IMPLEMENT_QUICK_SELECT(elem_type, arr, n, median) \ + { \ + int low = 0, high = n - 1, half = (low + high) / 2, middle, ll, hh; \ + \ + for (;;) { \ + if (high <= low) /* One element only */ \ + break; /*return arr[half] ; */ \ + \ + if (high == low + 1) { /* Two elements only */ \ + if (arr[low] > arr[high]) { \ + register elem_type t = arr[low]; \ + arr[low] = arr[high]; \ + arr[high] = t; \ + } \ + break; /* return arr[half] ; */ \ + } \ + \ + /* Find median of low, middle and high items; swap into low */ \ + middle = (low + high) / 2; \ + if (arr[middle] > arr[high]) { \ + register elem_type t = arr[middle]; \ + arr[middle] = arr[high]; \ + arr[high] = t; \ + } \ + if (arr[low] > arr[high]) { \ + register elem_type t = arr[low]; \ + arr[low] = arr[high]; \ + arr[high] = t; \ + } \ + if (arr[middle] > arr[low]) { \ + register elem_type t = arr[middle]; \ + arr[middle] = arr[low]; \ + arr[low] = t; \ + } \ + \ + /* Swap low item (now in position middle) into position (low+1) */ \ + { \ + register elem_type t = arr[middle]; \ + arr[middle] = arr[low + 1]; \ + arr[low + 1] = t; \ + } \ + \ + /* Nibble from ends towards middle, swapping items when stuck */ \ + ll = low + 1; \ + hh = high; \ + for (;;) { \ + do \ + ll++; \ + while (arr[low] > arr[ll]); \ + do \ + hh--; \ + while (arr[hh] > arr[low]); \ + \ + if (hh < ll) \ + break; \ + \ + { \ + register elem_type t = arr[ll]; \ + arr[ll] = arr[hh]; \ + arr[hh] = t; \ + } \ + } \ + \ + /* Swap middle item (in position low) back into correct position */ \ + { \ + register elem_type t = arr[low]; \ + arr[low] = arr[hh]; \ + arr[hh] = t; \ + } \ + \ + /* Re-set active partition */ \ + if (hh <= half) \ + low = ll; \ + if (hh >= half) \ + high = hh - 1; \ + } \ + median = arr[half]; \ + } /*--------------------------------------------------------------------------- Function : kth_smallest() @@ -139,45 +171,54 @@ ---------------------------------------------------------------------------*/ -#define DECLARE_WIRTHS_MEDIAN( name, elem_type ) \ - elem_type name( elem_type *arr, int n, elem_type &median ); - -#define DEFINE_WIRTHS_MEDIAN( name, elem_type ) \ - elem_type name( elem_type *arr, int n, elem_type &median ) \ - WIRTHS_MEDIAN( elem_type, arr, n, median ) - -#define IMPLEMENT_WIRTHS_MEDIAN(elem_type, arr, n, median) \ - IMPLEMENT_WIRTHS_KTH_SMALLEST(elem_type, arr, n, (((n)&1)?((n)/2):(((n)/2)-1)), median) - - -#define DECLARE_WIRTHS_KTH_SMALLEST( name, elem_type ) \ - elem_type name( elem_type *arr, int n, elem_type &median ); - -#define DEFINE_WIRTHS_KTH_SMALLEST( name, elem_type ) \ - elem_type name( elem_type *arr, int n, elem_type &median ) \ - IMPLEMENT_WIRTHS_MEDIAN( elem_type, arr, n, median ) - -#define IMPLEMENT_WIRTHS_KTH_SMALLEST(elem_type, arr, n, k, ksmallest) \ -{ \ - register int i, j, l=0, m=n-1; \ - register elem_type x; \ - \ - while (lmax) max=arr[i]; \ - } \ - \ - while (1) { \ - guess = (min+max)/2; \ - less = 0; greater = 0; equal = 0; \ - maxltguess = min; \ - mingtguess = max; \ - for (i=0; imaxltguess) maxltguess = arr[i]; \ - } else if (arr[i]>guess) { \ - greater++; \ - if (arr[i]greater) max = maxltguess; \ - else min = mingtguess; \ - } \ - if (less >= (n+1)/2) median = maxltguess; \ - else if (less+equal >= (n+1)/2) median = guess; \ - else median = mingtguess; \ -} +#define DECLARE_TORBEN_MEDIAN(name, elem_type) \ + elem_type name(elem_type *arr, int n, elem_type &median); + +#define DEFINE_TORBEN_MEDIAN(name, elem_type) \ + elem_type name(elem_type *arr, int n, elem_type &median) \ + IMPLEMENT_TORBEN_MEDIAN(elem_type, arr, n, median) + +#define IMPLEMENT_TORBEN_MEDIAN(elem_type, arr, n) \ + { \ + int i, less, greater, equal; \ + elem_type min, max, guess, maxltguess, mingtguess; \ + \ + min = max = arr[0]; \ + for (i = 1; i < n; i++) { \ + if (arr[i] < min) \ + min = arr[i]; \ + if (arr[i] > max) \ + max = arr[i]; \ + } \ + \ + while (1) { \ + guess = (min + max) / 2; \ + less = 0; \ + greater = 0; \ + equal = 0; \ + maxltguess = min; \ + mingtguess = max; \ + for (i = 0; i < n; i++) { \ + if (arr[i] < guess) { \ + less++; \ + if (arr[i] > maxltguess) \ + maxltguess = arr[i]; \ + } \ + else if (arr[i] > guess) { \ + greater++; \ + if (arr[i] < mingtguess) \ + mingtguess = arr[i]; \ + } \ + else \ + equal++; \ + } \ + if (less <= (n + 1) / 2 && greater <= (n + 1) / 2) \ + break; \ + else if (less > greater) \ + max = maxltguess; \ + else \ + min = mingtguess; \ + } \ + if (less >= (n + 1) / 2) \ + median = maxltguess; \ + else if (less + equal >= (n + 1) / 2) \ + median = guess; \ + else \ + median = mingtguess; \ + } /*---------------------------------------------------------------------------- Function : pixel_qsort() @@ -252,73 +308,101 @@ #define PIXEL_QSORT_STACK_SIZE 50 #define PIXEL_QSORT_THRESHOLD 7 -#define DECLARE_PIXEL_QSORT( name, elem_type ) \ - void name( elem_type *arr, int n ); - -#define DEFINE_PIXEL_QSORT( name, elem_type ) \ - void name( elem_type *arr, int n ) \ - IMPLEMENT_PIXEL_QSORT( name, elem_type ) - -#define IMPLEMENT_PIXEL_QSORT( elem_type, arr, n ) \ -{ \ - int i, ir=n, j, k, l=1, j_stack=0; \ - int *i_stack ; \ - elem_type a ; \ - \ - i_stack = (int*)malloc(PIXEL_QSORT_STACK_SIZE * sizeof(elem_type)); \ - for (;;) { \ - if (ir-l < PIXEL_QSORT_THRESHOLD) { \ - for (j=l+1 ; j<=ir ; j++) { \ - a = arr[j-1]; \ - for (i=j-1 ; i>=1 ; i--) { \ - if (arr[i-1] <= a) break; \ - arr[i] = arr[i-1]; \ - } \ - arr[i] = a; \ - } \ - if (j_stack == 0) break; \ - ir = i_stack[j_stack-- -1]; \ - l = i_stack[j_stack-- -1]; \ - } else { \ - k = (l+ir) >> 1; \ - { elem_type t=arr[k-1];arr[k-1]=arr[l];arr[l]=t; } \ - if (arr[l] > arr[ir-1]) { \ - { elem_type t=arr[l];arr[l]=arr[ir-1];arr[ir-1]=t; } \ - } \ - if (arr[l-1] > arr[ir-1]) { \ - { elem_type t=arr[l-1];arr[l-1]=arr[ir-1];arr[ir-1]=t; } \ - } \ - if (arr[l] > arr[l-1]) { \ - { elem_type t=arr[l];arr[l]=arr[l-1];arr[l-1]=t; } \ - } \ - i = l+1; j = ir; a = arr[l-1]; \ - for (;;) { \ - do i++; while (arr[i-1] < a); \ - do j--; while (arr[j-1] > a); \ - if (j < i) break; \ - { elem_type t=arr[i-1];arr[i-1]=arr[j-1];arr[j-1]=t; } \ - } \ - arr[l-1] = arr[j-1]; \ - arr[j-1] = a; \ - j_stack += 2; \ - wxASSERT(!(j_stack>PIXEL_QSORT_STACK_SIZE)); \ - /* if (j_stack > PIXEL_QSORT_STACK_SIZE) { */ \ - /* printf("stack too small in pixel_qsort: aborting"); */ \ - /* exit(-2001); } */ \ - if (ir-i+1 >= j-l) { \ - i_stack[j_stack-1] = ir; \ - i_stack[j_stack-2] = i; \ - ir = j-1; \ - } else { \ - i_stack[j_stack-1] = j-1; \ - i_stack[j_stack-2] = l; \ - l = i; \ - } \ - } \ - } \ - free(i_stack); \ -} - +#define DECLARE_PIXEL_QSORT(name, elem_type) void name(elem_type *arr, int n); + +#define DEFINE_PIXEL_QSORT(name, elem_type) \ + void name(elem_type *arr, int n) IMPLEMENT_PIXEL_QSORT(name, elem_type) + +#define IMPLEMENT_PIXEL_QSORT(elem_type, arr, n) \ + { \ + int i, ir = n, j, k, l = 1, j_stack = 0; \ + int *i_stack; \ + elem_type a; \ + \ + i_stack = (int *)malloc(PIXEL_QSORT_STACK_SIZE * sizeof(elem_type)); \ + for (;;) { \ + if (ir - l < PIXEL_QSORT_THRESHOLD) { \ + for (j = l + 1; j <= ir; j++) { \ + a = arr[j - 1]; \ + for (i = j - 1; i >= 1; i--) { \ + if (arr[i - 1] <= a) \ + break; \ + arr[i] = arr[i - 1]; \ + } \ + arr[i] = a; \ + } \ + if (j_stack == 0) \ + break; \ + ir = i_stack[j_stack-- - 1]; \ + l = i_stack[j_stack-- - 1]; \ + } \ + else { \ + k = (l + ir) >> 1; \ + { \ + elem_type t = arr[k - 1]; \ + arr[k - 1] = arr[l]; \ + arr[l] = t; \ + } \ + if (arr[l] > arr[ir - 1]) { \ + { \ + elem_type t = arr[l]; \ + arr[l] = arr[ir - 1]; \ + arr[ir - 1] = t; \ + } \ + } \ + if (arr[l - 1] > arr[ir - 1]) { \ + { \ + elem_type t = arr[l - 1]; \ + arr[l - 1] = arr[ir - 1]; \ + arr[ir - 1] = t; \ + } \ + } \ + if (arr[l] > arr[l - 1]) { \ + { \ + elem_type t = arr[l]; \ + arr[l] = arr[l - 1]; \ + arr[l - 1] = t; \ + } \ + } \ + i = l + 1; \ + j = ir; \ + a = arr[l - 1]; \ + for (;;) { \ + do \ + i++; \ + while (arr[i - 1] < a); \ + do \ + j--; \ + while (arr[j - 1] > a); \ + if (j < i) \ + break; \ + { \ + elem_type t = arr[i - 1]; \ + arr[i - 1] = arr[j - 1]; \ + arr[j - 1] = t; \ + } \ + } \ + arr[l - 1] = arr[j - 1]; \ + arr[j - 1] = a; \ + j_stack += 2; \ + wxASSERT(!(j_stack > PIXEL_QSORT_STACK_SIZE)); \ + /* if (j_stack > PIXEL_QSORT_STACK_SIZE) { */ \ + /* printf("stack too small in pixel_qsort: aborting"); */ \ + /* exit(-2001); } */ \ + if (ir - i + 1 >= j - l) { \ + i_stack[j_stack - 1] = ir; \ + i_stack[j_stack - 2] = i; \ + ir = j - 1; \ + } \ + else { \ + i_stack[j_stack - 1] = j - 1; \ + i_stack[j_stack - 2] = l; \ + l = i; \ + } \ + } \ + } \ + free(i_stack); \ + } /*------------------------------------------------------------------------- Function : pixel_qsort2() @@ -338,75 +422,122 @@ #define PIXEL_QSORT2_STACK_SIZE 50 #define PIXEL_QSORT2_THRESHOLD 7 -#define DECLARE_PIXEL_QSORT2( name, elem_type ) \ - void name( elem_type *arr, elem_type *arr2, int n ); - -#define DEFINE_PIXEL_QSORT2( name, elem_type ) \ - void name( elem_type *arr, elem_type *arr2, int n ) \ - IMPLEMENT_PIXEL_QSORT2( name, elem_type ) - -#define IMPLEMENT_PIXEL_QSORT2( elem_type, arr, arr2, n ) \ -{ \ - int i, ir=n, j, k, l=1, j_stack=0; \ - int *i_stack ; \ - elem_type a, a2 ; \ - \ - i_stack = (int*)malloc(PIXEL_QSORT2_STACK_SIZE * sizeof(elem_type)); \ - for (;;) { \ - if (ir-l < PIXEL_QSORT2_THRESHOLD) { \ - for (j=l+1 ; j<=ir ; j++) { \ - a = arr[j-1]; a2 = arr2[j-1]; \ - for (i=j-1 ; i>=1 ; i--) { \ - if (arr[i-1] <= a) break; \ - arr[i] = arr[i-1]; \ - arr2[i] = arr2[i-1]; \ - } \ - arr[i] = a; arr2[i] = a2; \ - } \ - if (j_stack == 0) break; \ - ir = i_stack[j_stack-- -1]; \ - l = i_stack[j_stack-- -1]; \ - } else { \ - k = (l+ir) >> 1; \ - { elem_type t=arr[k-1];arr[k-1]=arr[l];arr[l]=t; t=arr2[k-1];arr2[k-1]=arr2[l];arr2[l]=t; } \ - if (arr[l] > arr[ir-1]) { \ - { elem_type t=arr[l];arr[l]=arr[ir-1];arr[ir-1]=t; t=arr2[l];arr2[l]=arr2[ir-1];arr2[ir-1]=t;} \ - } \ - if (arr[l-1] > arr[ir-1]) { \ - { elem_type t=arr[l-1];arr[l-1]=arr[ir-1];arr[ir-1]=t; t=arr2[l-1];arr2[l-1]=arr2[ir-1];arr2[ir-1]=t;} \ - } \ - if (arr[l] > arr[l-1]) { \ - { elem_type t=arr[l];arr[l]=arr[l-1];arr[l-1]=t; t=arr2[l];arr2[l]=arr2[l-1];arr2[l-1]=t; } \ - } \ - i = l+1; j = ir; a = arr[l-1]; a2 = arr2[l-1]; \ - for (;;) { \ - do i++; while (arr[i-1] < a); \ - do j--; while (arr[j-1] > a); \ - if (j < i) break; \ - { elem_type t=arr[i-1];arr[i-1]=arr[j-1];arr[j-1]=t; t=arr2[i-1];arr2[i-1]=arr2[j-1];arr2[j-1]=t;} \ - } \ - arr[l-1] = arr[j-1]; arr2[l-1] = arr2[j-1]; \ - arr[j-1] = a; arr2[j-1] = a2; \ - j_stack += 2; \ - wxASSERT(!(j_stack>PIXEL_QSORT_STACK_SIZE)); \ - /* if (j_stack > PIXEL_QSORT_STACK_SIZE) { */ \ - /* printf("stack too small in pixel_qsort: aborting"); */ \ - /* exit(-2001); } */ \ - if (ir-i+1 >= j-l) { \ - i_stack[j_stack-1] = ir; \ - i_stack[j_stack-2] = i; \ - ir = j-1; \ - } else { \ - i_stack[j_stack-1] = j-1; \ - i_stack[j_stack-2] = l; \ - l = i; \ - } \ - } \ - } \ - free(i_stack); \ -} - - +#define DECLARE_PIXEL_QSORT2(name, elem_type) void name(elem_type *arr, elem_type *arr2, int n); + +#define DEFINE_PIXEL_QSORT2(name, elem_type) \ + void name(elem_type *arr, elem_type *arr2, int n) IMPLEMENT_PIXEL_QSORT2(name, elem_type) + +#define IMPLEMENT_PIXEL_QSORT2(elem_type, arr, arr2, n) \ + { \ + int i, ir = n, j, k, l = 1, j_stack = 0; \ + int *i_stack; \ + elem_type a, a2; \ + \ + i_stack = (int *)malloc(PIXEL_QSORT2_STACK_SIZE * sizeof(elem_type)); \ + for (;;) { \ + if (ir - l < PIXEL_QSORT2_THRESHOLD) { \ + for (j = l + 1; j <= ir; j++) { \ + a = arr[j - 1]; \ + a2 = arr2[j - 1]; \ + for (i = j - 1; i >= 1; i--) { \ + if (arr[i - 1] <= a) \ + break; \ + arr[i] = arr[i - 1]; \ + arr2[i] = arr2[i - 1]; \ + } \ + arr[i] = a; \ + arr2[i] = a2; \ + } \ + if (j_stack == 0) \ + break; \ + ir = i_stack[j_stack-- - 1]; \ + l = i_stack[j_stack-- - 1]; \ + } \ + else { \ + k = (l + ir) >> 1; \ + { \ + elem_type t = arr[k - 1]; \ + arr[k - 1] = arr[l]; \ + arr[l] = t; \ + t = arr2[k - 1]; \ + arr2[k - 1] = arr2[l]; \ + arr2[l] = t; \ + } \ + if (arr[l] > arr[ir - 1]) { \ + { \ + elem_type t = arr[l]; \ + arr[l] = arr[ir - 1]; \ + arr[ir - 1] = t; \ + t = arr2[l]; \ + arr2[l] = arr2[ir - 1]; \ + arr2[ir - 1] = t; \ + } \ + } \ + if (arr[l - 1] > arr[ir - 1]) { \ + { \ + elem_type t = arr[l - 1]; \ + arr[l - 1] = arr[ir - 1]; \ + arr[ir - 1] = t; \ + t = arr2[l - 1]; \ + arr2[l - 1] = arr2[ir - 1]; \ + arr2[ir - 1] = t; \ + } \ + } \ + if (arr[l] > arr[l - 1]) { \ + { \ + elem_type t = arr[l]; \ + arr[l] = arr[l - 1]; \ + arr[l - 1] = t; \ + t = arr2[l]; \ + arr2[l] = arr2[l - 1]; \ + arr2[l - 1] = t; \ + } \ + } \ + i = l + 1; \ + j = ir; \ + a = arr[l - 1]; \ + a2 = arr2[l - 1]; \ + for (;;) { \ + do \ + i++; \ + while (arr[i - 1] < a); \ + do \ + j--; \ + while (arr[j - 1] > a); \ + if (j < i) \ + break; \ + { \ + elem_type t = arr[i - 1]; \ + arr[i - 1] = arr[j - 1]; \ + arr[j - 1] = t; \ + t = arr2[i - 1]; \ + arr2[i - 1] = arr2[j - 1]; \ + arr2[j - 1] = t; \ + } \ + } \ + arr[l - 1] = arr[j - 1]; \ + arr2[l - 1] = arr2[j - 1]; \ + arr[j - 1] = a; \ + arr2[j - 1] = a2; \ + j_stack += 2; \ + wxASSERT(!(j_stack > PIXEL_QSORT_STACK_SIZE)); \ + /* if (j_stack > PIXEL_QSORT_STACK_SIZE) { */ \ + /* printf("stack too small in pixel_qsort: aborting"); */ \ + /* exit(-2001); } */ \ + if (ir - i + 1 >= j - l) { \ + i_stack[j_stack - 1] = ir; \ + i_stack[j_stack - 2] = i; \ + ir = j - 1; \ + } \ + else { \ + i_stack[j_stack - 1] = j - 1; \ + i_stack[j_stack - 2] = l; \ + l = i; \ + } \ + } \ + } \ + free(i_stack); \ + } /* Abbreviated benchmark data from diff --git a/src/labenski/include/wx/wxthings/optvalue.h b/src/labenski/include/wx/wxthings/optvalue.h index e8ed3c30b..aa299bbd5 100644 --- a/src/labenski/include/wx/wxthings/optvalue.h +++ b/src/labenski/include/wx/wxthings/optvalue.h @@ -20,152 +20,201 @@ WX_DECLARE_OBJARRAY_WITH_DECL(wxOptionValue, wxArrayOptionValue, class WXDLLIMPE // Global wxString utilities //---------------------------------------------------------------------------- -//extern wxArrayString wxStringToWords( const wxString &string ); +// extern wxArrayString wxStringToWords( const wxString &string ); //---------------------------------------------------------------------------- // wxOptionValue - a ref counted wxString key, wxString value container //---------------------------------------------------------------------------- -class WXDLLIMPEXP_THINGS wxOptionValue : public wxObject -{ +class WXDLLIMPEXP_THINGS wxOptionValue : public wxObject { public: - wxOptionValue(bool create = true) : wxObject() { if (create) Create(); } - wxOptionValue( const wxOptionValue &optValue ) : wxObject() { Create(optValue); } - wxOptionValue( const wxString &str ) : wxObject() { Create(str); } - - // (Re)Create as an empty container - bool Create(); - // Ref the other wxOptionValue - bool Create( const wxOptionValue &optValue ); - // Create from a string with this structure - // [type] # optional - // key = value - bool Create( const wxString &string ); - - // Make a true copy of the source wxOptionValue (not refed) - bool Copy( const wxOptionValue &source ); - - // Is there any ref data - bool Ok() const; - // Unref the data - void Destroy(); - - //------------------------------------------------------------------------- - - // Get/Set the "type", which can mean whatever you want - wxString GetType() const; - void SetType( const wxString &type ); - - //------------------------------------------------------------------------- - - // does this have a wxOptionValueArray filled with children - size_t GetChildrenCount() const; - wxArrayOptionValue *GetChildren() const; - - bool AddChild( const wxOptionValue& child ); - void DeleteChildren(); - - //------------------------------------------------------------------------- - - // Get the number of different option name/value combinations - size_t GetOptionCount() const; - // Access the arrays themselves - wxArrayString GetOptionNames() const; - wxArrayString GetOptionValues() const; - // Get a specific option name or value - wxString GetOptionName( size_t n ) const; - wxString GetOptionValue( size_t n ) const; - - // returns the index of the option >= 0 or -1 (wxNOT_FOUND) if not found - int HasOption(const wxString &name) const; - // Search through the option names for this part returning the first match - int FindOption(const wxString &part_of_option_name) const; - // delete this option, returns sucess - bool DeleteOption(const wxString &name); - bool DeleteOption( size_t n ); - - // Option functions (arbitrary name/value mapping) - void SetOption(const wxString& name, const wxString& value, bool force=true ); - void SetOption(const wxString& name, int value, bool force=true ) { SetOption(name, wxString::Format(wxT("%d"), value), force); } - void SetOption(const wxString& name, double value, bool force=true ) { SetOption(name, wxString::Format(wxT("%lf"), value), force); } - - // printf style for numeric values SetOption("Name", true, "%d %f", 2, 2.5) - void SetOption(const wxString& name, bool update, const wxChar* format, ...); - - void SetOption(const wxString& name, int v1, int v2, int v3, bool force=true ) { SetOption(name, wxString::Format(wxT("%d %d %d"), v1, v2, v3), force); } - void SetOption(const wxString& name, double v1, double v2, double v3, bool force=true ) { SetOption(name, wxString::Format(wxT("%lf %lf %lf"), v1, v2, v3), force); } - void SetOption(const wxString& name, int *v, int count, bool force=true ) { if(v) { wxString s; for (int i=0; i= 0 or -1 (wxNOT_FOUND) if not found + int HasOption(const wxString &name) const; + // Search through the option names for this part returning the first match + int FindOption(const wxString &part_of_option_name) const; + // delete this option, returns sucess + bool DeleteOption(const wxString &name); + bool DeleteOption(size_t n); + + // Option functions (arbitrary name/value mapping) + void SetOption(const wxString &name, const wxString &value, bool force = true); + void SetOption(const wxString &name, int value, bool force = true) + { + SetOption(name, wxString::Format(wxT("%d"), value), force); + } + void SetOption(const wxString &name, double value, bool force = true) + { + SetOption(name, wxString::Format(wxT("%lf"), value), force); + } + + // printf style for numeric values SetOption("Name", true, "%d %f", 2, 2.5) + void SetOption(const wxString &name, bool update, const wxChar *format, ...); + + void SetOption(const wxString &name, int v1, int v2, int v3, bool force = true) + { + SetOption(name, wxString::Format(wxT("%d %d %d"), v1, v2, v3), force); + } + void SetOption(const wxString &name, double v1, double v2, double v3, bool force = true) + { + SetOption(name, wxString::Format(wxT("%lf %lf %lf"), v1, v2, v3), force); + } + void SetOption(const wxString &name, int *v, int count, bool force = true) + { + if (v) { + wxString s; + for (int i = 0; i < count; i++) { + s += wxString::Format(wxT("%d "), v[i]); + } + SetOption(name, s, force); + } + } + void SetOption(const wxString &name, float *v, int count, bool force = true) + { + if (v) { + wxString s; + for (int i = 0; i < count; i++) { + s += wxString::Format(wxT("%f "), v[i]); + } + SetOption(name, s, force); + } + } + void SetOption(const wxString &name, const wxPoint &value, bool force = true) + { + SetOption(name, wxString::Format(wxT("%d %d"), value.x, value.y), force); + } + void SetOption(const wxString &name, const wxSize &value, bool force = true) + { + SetOption(name, wxString::Format(wxT("%d %d"), value.x, value.y), force); + } + void SetOption(const wxString &name, const wxRect &value, bool force = true) + { + SetOption(name, + wxString::Format(wxT("%d %d %d %d"), value.x, value.y, value.width, value.height), + force); + } + + wxString GetOption(const wxString &name) const; // returns wxEmptyString if not found + int GetOptionInt(const wxString &name) const; // returns 0 if not found + + // These return true on sucess otherwise the value is not modified + bool GetOption(const wxString &name, wxString &value) const; + bool GetOption(const wxString &name, int *value) const; + bool GetOption(const wxString &name, float *value) const; + bool GetOption(const wxString &name, double *value) const; + + // sscanf style for numeric values GetOption("Name", "%d %f", &n_int, &n_float) + int GetOption(const wxString &name, const wxChar *format, ...) const; + + // Get int values filling a wxArrayInt, if count == -1 get all, else count. + // delims are the possible separators between values. + int GetOption(const wxString &name, wxArrayInt &values, int count = -1, + const wxString &delims = wxT(" ,\t\r\n")) const; + + // Get values and fill arrays up to count items + bool GetOption(const wxString &name, unsigned char *value, int count, + const wxString &delims = wxT(" ,\t\r\n")) const; + bool GetOption(const wxString &name, int *value, int count, + const wxString &delims = wxT(" ,\t\r\n")) const; + bool GetOption(const wxString &name, long *value, int count, + const wxString &delims = wxT(" ,\t\r\n")) const; + bool GetOption(const wxString &name, float *value, int count, + const wxString &delims = wxT(" ,\t\r\n")) const; + bool GetOption(const wxString &name, double *value, int count, + const wxString &delims = wxT(" ,\t\r\n")) const; + + // Convience function to easily get common values + bool GetOption(const wxString &name, int *v1, int *v2, + const wxString &delims = wxT(" ,\t\r\n")) const; + + bool GetOption(const wxString &name, int *v1, int *v2, int *v3, + const wxString &delims = wxT(" ,\t\r\n")) const; + bool GetOption(const wxString &name, float *v1, float *v2, float *v3, + const wxString &delims = wxT(" ,\t\r\n")) const; + + bool GetOption(const wxString &name, wxPoint &value, + const wxString &delims = wxT(" ,\t\r\n")) const + { + return GetOption(name, &value.x, &value.y, delims); + } + bool GetOption(const wxString &name, wxSize &value, + const wxString &delims = wxT(" ,\t\r\n")) const + { + return GetOption(name, &value.x, &value.y, delims); + } + bool GetOption(const wxString &name, wxRect &value, + const wxString &delims = wxT(" ,\t\r\n")) const; + + //------------------------------------------------------------------------- + // Operators + + wxOptionValue &operator=(const wxOptionValue &optValue) + { + if ((*this) != optValue) { + wxObject::Ref(optValue); + } + return *this; + } + bool operator==(const wxOptionValue &optValue) const { return m_refData == optValue.m_refData; } + bool operator!=(const wxOptionValue &optValue) const { return m_refData != optValue.m_refData; } -private : - // ref counting code - virtual wxObjectRefData *CreateRefData() const; - virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; +private: + // ref counting code + virtual wxObjectRefData *CreateRefData() const; + virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const; - DECLARE_DYNAMIC_CLASS(wxOptionValue); + DECLARE_DYNAMIC_CLASS(wxOptionValue); }; #endif // __WXOPTIONVALUE_H__ diff --git a/src/labenski/include/wx/wxthings/range.h b/src/labenski/include/wx/wxthings/range.h index 77ebf4a68..a80842769 100644 --- a/src/labenski/include/wx/wxthings/range.h +++ b/src/labenski/include/wx/wxthings/range.h @@ -31,294 +31,407 @@ WXDLLIMPEXP_DATA_THINGS(extern const wxRangeDouble) wxEmptyRangeDouble; // wxRangeInt //============================================================================= -class WXDLLIMPEXP_THINGS wxRangeInt -{ +class WXDLLIMPEXP_THINGS wxRangeInt { public: - inline wxRangeInt(int min_=0, int max_=0) : m_min(min_), m_max(max_) { } - - // Get the width of the range - inline int GetRange() const { return m_max - m_min + 1; } - // Get/Set the min/max values of the range - inline int GetMin() const { return m_min; } - inline int GetMax() const { return m_max; } - inline void SetMin(int min_) { m_min = min_; } - inline void SetMax(int max_) { m_max = max_; } - inline void Set(int min_, int max_) { m_min = min_, m_max = max_; } - - // Shift the range by i - void Shift(int i) { m_min += i; m_max += i; } - - // Is the range empty, min < max - inline bool IsEmpty() const { return m_min > m_max; } - - // Swap the min and max values - inline void SwapMinMax() { int temp=m_min; m_min=m_max; m_max=temp; } - - // returns -1 for i < min, 0 for in range, +1 for i > m_max - inline int Position(int i) const { return i < m_min ? -1 : (i > m_max ? 1 : 0); } - - // Is this point or the range within this range - inline bool Contains( int i ) const { return (i >= m_min) && (i <= m_max); } - inline bool Contains( const wxRangeInt &r ) const - { return (r.m_min >= m_min) && (r.m_max <= m_max); } - - // returns if the range intersects the given range - inline bool Intersects(const wxRangeInt& r) const - { return Intersect(r).IsEmpty(); } - // returns the intersection of the range with the other - inline wxRangeInt Intersect(const wxRangeInt& r) const - { return wxRangeInt(wxMax(m_min, r.m_min), wxMin(m_max, r.m_max)); } - // returns the union of the range with the other - inline wxRangeInt Union(const wxRangeInt& r) const - { return wxRangeInt(wxMin(m_min, r.m_min), wxMax(m_max, r.m_max)); } - - // Is this point inside or touches +/- 1 of the range - inline bool Touches( int i ) const - { return !IsEmpty() && wxRangeInt(m_min-1, m_max+1).Contains(i); } - // Is the range adjoining this range - inline bool Touches( const wxRangeInt &r ) const - { if (IsEmpty() || r.IsEmpty()) return false; - wxRangeInt rExp(m_min-1, m_max+1); - return rExp.Contains(r.m_min) || rExp.Contains(r.m_max); } - // combine this single point with the range by expanding the m_min/m_max to contain it - // if only_if_touching then only combine if i is just outside the range by +/-1 - // returns true if the range has been changed at all, false if not - bool Combine(int i, bool only_if_touching = false); - bool Combine(const wxRangeInt &r, bool only_if_touching = false); - - // delete range r from this, return true is anything was done - // if r spans this then this and right become wxEmptyRangeInt - // else if r is inside of this then this is the left side and right is the right - // else if r.m_min > m_min then this is the left side - // else if r.m_min < m_min this is the right side - bool Delete( const wxRangeInt &r, wxRangeInt *right=NULL ); - - // operators - // no copy ctor or assignment operator - the defaults are ok - - // comparison - inline bool operator==(const wxRangeInt& r) const { return (m_min == r.m_min)&&(m_max == r.m_max); } - inline bool operator!=(const wxRangeInt& r) const { return !(*this == r); } - - // Adding ranges unions them to create the largest range - inline wxRangeInt operator+(const wxRangeInt& r) const { return Union(r); } - inline wxRangeInt& operator+=(const wxRangeInt& r) { if(r.m_minm_max) m_max=r.m_max; return *this; } - // Subtracting ranges intersects them to get the smallest range - inline wxRangeInt operator-(const wxRangeInt& r) const { return Intersect(r); } - inline wxRangeInt& operator-=(const wxRangeInt& r) { if(r.m_min>m_min) m_min=r.m_min; if(r.m_max m_max; } + + // Swap the min and max values + inline void SwapMinMax() + { + int temp = m_min; + m_min = m_max; + m_max = temp; + } + + // returns -1 for i < min, 0 for in range, +1 for i > m_max + inline int Position(int i) const { return i < m_min ? -1 : (i > m_max ? 1 : 0); } + + // Is this point or the range within this range + inline bool Contains(int i) const { return (i >= m_min) && (i <= m_max); } + inline bool Contains(const wxRangeInt &r) const + { + return (r.m_min >= m_min) && (r.m_max <= m_max); + } + + // returns if the range intersects the given range + inline bool Intersects(const wxRangeInt &r) const { return Intersect(r).IsEmpty(); } + // returns the intersection of the range with the other + inline wxRangeInt Intersect(const wxRangeInt &r) const + { + return wxRangeInt(wxMax(m_min, r.m_min), wxMin(m_max, r.m_max)); + } + // returns the union of the range with the other + inline wxRangeInt Union(const wxRangeInt &r) const + { + return wxRangeInt(wxMin(m_min, r.m_min), wxMax(m_max, r.m_max)); + } + + // Is this point inside or touches +/- 1 of the range + inline bool Touches(int i) const + { + return !IsEmpty() && wxRangeInt(m_min - 1, m_max + 1).Contains(i); + } + // Is the range adjoining this range + inline bool Touches(const wxRangeInt &r) const + { + if (IsEmpty() || r.IsEmpty()) { + return false; + } + wxRangeInt rExp(m_min - 1, m_max + 1); + return rExp.Contains(r.m_min) || rExp.Contains(r.m_max); + } + // combine this single point with the range by expanding the m_min/m_max to contain it + // if only_if_touching then only combine if i is just outside the range by +/-1 + // returns true if the range has been changed at all, false if not + bool Combine(int i, bool only_if_touching = false); + bool Combine(const wxRangeInt &r, bool only_if_touching = false); + + // delete range r from this, return true is anything was done + // if r spans this then this and right become wxEmptyRangeInt + // else if r is inside of this then this is the left side and right is the right + // else if r.m_min > m_min then this is the left side + // else if r.m_min < m_min this is the right side + bool Delete(const wxRangeInt &r, wxRangeInt *right = NULL); + + // operators + // no copy ctor or assignment operator - the defaults are ok + + // comparison + inline bool operator==(const wxRangeInt &r) const + { + return (m_min == r.m_min) && (m_max == r.m_max); + } + inline bool operator!=(const wxRangeInt &r) const { return !(*this == r); } + + // Adding ranges unions them to create the largest range + inline wxRangeInt operator+(const wxRangeInt &r) const { return Union(r); } + inline wxRangeInt &operator+=(const wxRangeInt &r) + { + if (r.m_min < m_min) { + m_min = r.m_min; + } + if (r.m_max > m_max) { + m_max = r.m_max; + } + return *this; + } + // Subtracting ranges intersects them to get the smallest range + inline wxRangeInt operator-(const wxRangeInt &r) const { return Intersect(r); } + inline wxRangeInt &operator-=(const wxRangeInt &r) + { + if (r.m_min > m_min) { + m_min = r.m_min; + } + if (r.m_max < m_max) { + m_max = r.m_max; + } + return *this; + } + + // Adding/Subtracting with an int shifts the range + inline wxRangeInt operator+(const int i) const { return wxRangeInt(m_min + i, m_max + i); } + inline wxRangeInt operator-(const int i) const { return wxRangeInt(m_min - i, m_max - i); } + inline wxRangeInt &operator+=(const int i) + { + Shift(i); + return *this; + } + inline wxRangeInt &operator-=(const int i) + { + Shift(-i); + return *this; + } + + int m_min, m_max; }; //============================================================================= // wxRangeIntSelection - ordered 1D array of wxRangeInts, combines to minimze size //============================================================================= -class WXDLLIMPEXP_THINGS wxRangeIntSelection -{ -public : - wxRangeIntSelection() {} - wxRangeIntSelection(const wxRangeInt& range) { if (!range.IsEmpty()) m_ranges.Add(range); } - wxRangeIntSelection(const wxRangeIntSelection &ranges) { Copy(ranges); } - - // Make a full copy of the source - void Copy(const wxRangeIntSelection &source) - { - m_ranges.Clear(); - WX_APPEND_ARRAY(m_ranges, source.GetRangeArray()); - } - - // Get the number of individual ranges - inline int GetCount() const { return m_ranges.GetCount(); } - // Get total number of items selected in all ranges, ie. sum of all wxRange::GetWidths - int GetItemCount() const; - // Get the ranges themselves to iterate though for example - const wxArrayRangeInt& GetRangeArray() const { return m_ranges; } - // Get a single range - const wxRangeInt& GetRange( int index ) const; - inline const wxRangeInt& Item( int index ) const { return GetRange(index); } - // Get a range of the min range value and max range value - wxRangeInt GetBoundingRange() const; - // Clear all the ranges - void Clear() { m_ranges.Clear(); } - - // Is this point or range contained in the selection - inline bool Contains( int i ) const { return Index(i) != wxNOT_FOUND; } - inline bool Contains( const wxRangeInt &range ) const { return Index(range) != wxNOT_FOUND; } - // Get the index of the range that contains this, or wxNOT_FOUND - int Index( int i ) const; - int Index( const wxRangeInt &range ) const; - - // Get the nearest index of a range, index returned contains i or is the one just below - // returns -1 if it's below all the selected ones, or no ranges - // returns GetCount() if it's above all the selected ones - int NearestIndex( int i ) const; - - // Add the range to the selection, returning if anything was done, false if already selected - bool SelectRange( const wxRangeInt &range ); - - // Remove the range to the selection, returning if anything was done, false if not already selected - bool DeselectRange( const wxRangeInt &range ); - - // Set the min and max bounds of the ranges, returns true if anything was done - bool BoundRanges( const wxRangeInt &range ); - - // operators - inline const wxRangeInt& operator[](int index) const { return GetRange(index); } - - wxRangeIntSelection& operator = (const wxRangeIntSelection& other) { Copy(other); return *this; } - -protected : - wxArrayRangeInt m_ranges; +class WXDLLIMPEXP_THINGS wxRangeIntSelection { +public: + wxRangeIntSelection() {} + wxRangeIntSelection(const wxRangeInt &range) + { + if (!range.IsEmpty()) { + m_ranges.Add(range); + } + } + wxRangeIntSelection(const wxRangeIntSelection &ranges) { Copy(ranges); } + + // Make a full copy of the source + void Copy(const wxRangeIntSelection &source) + { + m_ranges.Clear(); + WX_APPEND_ARRAY(m_ranges, source.GetRangeArray()); + } + + // Get the number of individual ranges + inline int GetCount() const { return m_ranges.GetCount(); } + // Get total number of items selected in all ranges, ie. sum of all wxRange::GetWidths + int GetItemCount() const; + // Get the ranges themselves to iterate though for example + const wxArrayRangeInt &GetRangeArray() const { return m_ranges; } + // Get a single range + const wxRangeInt &GetRange(int index) const; + inline const wxRangeInt &Item(int index) const { return GetRange(index); } + // Get a range of the min range value and max range value + wxRangeInt GetBoundingRange() const; + // Clear all the ranges + void Clear() { m_ranges.Clear(); } + + // Is this point or range contained in the selection + inline bool Contains(int i) const { return Index(i) != wxNOT_FOUND; } + inline bool Contains(const wxRangeInt &range) const { return Index(range) != wxNOT_FOUND; } + // Get the index of the range that contains this, or wxNOT_FOUND + int Index(int i) const; + int Index(const wxRangeInt &range) const; + + // Get the nearest index of a range, index returned contains i or is the one just below + // returns -1 if it's below all the selected ones, or no ranges + // returns GetCount() if it's above all the selected ones + int NearestIndex(int i) const; + + // Add the range to the selection, returning if anything was done, false if already selected + bool SelectRange(const wxRangeInt &range); + + // Remove the range to the selection, returning if anything was done, false if not already + // selected + bool DeselectRange(const wxRangeInt &range); + + // Set the min and max bounds of the ranges, returns true if anything was done + bool BoundRanges(const wxRangeInt &range); + + // operators + inline const wxRangeInt &operator[](int index) const { return GetRange(index); } + + wxRangeIntSelection &operator=(const wxRangeIntSelection &other) + { + Copy(other); + return *this; + } + +protected: + wxArrayRangeInt m_ranges; }; //============================================================================= // wxRangeDouble //============================================================================= -class WXDLLIMPEXP_THINGS wxRangeDouble -{ +class WXDLLIMPEXP_THINGS wxRangeDouble { public: - inline wxRangeDouble(wxDouble min_=0, wxDouble max_=0) : m_min(min_), m_max(max_) {} - - // Get the width of the range - inline wxDouble GetRange() const { return m_max - m_min; } - // Get/Set the min/max values of the range - inline wxDouble GetMin() const { return m_min; } - inline wxDouble GetMax() const { return m_max; } - inline void SetMin(wxDouble min_) { m_min = min_; } - inline void SetMax(wxDouble max_) { m_max = max_; } - inline void Set(wxDouble min_, wxDouble max_) { m_min = min_, m_max = max_; } - - // Shift the range by i - void Shift(wxDouble i) { m_min += i; m_max += i; } - - // Is the range empty, min < max - inline bool IsEmpty() const { return m_min > m_max; } - - // Swap the min and max values - inline void SwapMinMax() { wxDouble temp = m_min; m_min = m_max; m_max = temp; } - - // returns -1 for i < min, 0 for in range, +1 for i > m_max - inline int Position(wxDouble i) const { return i < m_min ? -1 : i > m_max ? 1 : 0; } - - // Is this point or the range within this range - inline bool Contains( wxDouble i ) const { return (i>=m_min)&&(i<=m_max); } - inline bool Contains( const wxRangeDouble &r ) const - { return (r.m_min>=m_min)&&(r.m_max<=m_max); } - - // returns if the range intersects the given range - inline bool Intersects(const wxRangeDouble& r) const - { return Intersect(r).IsEmpty(); } - // returns the intersection of the range with the other - inline wxRangeDouble Intersect(const wxRangeDouble& r) const - { return wxRangeDouble(wxMax(m_min, r.m_min), wxMin(m_max, r.m_max)); } - // returns the union of the range with the other - inline wxRangeDouble Union(const wxRangeDouble& r) const - { return wxRangeDouble(wxMin(m_min, r.m_min), wxMax(m_max, r.m_max)); } - - // no touches for double since what would be a good eps value? - - // combine this single point with the range by expanding the m_min/m_max to contain it - // if only_if_touching then only combine if there is overlap - // returns true if the range has been changed at all, false if not - bool Combine(wxDouble i); - bool Combine( const wxRangeDouble &r, bool only_if_touching = false ); - - // delete range r from this, return true is anything was done - // if r spans this then this and right become wxEmptyRangeInt - // else if r is inside of this then this is the left side and right is the right - // else if r.m_min > m_min then this is the left side - // else if r.m_min < m_min this is the right side - bool Delete( const wxRangeDouble &r, wxRangeDouble *right=NULL ); - - // operators - // no copy ctor or assignment operator - the defaults are ok - - // comparison - inline bool operator==(const wxRangeDouble& r) const { return (m_min == r.m_min)&&(m_max == r.m_max); } - inline bool operator!=(const wxRangeDouble& r) const { return !(*this == r); } - - // Adding ranges unions them to create the largest range - inline wxRangeDouble operator+(const wxRangeDouble& r) const { return Union(r); } - inline wxRangeDouble& operator+=(const wxRangeDouble& r) { if(r.m_minm_max) m_max=r.m_max; return *this; } - // Subtracting ranges intersects them to get the smallest range - inline wxRangeDouble operator-(const wxRangeDouble& r) const { return Intersect(r); } - inline wxRangeDouble& operator-=(const wxRangeDouble& r) { if(r.m_min>m_min) m_min=r.m_min; if(r.m_max m_max; } + + // Swap the min and max values + inline void SwapMinMax() + { + wxDouble temp = m_min; + m_min = m_max; + m_max = temp; + } + + // returns -1 for i < min, 0 for in range, +1 for i > m_max + inline int Position(wxDouble i) const { return i < m_min ? -1 : i > m_max ? 1 : 0; } + + // Is this point or the range within this range + inline bool Contains(wxDouble i) const { return (i >= m_min) && (i <= m_max); } + inline bool Contains(const wxRangeDouble &r) const + { + return (r.m_min >= m_min) && (r.m_max <= m_max); + } + + // returns if the range intersects the given range + inline bool Intersects(const wxRangeDouble &r) const { return Intersect(r).IsEmpty(); } + // returns the intersection of the range with the other + inline wxRangeDouble Intersect(const wxRangeDouble &r) const + { + return wxRangeDouble(wxMax(m_min, r.m_min), wxMin(m_max, r.m_max)); + } + // returns the union of the range with the other + inline wxRangeDouble Union(const wxRangeDouble &r) const + { + return wxRangeDouble(wxMin(m_min, r.m_min), wxMax(m_max, r.m_max)); + } + + // no touches for double since what would be a good eps value? + + // combine this single point with the range by expanding the m_min/m_max to contain it + // if only_if_touching then only combine if there is overlap + // returns true if the range has been changed at all, false if not + bool Combine(wxDouble i); + bool Combine(const wxRangeDouble &r, bool only_if_touching = false); + + // delete range r from this, return true is anything was done + // if r spans this then this and right become wxEmptyRangeInt + // else if r is inside of this then this is the left side and right is the right + // else if r.m_min > m_min then this is the left side + // else if r.m_min < m_min this is the right side + bool Delete(const wxRangeDouble &r, wxRangeDouble *right = NULL); + + // operators + // no copy ctor or assignment operator - the defaults are ok + + // comparison + inline bool operator==(const wxRangeDouble &r) const + { + return (m_min == r.m_min) && (m_max == r.m_max); + } + inline bool operator!=(const wxRangeDouble &r) const { return !(*this == r); } + + // Adding ranges unions them to create the largest range + inline wxRangeDouble operator+(const wxRangeDouble &r) const { return Union(r); } + inline wxRangeDouble &operator+=(const wxRangeDouble &r) + { + if (r.m_min < m_min) { + m_min = r.m_min; + } + if (r.m_max > m_max) { + m_max = r.m_max; + } + return *this; + } + // Subtracting ranges intersects them to get the smallest range + inline wxRangeDouble operator-(const wxRangeDouble &r) const { return Intersect(r); } + inline wxRangeDouble &operator-=(const wxRangeDouble &r) + { + if (r.m_min > m_min) { + m_min = r.m_min; + } + if (r.m_max < m_max) { + m_max = r.m_max; + } + return *this; + } + + // Adding/Subtracting with a double shifts the range + inline wxRangeDouble operator+(const wxDouble i) const + { + return wxRangeDouble(m_min + i, m_max + i); + } + inline wxRangeDouble operator-(const wxDouble i) const + { + return wxRangeDouble(m_min - i, m_max - i); + } + inline wxRangeDouble &operator+=(const wxDouble i) + { + Shift(i); + return *this; + } + inline wxRangeDouble &operator-=(const wxDouble i) + { + Shift(-i); + return *this; + } + + wxDouble m_min, m_max; }; //============================================================================= // wxRangeDoubleSelection - ordered 1D array of wxRangeDoubles, combines to minimze size //============================================================================= -class WXDLLIMPEXP_THINGS wxRangeDoubleSelection -{ -public : - wxRangeDoubleSelection() {} - wxRangeDoubleSelection(const wxRangeDouble& range) { if (!range.IsEmpty()) m_ranges.Add(range); } - wxRangeDoubleSelection(const wxRangeDoubleSelection &ranges) { Copy(ranges); } - - // Make a full copy of the source - void Copy(const wxRangeDoubleSelection &source) - { - m_ranges.Clear(); - WX_APPEND_ARRAY(m_ranges, source.GetRangeArray()); - } - - // Get the number of individual ranges - inline int GetCount() const { return m_ranges.GetCount(); } - // Get the ranges themselves to iterate though for example - const wxArrayRangeDouble& GetRangeArray() const { return m_ranges; } - // Get a single range - const wxRangeDouble& GetRange( int index ) const; - inline const wxRangeDouble& Item( int index ) const { return GetRange(index); } - // Get a range of the min range value and max range value - wxRangeDouble GetBoundingRange() const; - // Clear all the ranges - void Clear() { m_ranges.Clear(); } - - // Is this point or range contained in the selection - inline bool Contains( wxDouble i ) const { return Index(i) != wxNOT_FOUND; } - inline bool Contains( const wxRangeDouble &range ) const { return Index(range) != wxNOT_FOUND; } - // Get the index of the range that contains this, or wxNOT_FOUND - int Index( wxDouble i ) const; - int Index( const wxRangeDouble &range ) const; - - // Get the nearest index of a range, index returned contains i or is the one just below - // returns -1 if it's below all the selected ones, or no ranges - // returns GetCount() if it's above all the selected ones - int NearestIndex( wxDouble i ) const; - - // Add the range to the selection, returning if anything was done, false if already selected - bool SelectRange( const wxRangeDouble &range); - // Remove the range to the selection, returning if anything was done, false if not already selected - bool DeselectRange( const wxRangeDouble &range); - - // Set the min and max bounds of the ranges, returns true if anything was done - bool BoundRanges( const wxRangeDouble &range ); - - // operators - inline const wxRangeDouble& operator[](int index) const { return GetRange(index); } - - wxRangeDoubleSelection& operator = (const wxRangeDoubleSelection& other) { Copy(other); return *this; } - -protected : - wxArrayRangeDouble m_ranges; +class WXDLLIMPEXP_THINGS wxRangeDoubleSelection { +public: + wxRangeDoubleSelection() {} + wxRangeDoubleSelection(const wxRangeDouble &range) + { + if (!range.IsEmpty()) { + m_ranges.Add(range); + } + } + wxRangeDoubleSelection(const wxRangeDoubleSelection &ranges) { Copy(ranges); } + + // Make a full copy of the source + void Copy(const wxRangeDoubleSelection &source) + { + m_ranges.Clear(); + WX_APPEND_ARRAY(m_ranges, source.GetRangeArray()); + } + + // Get the number of individual ranges + inline int GetCount() const { return m_ranges.GetCount(); } + // Get the ranges themselves to iterate though for example + const wxArrayRangeDouble &GetRangeArray() const { return m_ranges; } + // Get a single range + const wxRangeDouble &GetRange(int index) const; + inline const wxRangeDouble &Item(int index) const { return GetRange(index); } + // Get a range of the min range value and max range value + wxRangeDouble GetBoundingRange() const; + // Clear all the ranges + void Clear() { m_ranges.Clear(); } + + // Is this point or range contained in the selection + inline bool Contains(wxDouble i) const { return Index(i) != wxNOT_FOUND; } + inline bool Contains(const wxRangeDouble &range) const { return Index(range) != wxNOT_FOUND; } + // Get the index of the range that contains this, or wxNOT_FOUND + int Index(wxDouble i) const; + int Index(const wxRangeDouble &range) const; + + // Get the nearest index of a range, index returned contains i or is the one just below + // returns -1 if it's below all the selected ones, or no ranges + // returns GetCount() if it's above all the selected ones + int NearestIndex(wxDouble i) const; + + // Add the range to the selection, returning if anything was done, false if already selected + bool SelectRange(const wxRangeDouble &range); + // Remove the range to the selection, returning if anything was done, false if not already + // selected + bool DeselectRange(const wxRangeDouble &range); + + // Set the min and max bounds of the ranges, returns true if anything was done + bool BoundRanges(const wxRangeDouble &range); + + // operators + inline const wxRangeDouble &operator[](int index) const { return GetRange(index); } + + wxRangeDoubleSelection &operator=(const wxRangeDoubleSelection &other) + { + Copy(other); + return *this; + } + +protected: + wxArrayRangeDouble m_ranges; }; - #endif // __WX_RANGE_H__ diff --git a/src/labenski/include/wx/wxthings/spinctld.h b/src/labenski/include/wx/wxthings/spinctld.h index a4be1d3ca..01c776c92 100644 --- a/src/labenski/include/wx/wxthings/spinctld.h +++ b/src/labenski/include/wx/wxthings/spinctld.h @@ -45,161 +45,154 @@ Differences to wxSpinCtrl: class /* WXDLLEXPORT */ wxTextCtrl; class WXDLLIMPEXP_THINGS wxSpinCtrlDblTextCtrl; -enum -{ - wxSPINCTRLDBL_AUTODIGITS = -1 // try to autocalc the # of digits +enum { + wxSPINCTRLDBL_AUTODIGITS = -1 // try to autocalc the # of digits }; -class WXDLLIMPEXP_THINGS wxSpinCtrlDbl: public wxControl -{ +class WXDLLIMPEXP_THINGS wxSpinCtrlDbl : public wxControl { public: - wxSpinCtrlDbl() : wxControl() { Init(); } - - // Native constructor - note &parent, this is to avoid ambiguity - wxSpinCtrlDbl( wxWindow &parent, wxWindowID id, - const wxString &value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxSize(95,-1), - long style = 0, - double min = 0.0, double max = 100.0, - double initial = 0.0, - double increment = 1.0, int digits = wxSPINCTRLDBL_AUTODIGITS, - const wxString& name = _T("wxSpinCtrlDbl") ) - { - Init(); - Create(&parent, id, value, pos, size, style, - min, max, initial, increment, digits, name); - } - - // wxSpinCtrl compatibility, call SetIncrement(increment,digits) after - wxSpinCtrlDbl( wxWindow *parent, wxWindowID id = wxID_ANY, - const wxString &value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxSize(95,-1), - long style = 0, - int min = 0, int max = 100, - int initial = 0, - const wxString& name = _T("wxSpinCtrlDbl") ) - { - Init(); - Create(parent, id, value, pos, size, style, - (double)min, (double)max, (double)initial, 1.0, -1, name); - } - - bool Create( wxWindow *parent, - wxWindowID id = wxID_ANY, - const wxString &value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxSize(100,-1), - long style = 0, - double min = 0.0, double max = 100.0, - double initial = 0.0, - double increment = 1.0, int digits = wxSPINCTRLDBL_AUTODIGITS, - const wxString& name = _T("wxSpinCtrlDbl") ); - - virtual ~wxSpinCtrlDbl(); - - // ----------------------------------------------------------------------- - // Public (normal usage) functions - - enum formatType - { - lf_fmt, // %lf - le_fmt, // %le - lg_fmt // %lg - }; - - virtual void SetValue( double value ); - void SetValue( double value, double min, double max, double increment, - int digits = wxSPINCTRLDBL_AUTODIGITS, formatType fmt = lg_fmt ) - { SetRange(min, max); SetIncrement(increment); SetDigits(digits, fmt); SetValue(value); } - // Set the value as text, if force then set text as is - virtual void SetValue( const wxString& text, bool force ); - // Set the allowed range, if max_val < min_val then no range and all vals allowed. - void SetRange( double min_val, double max_val ); - // Set the increment to use when the spin button or arrow keys pressed. - void SetIncrement( double increment ); - void SetIncrement( double increment, int digits, formatType fmt = lg_fmt ) - { SetIncrement(increment); SetDigits(digits, fmt); } - // Set the number of digits to show, use wxSPINCTRLDBL_AUTODIGITS - // or specify exact number to show i.e. %.[digits]lf - // The format type is used to create an appropriate format string. - void SetDigits( int digits = wxSPINCTRLDBL_AUTODIGITS, formatType fmt = lg_fmt ); - // Set the format string to use, ie. format="%.2lf" for .01 - void SetFormat( const wxString& format ); - // Set the control the the default value. - virtual void SetDefaultValue() { SetValue( m_default_value ); } - // Set the value of the default value, default is the inital value. - void SetDefaultValue( double default_value ); - // Force the value to always be divisible by the increment, initially off. - // This uses the default_value as the basis, you'll get strange results - // for very large differences between the current value and default value - // when the increment is very small. - void SetSnapToTicks(bool forceTicks); - - double GetValue() const { return m_value; } - double GetMin() const { return m_min; } - double GetMax() const { return m_max; } - virtual bool HasRange() const { return m_max >= m_min; } - virtual bool InRange(double value) const { return !HasRange() || ((value >= m_min) && (value <= m_max)); } - double GetIncrement() const { return m_increment; } - int GetDigits() const { return m_digits; } - wxString GetFormat() const { return m_textFormat; } - double GetDefaultValue() const { return m_default_value; } - bool GetSnapToTicks() const { return m_snap_ticks; } - - bool IsDefaultValue() const { return (m_value == m_default_value); } - - virtual bool SetFont( const wxFont &font ); - wxFont GetFont() const; - - virtual bool SetBackgroundColour(const wxColour& colour); - wxColour GetBackgroundColour() const; - - virtual bool SetForegroundColour(const wxColour& colour); - wxColour GetForegroundColour() const; - - // for setting... stuff - wxTextCtrl *GetTextCtrl() { return (wxTextCtrl*)m_textCtrl; } + wxSpinCtrlDbl() : wxControl() { Init(); } + + // Native constructor - note &parent, this is to avoid ambiguity + wxSpinCtrlDbl(wxWindow &parent, wxWindowID id, const wxString &value = wxEmptyString, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxSize(95, -1), + long style = 0, double min = 0.0, double max = 100.0, double initial = 0.0, + double increment = 1.0, int digits = wxSPINCTRLDBL_AUTODIGITS, + const wxString &name = _T("wxSpinCtrlDbl")) + { + Init(); + Create(&parent, id, value, pos, size, style, min, max, initial, increment, digits, name); + } + + // wxSpinCtrl compatibility, call SetIncrement(increment,digits) after + wxSpinCtrlDbl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxString &value = wxEmptyString, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxSize(95, -1), + long style = 0, int min = 0, int max = 100, int initial = 0, + const wxString &name = _T("wxSpinCtrlDbl")) + { + Init(); + Create(parent, id, value, pos, size, style, (double)min, (double)max, (double)initial, 1.0, -1, + name); + } + + bool Create(wxWindow *parent, wxWindowID id = wxID_ANY, const wxString &value = wxEmptyString, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxSize(100, -1), + long style = 0, double min = 0.0, double max = 100.0, double initial = 0.0, + double increment = 1.0, int digits = wxSPINCTRLDBL_AUTODIGITS, + const wxString &name = _T("wxSpinCtrlDbl")); + + virtual ~wxSpinCtrlDbl(); + + // ----------------------------------------------------------------------- + // Public (normal usage) functions + + enum formatType { + lf_fmt, // %lf + le_fmt, // %le + lg_fmt // %lg + }; + + virtual void SetValue(double value); + void SetValue(double value, double min, double max, double increment, + int digits = wxSPINCTRLDBL_AUTODIGITS, formatType fmt = lg_fmt) + { + SetRange(min, max); + SetIncrement(increment); + SetDigits(digits, fmt); + SetValue(value); + } + // Set the value as text, if force then set text as is + virtual void SetValue(const wxString &text, bool force); + // Set the allowed range, if max_val < min_val then no range and all vals allowed. + void SetRange(double min_val, double max_val); + // Set the increment to use when the spin button or arrow keys pressed. + void SetIncrement(double increment); + void SetIncrement(double increment, int digits, formatType fmt = lg_fmt) + { + SetIncrement(increment); + SetDigits(digits, fmt); + } + // Set the number of digits to show, use wxSPINCTRLDBL_AUTODIGITS + // or specify exact number to show i.e. %.[digits]lf + // The format type is used to create an appropriate format string. + void SetDigits(int digits = wxSPINCTRLDBL_AUTODIGITS, formatType fmt = lg_fmt); + // Set the format string to use, ie. format="%.2lf" for .01 + void SetFormat(const wxString &format); + // Set the control the the default value. + virtual void SetDefaultValue() { SetValue(m_default_value); } + // Set the value of the default value, default is the inital value. + void SetDefaultValue(double default_value); + // Force the value to always be divisible by the increment, initially off. + // This uses the default_value as the basis, you'll get strange results + // for very large differences between the current value and default value + // when the increment is very small. + void SetSnapToTicks(bool forceTicks); + + double GetValue() const { return m_value; } + double GetMin() const { return m_min; } + double GetMax() const { return m_max; } + virtual bool HasRange() const { return m_max >= m_min; } + virtual bool InRange(double value) const + { + return !HasRange() || ((value >= m_min) && (value <= m_max)); + } + double GetIncrement() const { return m_increment; } + int GetDigits() const { return m_digits; } + wxString GetFormat() const { return m_textFormat; } + double GetDefaultValue() const { return m_default_value; } + bool GetSnapToTicks() const { return m_snap_ticks; } + + bool IsDefaultValue() const { return (m_value == m_default_value); } + + virtual bool SetFont(const wxFont &font); + wxFont GetFont() const; + + virtual bool SetBackgroundColour(const wxColour &colour); + wxColour GetBackgroundColour() const; + + virtual bool SetForegroundColour(const wxColour &colour); + wxColour GetForegroundColour() const; + + // for setting... stuff + wxTextCtrl *GetTextCtrl() { return (wxTextCtrl *)m_textCtrl; } protected: - void OnSpinUp( wxSpinEvent &event ); - void OnSpinDown( wxSpinEvent &event ); - void OnTextEnter( wxCommandEvent &event ); - void OnText( wxCommandEvent &event ); - // the textctrl is subclassed to get at pgup/dn and then sent here - void OnChar( wxKeyEvent &event ); + void OnSpinUp(wxSpinEvent &event); + void OnSpinDown(wxSpinEvent &event); + void OnTextEnter(wxCommandEvent &event); + void OnText(wxCommandEvent &event); + // the textctrl is subclassed to get at pgup/dn and then sent here + void OnChar(wxKeyEvent &event); - virtual void SyncSpinToText(bool send_event = true, bool force_valid = true); + virtual void SyncSpinToText(bool send_event = true, bool force_valid = true); - void DoSendEvent(); // send an event based on current state + void DoSendEvent(); // send an event based on current state - virtual void DoSetSize(int x, int y, int width, int height, - int sizeFlags = wxSIZE_AUTO); + virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetBestSize() const; - void OnFocus( wxFocusEvent& event ); // pass focus to textctrl, for wxTAB_TRAVERSAL - void OnKillFocus( wxFocusEvent &event ); + void OnFocus(wxFocusEvent &event); // pass focus to textctrl, for wxTAB_TRAVERSAL + void OnKillFocus(wxFocusEvent &event); - wxSpinButton *m_spinButton; - wxSpinCtrlDblTextCtrl *m_textCtrl; + wxSpinButton *m_spinButton; + wxSpinCtrlDblTextCtrl *m_textCtrl; - double m_min; // min allowed value - double m_max; // max allowed value - double m_value; // current value - double m_default_value; // initial value, or SetDefaultValue(value) - double m_increment; // how much to to add per spin - int m_digits; // number of digits displayed after decimal point - bool m_snap_ticks; // value is divisible by increment - wxString m_textFormat; // used as wxString.Printf(m_textFormat.c_str(), m_value); + double m_min; // min allowed value + double m_max; // max allowed value + double m_value; // current value + double m_default_value; // initial value, or SetDefaultValue(value) + double m_increment; // how much to to add per spin + int m_digits; // number of digits displayed after decimal point + bool m_snap_ticks; // value is divisible by increment + wxString m_textFormat; // used as wxString.Printf(m_textFormat.c_str(), m_value); private: - friend class wxSpinCtrlDblTextCtrl; + friend class wxSpinCtrlDblTextCtrl; - void Init(); - DECLARE_DYNAMIC_CLASS(wxSpinCtrlDbl) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_DYNAMIC_CLASS(wxSpinCtrlDbl) + DECLARE_EVENT_TABLE() }; -#endif // __wxSPINCTRLDBL_H__ +#endif // __wxSPINCTRLDBL_H__ diff --git a/src/labenski/include/wx/wxthings/thingdef.h b/src/labenski/include/wx/wxthings/thingdef.h index 41a2127c7..07b0c2d3f 100644 --- a/src/labenski/include/wx/wxthings/thingdef.h +++ b/src/labenski/include/wx/wxthings/thingdef.h @@ -28,10 +28,10 @@ #define WXDLLIMPEXP_DATA_THINGS(type) WXIMPORT type #else // not making nor using DLL */ - #define WXDLLIMPEXP_THINGS - #define WXDLLIMPEXP_DATA_THINGS(type) type +#define WXDLLIMPEXP_THINGS +#define WXDLLIMPEXP_DATA_THINGS(type) type /* #endif */ -#endif // __WX_THINGDEF_H__ +#endif // __WX_THINGDEF_H__ diff --git a/src/labenski/include/wx/wxthings/toggle.h b/src/labenski/include/wx/wxthings/toggle.h index 3331076b3..169cbe57c 100644 --- a/src/labenski/include/wx/wxthings/toggle.h +++ b/src/labenski/include/wx/wxthings/toggle.h @@ -77,174 +77,170 @@ class WXDLLEXPORT wxTimerEvent; // wxCustomButton styles //----------------------------------------------------------------------------- -enum wxCustomButton_Style -{ - // Position of the label, use only one - wxCUSTBUT_LEFT = 0x0001, - wxCUSTBUT_RIGHT = 0x0002, - wxCUSTBUT_TOP = 0x0004, - wxCUSTBUT_BOTTOM = 0x0008, - // Button style, use only one - wxCUSTBUT_NOTOGGLE = 0x0100, - wxCUSTBUT_BUTTON = 0x0200, - wxCUSTBUT_TOGGLE = 0x0400, - wxCUSTBUT_BUT_DCLICK_TOG = 0x0800, - wxCUSTBUT_TOG_DCLICK_BUT = 0x1000, - // drawing styles - wxCUSTBUT_FLAT = 0x2000 // flat, mouseover raises if not depressed +enum wxCustomButton_Style { + // Position of the label, use only one + wxCUSTBUT_LEFT = 0x0001, + wxCUSTBUT_RIGHT = 0x0002, + wxCUSTBUT_TOP = 0x0004, + wxCUSTBUT_BOTTOM = 0x0008, + // Button style, use only one + wxCUSTBUT_NOTOGGLE = 0x0100, + wxCUSTBUT_BUTTON = 0x0200, + wxCUSTBUT_TOGGLE = 0x0400, + wxCUSTBUT_BUT_DCLICK_TOG = 0x0800, + wxCUSTBUT_TOG_DCLICK_BUT = 0x1000, + // drawing styles + wxCUSTBUT_FLAT = 0x2000 // flat, mouseover raises if not depressed }; //----------------------------------------------------------------------------- // wxCustomButton //----------------------------------------------------------------------------- -class WXDLLIMPEXP_THINGS wxCustomButton : public wxControl -{ +class WXDLLIMPEXP_THINGS wxCustomButton : public wxControl { public: - - wxCustomButton() : wxControl() { Init(); } - - // wxToggleButton or wxButton compatible constructor (also wxTextCtrl) - wxCustomButton(wxWindow* parent, wxWindowID id, - const wxString& label, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxCUSTBUT_TOGGLE, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("wxCustomButton")) - : wxControl() - { - Init(); - Create(parent,id,label,wxNullBitmap,pos,size,style,val,name); - } - - // wxBitmapButton compatible constructor - wxCustomButton(wxWindow *parent, wxWindowID id, - const wxBitmap& bitmap, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxCUSTBUT_TOGGLE, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("wxCustomButton")) - : wxControl() - { - Init(); - Create(parent,id,wxEmptyString,bitmap,pos,size,style,val,name); - } - - // Native constructor - wxCustomButton(wxWindow *parent, wxWindowID id, - const wxString& label, const wxBitmap& bitmap, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("wxCustomButton")) - : wxControl() - { - Init(); - Create(parent,id,label,bitmap,pos,size,style,val,name); - } - - virtual ~wxCustomButton(); - - bool Create(wxWindow* parent, - wxWindowID id, - const wxString& label, - const wxBitmap &bitmap, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxValidator& val = wxDefaultValidator, - const wxString& name = wxT("wxCustomButton")); - - bool GetValue() const { return m_down%2 != 0; } - void SetValue( bool depressed ); - - // Use combinations of wxCustomButton_Style(s) - long GetButtonStyle() const { return m_button_style; } - bool SetButtonStyle( long style ); - - // Set the text label, wxEmptyString for none - void SetLabel( const wxString &label ); - - // set the bitmaps, ONLY this Label bitmap is used for calculating control size - // all bitmaps will be centered accordingly in any case - // call SetSet(GetBestSize()) if you change their size and want the control to resize appropriately - void SetBitmapLabel(const wxBitmap& bitmap); - void SetBitmapSelected(const wxBitmap& sel) { m_bmpSelected = sel; CalcLayout(true); }; - void SetBitmapFocus(const wxBitmap& focus) { m_bmpFocus = focus; CalcLayout(true); }; - void SetBitmapDisabled(const wxBitmap& disabled) { m_bmpDisabled = disabled; CalcLayout(true); }; - // wxBitmapButton compatibility - void SetLabel(const wxBitmap& bitmap) { SetBitmapLabel(bitmap); } - - // retrieve the bitmaps - const wxBitmap& GetBitmapLabel() const { return m_bmpLabel; } - const wxBitmap& GetBitmapSelected() const { return m_bmpSelected; } - const wxBitmap& GetBitmapFocus() const { return m_bmpFocus; } - const wxBitmap& GetBitmapDisabled() const { return m_bmpDisabled; } - - // Creates a "disabled" bitmap by dithering it with the background colour - wxBitmap CreateBitmapDisabled(const wxBitmap &bitmap) const; - - // set/get the margins (in pixels) around the label and bitmap - // if fit = true then resize the button to fit - void SetMargins(const wxSize &margin, bool fit = false); - - // set/get the margins around the text label - // the inter bitmap/label margin is the max of either margin, not the sum - void SetLabelMargin(const wxSize &margin, bool fit = false); - wxSize GetLabelMargin() const { return m_labelMargin; } - // set/get the margins around the bitmap - // the inter bitmap/label margin is the max of either margin, not the sum - void SetBitmapMargin(const wxSize &margin, bool fit = false); - wxSize GetBitmapMargin() const { return m_bitmapMargin; } - - // can be used to activate the focused behavior (see MenuButton) - void SetFocused(bool focused) { m_focused = focused; Refresh(false); } - bool GetFocused() const { return m_focused; } + wxCustomButton() : wxControl() { Init(); } + + // wxToggleButton or wxButton compatible constructor (also wxTextCtrl) + wxCustomButton(wxWindow *parent, wxWindowID id, const wxString &label, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + long style = wxCUSTBUT_TOGGLE, const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("wxCustomButton")) + : wxControl() + { + Init(); + Create(parent, id, label, wxNullBitmap, pos, size, style, val, name); + } + + // wxBitmapButton compatible constructor + wxCustomButton(wxWindow *parent, wxWindowID id, const wxBitmap &bitmap, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + long style = wxCUSTBUT_TOGGLE, const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("wxCustomButton")) + : wxControl() + { + Init(); + Create(parent, id, wxEmptyString, bitmap, pos, size, style, val, name); + } + + // Native constructor + wxCustomButton(wxWindow *parent, wxWindowID id, const wxString &label, const wxBitmap &bitmap, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + long style = wxCUSTBUT_TOGGLE | wxCUSTBUT_BOTTOM, + const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("wxCustomButton")) + : wxControl() + { + Init(); + Create(parent, id, label, bitmap, pos, size, style, val, name); + } + + virtual ~wxCustomButton(); + + bool Create(wxWindow *parent, wxWindowID id, const wxString &label, const wxBitmap &bitmap, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + long style = 0, const wxValidator &val = wxDefaultValidator, + const wxString &name = wxT("wxCustomButton")); + + bool GetValue() const { return m_down % 2 != 0; } + void SetValue(bool depressed); + + // Use combinations of wxCustomButton_Style(s) + long GetButtonStyle() const { return m_button_style; } + bool SetButtonStyle(long style); + + // Set the text label, wxEmptyString for none + void SetLabel(const wxString &label); + + // set the bitmaps, ONLY this Label bitmap is used for calculating control size + // all bitmaps will be centered accordingly in any case + // call SetSet(GetBestSize()) if you change their size and want the control to resize + // appropriately + void SetBitmapLabel(const wxBitmap &bitmap); + void SetBitmapSelected(const wxBitmap &sel) + { + m_bmpSelected = sel; + CalcLayout(true); + }; + void SetBitmapFocus(const wxBitmap &focus) + { + m_bmpFocus = focus; + CalcLayout(true); + }; + void SetBitmapDisabled(const wxBitmap &disabled) + { + m_bmpDisabled = disabled; + CalcLayout(true); + }; + // wxBitmapButton compatibility + void SetLabel(const wxBitmap &bitmap) { SetBitmapLabel(bitmap); } + + // retrieve the bitmaps + const wxBitmap &GetBitmapLabel() const { return m_bmpLabel; } + const wxBitmap &GetBitmapSelected() const { return m_bmpSelected; } + const wxBitmap &GetBitmapFocus() const { return m_bmpFocus; } + const wxBitmap &GetBitmapDisabled() const { return m_bmpDisabled; } + + // Creates a "disabled" bitmap by dithering it with the background colour + wxBitmap CreateBitmapDisabled(const wxBitmap &bitmap) const; + + // set/get the margins (in pixels) around the label and bitmap + // if fit = true then resize the button to fit + void SetMargins(const wxSize &margin, bool fit = false); + + // set/get the margins around the text label + // the inter bitmap/label margin is the max of either margin, not the sum + void SetLabelMargin(const wxSize &margin, bool fit = false); + wxSize GetLabelMargin() const { return m_labelMargin; } + // set/get the margins around the bitmap + // the inter bitmap/label margin is the max of either margin, not the sum + void SetBitmapMargin(const wxSize &margin, bool fit = false); + wxSize GetBitmapMargin() const { return m_bitmapMargin; } + + // can be used to activate the focused behavior (see MenuButton) + void SetFocused(bool focused) + { + m_focused = focused; + Refresh(false); + } + bool GetFocused() const { return m_focused; } protected: - void OnPaint(wxPaintEvent &event); - void Redraw(); - virtual void Paint( wxDC &dc ); + void OnPaint(wxPaintEvent &event); + void Redraw(); + virtual void Paint(wxDC &dc); - virtual wxSize DoGetBestSize() const; + virtual wxSize DoGetBestSize() const; - virtual void SendEvent(); + virtual void SendEvent(); - void OnMouseEvents(wxMouseEvent &event); + void OnMouseEvents(wxMouseEvent &event); - void OnTimer(wxTimerEvent &event); - void OnSize( wxSizeEvent &event ); + void OnTimer(wxTimerEvent &event); + void OnSize(wxSizeEvent &event); - virtual void CalcLayout(bool refresh); + virtual void CalcLayout(bool refresh); - int m_down; // toggle state if m_down%2 then depressed - bool m_focused; // mouse in window - long m_button_style; + int m_down; // toggle state if m_down%2 then depressed + bool m_focused; // mouse in window + long m_button_style; - // the bitmaps for various states - wxBitmap m_bmpLabel, - m_bmpSelected, - m_bmpFocus, - m_bmpDisabled; + // the bitmaps for various states + wxBitmap m_bmpLabel, m_bmpSelected, m_bmpFocus, m_bmpDisabled; - // the margins around the label/bitmap - wxSize m_labelMargin, - m_bitmapMargin; + // the margins around the label/bitmap + wxSize m_labelMargin, m_bitmapMargin; - wxPoint m_bitmapPos, - m_labelPos; + wxPoint m_bitmapPos, m_labelPos; - wxTimer *m_timer; + wxTimer *m_timer; - wxEventType m_eventType; // store the mouse event type + wxEventType m_eventType; // store the mouse event type private: - void Init(); - DECLARE_DYNAMIC_CLASS(wxCustomButton) - DECLARE_EVENT_TABLE() + void Init(); + DECLARE_DYNAMIC_CLASS(wxCustomButton) + DECLARE_EVENT_TABLE() }; -#endif // _WX_CUSTOMBUTTON_H_ +#endif // _WX_CUSTOMBUTTON_H_ diff --git a/src/labenski/src/block.cpp b/src/labenski/src/block.cpp index 54b441fa2..ca4921db1 100644 --- a/src/labenski/src/block.cpp +++ b/src/labenski/src/block.cpp @@ -11,21 +11,25 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - //#include "wx/object.h" +// #include "wx/object.h" #endif // WX_PRECOMP #include "wx/wxthings/block.h" // use this to check to see if there is any overlap after minimizing -//#define CHECK_BLOCK_OVERLAP 1 +// #define CHECK_BLOCK_OVERLAP 1 -#include "wx/crt.h" // for wxPrintf +#include "wx/crt.h" // for wxPrintf -#define PRINT_BLOCK(msg, b) { wxPrintf(wxT("Block '%s' %lg %lg %lg %lg\n"), msg, (double)(b).m_x1, (double)(b).m_y1, (double)(b).m_x2, (double)(b).m_y2); } +#define PRINT_BLOCK(msg, b) \ + { \ + wxPrintf(wxT("Block '%s' %lg %lg %lg %lg\n"), msg, (double)(b).m_x1, (double)(b).m_y1, \ + (double)(b).m_x2, (double)(b).m_y2); \ + } wxBlockInt const wxEmptyBlockInt(0, 0, -1, -1); wxBlockDouble const wxEmptyBlockDouble(0, 0, -1, -1); @@ -40,120 +44,182 @@ WX_DEFINE_OBJARRAY(wxArrayBlockDoubleSelection); // Sorting functions for wxBlockInt // ---------------------------------------------------------------------------- -static int wxCMPFUNC_CONV wxblockint_sort_topleft_bottomright( wxBlockInt **a, wxBlockInt **b) +static int wxCMPFUNC_CONV wxblockint_sort_topleft_bottomright(wxBlockInt **a, wxBlockInt **b) { - int y = ((*a)->m_y1 - (*b)->m_y1); - - if (y < 0) return -1; - if (y == 0) return ((*a)->m_x1 - (*b)->m_x1); - return 1; + int y = ((*a)->m_y1 - (*b)->m_y1); + + if (y < 0) { + return -1; + } + if (y == 0) { + return ((*a)->m_x1 - (*b)->m_x1); + } + return 1; } -static int wxCMPFUNC_CONV wxblockint_sort_topright_bottomleft( wxBlockInt **a, wxBlockInt **b) +static int wxCMPFUNC_CONV wxblockint_sort_topright_bottomleft(wxBlockInt **a, wxBlockInt **b) { - int y = ((*a)->m_y1 - (*b)->m_y1); - - if (y < 0) return -1; - if (y == 0) return ((*a)->m_x2 - (*b)->m_x2); - return 1; + int y = ((*a)->m_y1 - (*b)->m_y1); + + if (y < 0) { + return -1; + } + if (y == 0) { + return ((*a)->m_x2 - (*b)->m_x2); + } + return 1; } -static int wxCMPFUNC_CONV wxblockint_sort_bottomleft_topright( wxBlockInt **a, wxBlockInt **b) +static int wxCMPFUNC_CONV wxblockint_sort_bottomleft_topright(wxBlockInt **a, wxBlockInt **b) { - int y = ((*a)->m_y2 - (*b)->m_y2); - - if (y > 0) return -1; - if (y == 0) return ((*a)->m_x1 - (*b)->m_x1); - return 1; + int y = ((*a)->m_y2 - (*b)->m_y2); + + if (y > 0) { + return -1; + } + if (y == 0) { + return ((*a)->m_x1 - (*b)->m_x1); + } + return 1; } -static int wxCMPFUNC_CONV wxblockint_sort_bottomright_topleft( wxBlockInt **a, wxBlockInt **b) +static int wxCMPFUNC_CONV wxblockint_sort_bottomright_topleft(wxBlockInt **a, wxBlockInt **b) { - int y = ((*a)->m_y2 - (*b)->m_y2); - - if (y > 0) return -1; - if (y == 0) return ((*a)->m_x2 - (*b)->m_x2); - return 1; + int y = ((*a)->m_y2 - (*b)->m_y2); + + if (y > 0) { + return -1; + } + if (y == 0) { + return ((*a)->m_x2 - (*b)->m_x2); + } + return 1; } -static int wxCMPFUNC_CONV wxblockint_sort_largest_to_smallest( wxBlockInt **a, wxBlockInt **b) +static int wxCMPFUNC_CONV wxblockint_sort_largest_to_smallest(wxBlockInt **a, wxBlockInt **b) { - return (*a)->IsLarger(**b); + return (*a)->IsLarger(**b); } -static int wxCMPFUNC_CONV wxblockint_sort_smallest_to_largest( wxBlockInt **a, wxBlockInt **b) +static int wxCMPFUNC_CONV wxblockint_sort_smallest_to_largest(wxBlockInt **a, wxBlockInt **b) { - return -(*a)->IsLarger(**b); + return -(*a)->IsLarger(**b); } void wxArrayBlockIntSort(wxArrayBlockInt &blocks, wxBlockSort_Type type) { - switch (type) - { - case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockint_sort_topleft_bottomright); break; - case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockint_sort_topright_bottomleft); break; - case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockint_sort_bottomleft_topright); break; - case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockint_sort_bottomright_topleft); break; - case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockint_sort_smallest_to_largest); break; - case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockint_sort_largest_to_smallest); break; - default : wxFAIL_MSG(wxT("unknown block sort type")); - } + switch (type) { + case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT: + blocks.Sort(wxblockint_sort_topleft_bottomright); + break; + case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT: + blocks.Sort(wxblockint_sort_topright_bottomleft); + break; + case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT: + blocks.Sort(wxblockint_sort_bottomleft_topright); + break; + case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT: + blocks.Sort(wxblockint_sort_bottomright_topleft); + break; + case wxBLOCKSORT_SMALLEST_TO_LARGEST: + blocks.Sort(wxblockint_sort_smallest_to_largest); + break; + case wxBLOCKSORT_LARGEST_TO_SMALLEST: + blocks.Sort(wxblockint_sort_largest_to_smallest); + break; + default: + wxFAIL_MSG(wxT("unknown block sort type")); + } } // ---------------------------------------------------------------------------- // Sorting functions for wxBlockDouble // ---------------------------------------------------------------------------- -static int wxCMPFUNC_CONV wxblockdouble_sort_topleft_bottomright( wxBlockDouble **a, wxBlockDouble **b) +static int wxCMPFUNC_CONV wxblockdouble_sort_topleft_bottomright(wxBlockDouble **a, + wxBlockDouble **b) { - wxDouble y = ((*a)->m_y1 - (*b)->m_y1); - - if (y < 0) return -1; - if (y == 0) return int((*a)->m_x1 - (*b)->m_x1); - return 1; + wxDouble y = ((*a)->m_y1 - (*b)->m_y1); + + if (y < 0) { + return -1; + } + if (y == 0) { + return int((*a)->m_x1 - (*b)->m_x1); + } + return 1; } -static int wxCMPFUNC_CONV wxblockdouble_sort_topright_bottomleft( wxBlockDouble **a, wxBlockDouble **b) +static int wxCMPFUNC_CONV wxblockdouble_sort_topright_bottomleft(wxBlockDouble **a, + wxBlockDouble **b) { - wxDouble y = ((*a)->m_y1 - (*b)->m_y1); - - if (y < 0) return -1; - if (y == 0) return int((*a)->m_x2 - (*b)->m_x2); - return 1; + wxDouble y = ((*a)->m_y1 - (*b)->m_y1); + + if (y < 0) { + return -1; + } + if (y == 0) { + return int((*a)->m_x2 - (*b)->m_x2); + } + return 1; } -static int wxCMPFUNC_CONV wxblockdouble_sort_bottomleft_topright( wxBlockDouble **a, wxBlockDouble **b) +static int wxCMPFUNC_CONV wxblockdouble_sort_bottomleft_topright(wxBlockDouble **a, + wxBlockDouble **b) { - wxDouble y = ((*a)->m_y2 - (*b)->m_y2); - - if (y > 0) return -1; - if (y == 0) return int((*a)->m_x1 - (*b)->m_x1); - return 1; + wxDouble y = ((*a)->m_y2 - (*b)->m_y2); + + if (y > 0) { + return -1; + } + if (y == 0) { + return int((*a)->m_x1 - (*b)->m_x1); + } + return 1; } -static int wxCMPFUNC_CONV wxblockdouble_sort_bottomright_topleft( wxBlockDouble **a, wxBlockDouble **b) +static int wxCMPFUNC_CONV wxblockdouble_sort_bottomright_topleft(wxBlockDouble **a, + wxBlockDouble **b) { - wxDouble y = ((*a)->m_y2 - (*b)->m_y2); - - if (y > 0) return -1; - if (y == 0) return int((*a)->m_x2 - (*b)->m_x2); - return 1; + wxDouble y = ((*a)->m_y2 - (*b)->m_y2); + + if (y > 0) { + return -1; + } + if (y == 0) { + return int((*a)->m_x2 - (*b)->m_x2); + } + return 1; } -static int wxCMPFUNC_CONV wxblockdouble_sort_largest_to_smallest( wxBlockDouble **a, wxBlockDouble **b) +static int wxCMPFUNC_CONV wxblockdouble_sort_largest_to_smallest(wxBlockDouble **a, + wxBlockDouble **b) { - return (*a)->IsLarger(**b); + return (*a)->IsLarger(**b); } -static int wxCMPFUNC_CONV wxblockdouble_sort_smallest_to_largest( wxBlockDouble **a, wxBlockDouble **b) +static int wxCMPFUNC_CONV wxblockdouble_sort_smallest_to_largest(wxBlockDouble **a, + wxBlockDouble **b) { - return -(*a)->IsLarger(**b); + return -(*a)->IsLarger(**b); } void wxArrayBlockDoubleSort(wxArrayBlockDouble &blocks, wxBlockSort_Type type) { - switch (type) - { - case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT : blocks.Sort(wxblockdouble_sort_topleft_bottomright); break; - case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT : blocks.Sort(wxblockdouble_sort_topright_bottomleft); break; - case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT : blocks.Sort(wxblockdouble_sort_bottomleft_topright); break; - case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT : blocks.Sort(wxblockdouble_sort_bottomright_topleft); break; - case wxBLOCKSORT_SMALLEST_TO_LARGEST : blocks.Sort(wxblockdouble_sort_smallest_to_largest); break; - case wxBLOCKSORT_LARGEST_TO_SMALLEST : blocks.Sort(wxblockdouble_sort_largest_to_smallest); break; - default : wxFAIL_MSG(wxT("unknown block sort type")); - } + switch (type) { + case wxBLOCKSORT_TOPLEFT_BOTTOMRIGHT: + blocks.Sort(wxblockdouble_sort_topleft_bottomright); + break; + case wxBLOCKSORT_TOPRIGHT_BOTTOMLEFT: + blocks.Sort(wxblockdouble_sort_topright_bottomleft); + break; + case wxBLOCKSORT_BOTTOMLEFT_TOPRIGHT: + blocks.Sort(wxblockdouble_sort_bottomleft_topright); + break; + case wxBLOCKSORT_BOTTOMRIGHT_TOPLEFT: + blocks.Sort(wxblockdouble_sort_bottomright_topleft); + break; + case wxBLOCKSORT_SMALLEST_TO_LARGEST: + blocks.Sort(wxblockdouble_sort_smallest_to_largest); + break; + case wxBLOCKSORT_LARGEST_TO_SMALLEST: + blocks.Sort(wxblockdouble_sort_largest_to_smallest); + break; + default: + wxFAIL_MSG(wxT("unknown block sort type")); + } } //============================================================================= @@ -165,170 +231,175 @@ void wxArrayBlockDoubleSort(wxArrayBlockDouble &blocks, wxBlockSort_Type type) #ifdef TEST_BLOCKS void TestBlocks() { - printf("Start Testing blocks -----------------------------------------\n"); - wxBlockInt b1(1,1,4,4); - wxBlockInt b2(5,4,10,11); - PRINT_BLOCK("b1", b1) - PRINT_BLOCK("b2", b2) - - wxBlockInt iB; - iB.Intersect(b1, b2, &iB); - PRINT_BLOCK("Intersect b1 b2", iB) - - wxBlockInt uB; - uB.Union(b1, b2, &uB); - PRINT_BLOCK("Union b1 b2", uB) - - printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); - - b1 = wxBlockInt(2,3,7,9); - b2 = wxBlockInt(8,3,8,3); - printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); - - b1 = wxBlockInt(2,3,7,9); - b2 = wxBlockInt(1,3,1,3); - printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); - iB.Intersect(b1, b2, &iB); - PRINT_BLOCK("Intersect b1 b2", iB) - - b1 = wxBlockInt(2,3,7,9); - b2 = wxBlockInt(2,2,2,2); - printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); - - b1 = wxBlockInt(2,3,7,9); - b2 = wxBlockInt(7,10,7,10); - printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); - - printf("End Testing blocks -----------------------------------------\n"); - fflush(stdout); + printf("Start Testing blocks -----------------------------------------\n"); + wxBlockInt b1(1, 1, 4, 4); + wxBlockInt b2(5, 4, 10, 11); + PRINT_BLOCK("b1", b1) + PRINT_BLOCK("b2", b2) + + wxBlockInt iB; + iB.Intersect(b1, b2, &iB); + PRINT_BLOCK("Intersect b1 b2", iB) + + wxBlockInt uB; + uB.Union(b1, b2, &uB); + PRINT_BLOCK("Union b1 b2", uB) + + printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); + + b1 = wxBlockInt(2, 3, 7, 9); + b2 = wxBlockInt(8, 3, 8, 3); + printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); + + b1 = wxBlockInt(2, 3, 7, 9); + b2 = wxBlockInt(1, 3, 1, 3); + printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); + iB.Intersect(b1, b2, &iB); + PRINT_BLOCK("Intersect b1 b2", iB) + + b1 = wxBlockInt(2, 3, 7, 9); + b2 = wxBlockInt(2, 2, 2, 2); + printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); + + b1 = wxBlockInt(2, 3, 7, 9); + b2 = wxBlockInt(7, 10, 7, 10); + printf("Touches b1 b2 %d %d\n", b1.Touches(b2), b2.Touches(b1)); + + printf("End Testing blocks -----------------------------------------\n"); + fflush(stdout); } -#endif //TEST_BLOCKS +#endif // TEST_BLOCKS bool wxBlockInt::Touches(const wxBlockInt &b) const // see Intersects { - //if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) && - // ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2)))) - // return true; - - return Intersects(wxBlockInt(b.m_x1-1, b.m_y1-1, b.m_x2+1, b.m_y2+1)); - -/* - wxInt32 left = wxMax( m_x1, b.m_x1 ); - wxInt32 right = wxMin( m_x2, b.m_x2 ); - - if (labs(left - right) <= 1) - { - wxInt32 top = wxMax( m_y1, b.m_y1 ); - wxInt32 bottom = wxMin( m_y2, b.m_y2 ); - if (labs(top - bottom) <= 1) - return true; - } - return false; -*/ + // if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) && + // ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2)))) + // return true; + + return Intersects(wxBlockInt(b.m_x1 - 1, b.m_y1 - 1, b.m_x2 + 1, b.m_y2 + 1)); + + /* + wxInt32 left = wxMax( m_x1, b.m_x1 ); + wxInt32 right = wxMin( m_x2, b.m_x2 ); + + if (labs(left - right) <= 1) + { + wxInt32 top = wxMax( m_y1, b.m_y1 ); + wxInt32 bottom = wxMin( m_y2, b.m_y2 ); + if (labs(top - bottom) <= 1) + return true; + } + return false; + */ } bool wxBlockInt::Combine(const wxBlockInt &b) { - if (!Touches(b)) return false; - if (Contains(b)) return true; - if (b.Contains(*this)) - { - *this = b; - return true; - } - - wxBlockInt unionBlock; - Union( *this, b, &unionBlock ); - - if (unionBlock.IsEmpty()) return false; - - // at least one of the two blocks has to be at each corner of the union - if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) && - ((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) && - ((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) && - ((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) ) - { - *this = unionBlock; - return true; - } - + if (!Touches(b)) { return false; -} - -bool wxBlockInt::Combine( const wxBlockInt &block, - wxBlockInt &top, wxBlockInt &bottom, - wxBlockInt &left, wxBlockInt &right) const -{ - top = bottom = left = right = wxEmptyBlockInt; - - wxBlockInt iBlock; - Intersect(*this, block, &iBlock); - - if (iBlock.IsEmpty()) return false; // nothing to combine - if (iBlock == *this) return true; // can combine all of this, no leftover + } + if (Contains(b)) { + return true; + } + if (b.Contains(*this)) { + *this = b; + return true; + } - bool combined = false; + wxBlockInt unionBlock; + Union(*this, b, &unionBlock); - if ( block.m_y1 < m_y1 ) - { - top = wxBlockInt( block.m_x1, block.m_y1, block.m_x2, m_y1-1 ); - combined = true; - } - if ( block.m_y2 > m_y2 ) - { - bottom = wxBlockInt( block.m_x1, m_y2+1, block.m_x2, block.m_y2 ); - combined = true; - } - if ( block.m_x1 < m_x1 ) - { - left = wxBlockInt( block.m_x1, iBlock.m_y1, m_x1-1, iBlock.m_y2 ); - combined = true; - } - if ( block.m_x2 > m_x2 ) - { - right = wxBlockInt( m_x2+1, iBlock.m_y1, block.m_x2, iBlock.m_y2 ); - combined = true; - } + if (unionBlock.IsEmpty()) { + return false; + } + + // at least one of the two blocks has to be at each corner of the union + if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) && + ((unionBlock.GetRightTop() == GetRightTop()) || + (unionBlock.GetRightTop() == b.GetRightTop())) && + ((unionBlock.GetLeftBottom() == GetLeftBottom()) || + (unionBlock.GetLeftBottom() == b.GetLeftBottom())) && + ((unionBlock.GetRightBottom() == GetRightBottom()) || + (unionBlock.GetRightBottom() == b.GetRightBottom()))) { + *this = unionBlock; + return true; + } - return combined; + return false; } -bool wxBlockInt::Delete( const wxBlockInt &block, - wxBlockInt &top, wxBlockInt &bottom, +bool wxBlockInt::Combine(const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, wxBlockInt &left, wxBlockInt &right) const { - top = bottom = left = right = wxEmptyBlockInt; - - wxBlockInt iBlock; - Intersect(*this, block, &iBlock); - - if (iBlock.IsEmpty()) return false; // nothing to delete - if (iBlock == *this) return true; // can delete all of this, no leftover - - bool deleted = false; - - if ( m_y1 < iBlock.m_y1 ) - { - top = wxBlockInt( m_x1, m_y1, m_x2, iBlock.m_y1-1 ); - deleted = true; - } - if ( GetBottom() > iBlock.GetBottom() ) - { - bottom = wxBlockInt( m_x1, iBlock.m_y2+1, m_x2, m_y2 ); - deleted = true; - } - if ( m_x1 < iBlock.m_x1 ) - { - left = wxBlockInt( m_x1, iBlock.m_y1, iBlock.m_x1-1, iBlock.m_y2 ); - deleted = true; - } - if ( GetRight() > iBlock.GetRight() ) - { - right = wxBlockInt( iBlock.m_x2+1, iBlock.m_y1, m_x2, iBlock.m_y2 ); - deleted = true; - } + top = bottom = left = right = wxEmptyBlockInt; + + wxBlockInt iBlock; + Intersect(*this, block, &iBlock); + + if (iBlock.IsEmpty()) { + return false; // nothing to combine + } + if (iBlock == *this) { + return true; // can combine all of this, no leftover + } + + bool combined = false; + + if (block.m_y1 < m_y1) { + top = wxBlockInt(block.m_x1, block.m_y1, block.m_x2, m_y1 - 1); + combined = true; + } + if (block.m_y2 > m_y2) { + bottom = wxBlockInt(block.m_x1, m_y2 + 1, block.m_x2, block.m_y2); + combined = true; + } + if (block.m_x1 < m_x1) { + left = wxBlockInt(block.m_x1, iBlock.m_y1, m_x1 - 1, iBlock.m_y2); + combined = true; + } + if (block.m_x2 > m_x2) { + right = wxBlockInt(m_x2 + 1, iBlock.m_y1, block.m_x2, iBlock.m_y2); + combined = true; + } + + return combined; +} - return deleted; +bool wxBlockInt::Delete(const wxBlockInt &block, wxBlockInt &top, wxBlockInt &bottom, + wxBlockInt &left, wxBlockInt &right) const +{ + top = bottom = left = right = wxEmptyBlockInt; + + wxBlockInt iBlock; + Intersect(*this, block, &iBlock); + + if (iBlock.IsEmpty()) { + return false; // nothing to delete + } + if (iBlock == *this) { + return true; // can delete all of this, no leftover + } + + bool deleted = false; + + if (m_y1 < iBlock.m_y1) { + top = wxBlockInt(m_x1, m_y1, m_x2, iBlock.m_y1 - 1); + deleted = true; + } + if (GetBottom() > iBlock.GetBottom()) { + bottom = wxBlockInt(m_x1, iBlock.m_y2 + 1, m_x2, m_y2); + deleted = true; + } + if (m_x1 < iBlock.m_x1) { + left = wxBlockInt(m_x1, iBlock.m_y1, iBlock.m_x1 - 1, iBlock.m_y2); + deleted = true; + } + if (GetRight() > iBlock.GetRight()) { + right = wxBlockInt(iBlock.m_x2 + 1, iBlock.m_y1, m_x2, iBlock.m_y2); + deleted = true; + } + + return deleted; } //============================================================================= @@ -337,721 +408,738 @@ bool wxBlockInt::Delete( const wxBlockInt &block, bool wxBlockDouble::Touches(const wxBlockDouble &b) const // see Intersects { - if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) && - ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2)))) - return true; + if (((wxMax(m_x1, b.m_x1)) <= (wxMin(m_x2, b.m_x2))) && + ((wxMax(m_y1, b.m_y1)) <= (wxMin(m_y2, b.m_y2)))) { + return true; + } - return false; + return false; } bool wxBlockDouble::Combine(const wxBlockDouble &b) { - if (!Touches(b)) return false; - if (Contains(b)) return true; - if (b.Contains(*this)) - { - *this = b; - return true; - } - - wxBlockDouble unionBlock; - Union( *this, b, &unionBlock ); - - if (unionBlock.IsEmpty()) return false; - - // at least one of the two blocks has to be at each corner of the union - if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) && - ((unionBlock.GetRightTop() == GetRightTop()) || (unionBlock.GetRightTop() == b.GetRightTop())) && - ((unionBlock.GetLeftBottom() == GetLeftBottom()) || (unionBlock.GetLeftBottom() == b.GetLeftBottom())) && - ((unionBlock.GetRightBottom() == GetRightBottom()) || (unionBlock.GetRightBottom() == b.GetRightBottom())) ) - { - *this = unionBlock; - return true; - } - + if (!Touches(b)) { return false; -} - -bool wxBlockDouble::Combine( const wxBlockDouble &block, - wxBlockDouble &top, wxBlockDouble &bottom, - wxBlockDouble &left, wxBlockDouble &right) const -{ - top = bottom = left = right = wxEmptyBlockDouble; - - wxBlockDouble iBlock; - Intersect(*this, block, &iBlock); - - if (iBlock.IsEmpty()) return false; // nothing to combine - if (iBlock == *this) return true; // can combine all of this, no leftover + } + if (Contains(b)) { + return true; + } + if (b.Contains(*this)) { + *this = b; + return true; + } - bool combined = false; + wxBlockDouble unionBlock; + Union(*this, b, &unionBlock); - if ( block.m_y1 < m_y1 ) - { - top = wxBlockDouble( block.m_x1, block.m_y1, block.m_x2, m_y1 ); - combined = true; - } - if ( block.m_y2 > m_y2 ) - { - bottom = wxBlockDouble( block.m_x1, m_y2, block.m_x2, block.m_y2 ); - combined = true; - } - if ( block.m_x1 < m_x1 ) - { - left = wxBlockDouble( block.m_x1, iBlock.m_y1, m_x1, iBlock.m_y2 ); - combined = true; - } - if ( block.m_x2 > m_x2 ) - { - right = wxBlockDouble( m_x2, iBlock.m_y1, block.m_x2, iBlock.m_y2 ); - combined = true; - } + if (unionBlock.IsEmpty()) { + return false; + } + + // at least one of the two blocks has to be at each corner of the union + if (((unionBlock.GetLeftTop() == GetLeftTop()) || (unionBlock.GetLeftTop() == b.GetLeftTop())) && + ((unionBlock.GetRightTop() == GetRightTop()) || + (unionBlock.GetRightTop() == b.GetRightTop())) && + ((unionBlock.GetLeftBottom() == GetLeftBottom()) || + (unionBlock.GetLeftBottom() == b.GetLeftBottom())) && + ((unionBlock.GetRightBottom() == GetRightBottom()) || + (unionBlock.GetRightBottom() == b.GetRightBottom()))) { + *this = unionBlock; + return true; + } - return combined; + return false; } -bool wxBlockDouble::Delete( const wxBlockDouble &block, - wxBlockDouble &top, wxBlockDouble &bottom, +bool wxBlockDouble::Combine(const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, wxBlockDouble &left, wxBlockDouble &right) const { - top = bottom = left = right = wxEmptyBlockDouble; - - wxBlockDouble iBlock; - Intersect(*this, block, &iBlock); - - if (iBlock.IsEmpty()) return false; // nothing to delete - if (iBlock == *this) return true; // can delete all of this, no leftover - - bool deleted = false; - - if ( m_y1 < iBlock.m_y1 ) - { - top = wxBlockDouble( m_x1, m_y1, m_x2, iBlock.m_y1 ); - deleted = true; - } - if ( m_y2 > iBlock.m_y2 ) - { - bottom = wxBlockDouble( m_x1, iBlock.m_y2, m_x2, m_y2 ); - deleted = true; - } - if ( m_x1 < iBlock.m_x1 ) - { - left = wxBlockDouble( m_x1, iBlock.m_y1, iBlock.m_x1, iBlock.m_y2 ); - deleted = true; - } - if ( m_x2 > iBlock.m_x2 ) - { - right = wxBlockDouble( iBlock.m_x2, iBlock.m_y1, m_x2, iBlock.m_y2 ); - deleted = true; - } + top = bottom = left = right = wxEmptyBlockDouble; + + wxBlockDouble iBlock; + Intersect(*this, block, &iBlock); + + if (iBlock.IsEmpty()) { + return false; // nothing to combine + } + if (iBlock == *this) { + return true; // can combine all of this, no leftover + } + + bool combined = false; + + if (block.m_y1 < m_y1) { + top = wxBlockDouble(block.m_x1, block.m_y1, block.m_x2, m_y1); + combined = true; + } + if (block.m_y2 > m_y2) { + bottom = wxBlockDouble(block.m_x1, m_y2, block.m_x2, block.m_y2); + combined = true; + } + if (block.m_x1 < m_x1) { + left = wxBlockDouble(block.m_x1, iBlock.m_y1, m_x1, iBlock.m_y2); + combined = true; + } + if (block.m_x2 > m_x2) { + right = wxBlockDouble(m_x2, iBlock.m_y1, block.m_x2, iBlock.m_y2); + combined = true; + } + + return combined; +} - return deleted; +bool wxBlockDouble::Delete(const wxBlockDouble &block, wxBlockDouble &top, wxBlockDouble &bottom, + wxBlockDouble &left, wxBlockDouble &right) const +{ + top = bottom = left = right = wxEmptyBlockDouble; + + wxBlockDouble iBlock; + Intersect(*this, block, &iBlock); + + if (iBlock.IsEmpty()) { + return false; // nothing to delete + } + if (iBlock == *this) { + return true; // can delete all of this, no leftover + } + + bool deleted = false; + + if (m_y1 < iBlock.m_y1) { + top = wxBlockDouble(m_x1, m_y1, m_x2, iBlock.m_y1); + deleted = true; + } + if (m_y2 > iBlock.m_y2) { + bottom = wxBlockDouble(m_x1, iBlock.m_y2, m_x2, m_y2); + deleted = true; + } + if (m_x1 < iBlock.m_x1) { + left = wxBlockDouble(m_x1, iBlock.m_y1, iBlock.m_x1, iBlock.m_y2); + deleted = true; + } + if (m_x2 > iBlock.m_x2) { + right = wxBlockDouble(iBlock.m_x2, iBlock.m_y1, m_x2, iBlock.m_y2); + deleted = true; + } + + return deleted; } //============================================================================= // wxBlockIntSelection //============================================================================= -wxBlockInt wxBlockIntSelection::GetBlock( int index ) const +wxBlockInt wxBlockIntSelection::GetBlock(int index) const { - wxCHECK_MSG((index>=0) && (index= 0) && (index < int(m_blocks.GetCount())), wxEmptyBlockInt, + wxT("Invalid index")); + return m_blocks[index]; } #ifdef USE_wxRANGE wxArrayRangeInt wxBlockIntSelection::GetBlockCol(int col) const { - wxArrayRangeInt ranges; - int n, count = m_blocks.GetCount(); - for (n=0; n= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2)) - { - wxRangeInt range(m_blocks[n].m_y1, m_blocks[n].m_y2); - ranges.Add(range); - } + wxArrayRangeInt ranges; + int n, count = m_blocks.GetCount(); + for (n = 0; n < count; n++) { + if ((col >= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2)) { + wxRangeInt range(m_blocks[n].m_y1, m_blocks[n].m_y2); + ranges.Add(range); } - return ranges; + } + return ranges; } wxArrayRangeInt wxBlockIntSelection::GetBlockRow(int row) const { - wxArrayRangeInt ranges; - int n, count = m_blocks.GetCount(); - for (n=0; n= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2)) - ranges.Add(wxRangeInt(m_blocks[n].m_x1, m_blocks[n].m_x2)); + wxArrayRangeInt ranges; + int n, count = m_blocks.GetCount(); + for (n = 0; n < count; n++) { + if ((row >= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2)) { + ranges.Add(wxRangeInt(m_blocks[n].m_x1, m_blocks[n].m_x2)); } - return ranges; + } + return ranges; } #endif // USE_wxRANGE wxBlockInt wxBlockIntSelection::GetBoundingBlock() const { - int n, count = m_blocks.GetCount(); - if (count == 0) return wxEmptyBlockInt; - wxBlockInt bound = m_blocks[0]; - for (n=1; n 0) ? n - 1 : -1; - - if (!top.IsEmpty()) m_blocks.Add(top); - if (!bottom.IsEmpty()) m_blocks.Add(bottom); - if (!left.IsEmpty()) m_blocks.Add(left); - if (!right.IsEmpty()) m_blocks.Add(right); - } + wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block")); + + bool done = false; + + wxBlockInt top, bottom, left, right; + for (int n = 0; n < int(m_blocks.GetCount()); n++) { + if (m_blocks[n].Delete(block, top, bottom, left, right)) { + done = true; + m_blocks.RemoveAt(n); + n = (n > 0) ? n - 1 : -1; + + if (!top.IsEmpty()) { + m_blocks.Add(top); + } + if (!bottom.IsEmpty()) { + m_blocks.Add(bottom); + } + if (!left.IsEmpty()) { + m_blocks.Add(left); + } + if (!right.IsEmpty()) { + m_blocks.Add(right); + } } + } - if (combineNow) - Minimize(); + if (combineNow) { + Minimize(); + } - return done; + return done; } -bool wxBlockIntSelection::SelectBlock( const wxBlockInt &block, bool combineNow, - wxArrayBlockInt *addedBlocks ) +bool wxBlockIntSelection::SelectBlock(const wxBlockInt &block, bool combineNow, + wxArrayBlockInt *addedBlocks) { - wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") ); + wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block")); - //TestBlocks(); + // TestBlocks(); - wxArrayBlockInt extraBlocks; - wxArrayBlockInt *extra = &extraBlocks; + wxArrayBlockInt extraBlocks; + wxArrayBlockInt *extra = &extraBlocks; - if (addedBlocks != NULL) - { - addedBlocks->Clear(); - extra = addedBlocks; - } + if (addedBlocks != NULL) { + addedBlocks->Clear(); + extra = addedBlocks; + } - extra->Add(block); - - int n, count = m_blocks.GetCount(); - wxBlockInt top, bottom, left, right; - - for (n=0; nGetCount()); k++) - { - if (m_blocks[n].Combine(extra->Item(k), top, bottom, left, right)) - { - extra->RemoveAt(k); - if (!top.IsEmpty()) extra->Add(top); - if (!bottom.IsEmpty()) extra->Add(bottom); - if (!left.IsEmpty()) extra->Add(left); - if (!right.IsEmpty()) extra->Add(right); - //DoMinimize( *extra ); - n = -1; - break; - } + extra->Add(block); + + int n, count = m_blocks.GetCount(); + wxBlockInt top, bottom, left, right; + + for (n = 0; n < count; n++) { + for (int k = 0; k < int(extra->GetCount()); k++) { + if (m_blocks[n].Combine(extra->Item(k), top, bottom, left, right)) { + extra->RemoveAt(k); + if (!top.IsEmpty()) { + extra->Add(top); + } + if (!bottom.IsEmpty()) { + extra->Add(bottom); + } + if (!left.IsEmpty()) { + extra->Add(left); } + if (!right.IsEmpty()) { + extra->Add(right); + } + // DoMinimize( *extra ); + n = -1; + break; + } } + } - if (extra->GetCount() > 0u) - { - WX_APPEND_ARRAY(m_blocks, *extra); - if (combineNow) - Minimize(); - - return true; + if (extra->GetCount() > 0u) { + WX_APPEND_ARRAY(m_blocks, *extra); + if (combineNow) { + Minimize(); } - return false; + return true; + } + + return false; } bool wxBlockIntSelection::Minimize() { - bool ret = DoMinimize(m_blocks); - Sort(m_sort); - return ret; + bool ret = DoMinimize(m_blocks); + Sort(m_sort); + return ret; } bool wxBlockIntSelection::DoMinimize(wxArrayBlockInt &blocks) { - int n; - for (n=0; n<1000; n++) // should probably just take a few - { - if (!DoDoMinimize(blocks)) break; + int n; + for (n = 0; n < 1000; n++) // should probably just take a few + { + if (!DoDoMinimize(blocks)) { + break; } + } #ifdef CHECK_BLOCK_OVERLAP - for (size_t a=0; a=0) && (index= 0) && (index < int(m_blocks.GetCount())), wxEmptyBlockDouble, + wxT("Invalid index")); + return m_blocks[index]; } #ifdef USE_wxRANGE wxArrayRangeDouble wxBlockDoubleSelection::GetBlockCol(wxDouble col) const { - wxArrayRangeDouble ranges; - int n, count = m_blocks.GetCount(); - for (n=0; n= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2)) - { - wxRangeDouble range(m_blocks[n].m_y1, m_blocks[n].m_y2); - ranges.Add(range); - } + wxArrayRangeDouble ranges; + int n, count = m_blocks.GetCount(); + for (n = 0; n < count; n++) { + if ((col >= m_blocks[n].m_x1) && (col <= m_blocks[n].m_x2)) { + wxRangeDouble range(m_blocks[n].m_y1, m_blocks[n].m_y2); + ranges.Add(range); } - return ranges; + } + return ranges; } wxArrayRangeDouble wxBlockDoubleSelection::GetBlockRow(wxDouble row) const { - wxArrayRangeDouble ranges; - int n, count = m_blocks.GetCount(); - for (n=0; n= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2)) - ranges.Add(wxRangeDouble(m_blocks[n].m_x1, m_blocks[n].m_x2)); + wxArrayRangeDouble ranges; + int n, count = m_blocks.GetCount(); + for (n = 0; n < count; n++) { + if ((row >= m_blocks[n].m_y1) && (row <= m_blocks[n].m_y2)) { + ranges.Add(wxRangeDouble(m_blocks[n].m_x1, m_blocks[n].m_x2)); } - return ranges; + } + return ranges; } #endif // USE_wxRANGE wxBlockDouble wxBlockDoubleSelection::GetBoundingBlock() const { - int n, count = m_blocks.GetCount(); - if (count == 0) return wxEmptyBlockDouble; - wxBlockDouble bound = m_blocks[0]; - for (n=1; n= m_blocks[n].m_x1) && (y >= m_blocks[n].m_y1) && - (x <= m_blocks[n].m_x2) && (y <= m_blocks[n].m_y2) ) - return true; + int n, count = m_blocks.GetCount(); + for (n = 0; n < count; n++) { + if ((x >= m_blocks[n].m_x1) && (y >= m_blocks[n].m_y1) && (x <= m_blocks[n].m_x2) && + (y <= m_blocks[n].m_y2)) { + return true; } - return wxNOT_FOUND; + } + return wxNOT_FOUND; } -int wxBlockDoubleSelection::Index( const wxBlockDouble &b ) const +int wxBlockDoubleSelection::Index(const wxBlockDouble &b) const { - int n, count = m_blocks.GetCount(); - for (n=0; n 0) ? n - 1 : -1; - - if (!top.IsEmpty()) m_blocks.Add(top); - if (!bottom.IsEmpty()) m_blocks.Add(bottom); - if (!left.IsEmpty()) m_blocks.Add(left); - if (!right.IsEmpty()) m_blocks.Add(right); - } + // wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") ); + + bool done = false; + + wxBlockDouble top, bottom, left, right; + for (int n = 0; n < int(m_blocks.GetCount()); n++) { + if (m_blocks[n].Delete(block, top, bottom, left, right)) { + done = true; + m_blocks.RemoveAt(n); + n = (n > 0) ? n - 1 : -1; + + if (!top.IsEmpty()) { + m_blocks.Add(top); + } + if (!bottom.IsEmpty()) { + m_blocks.Add(bottom); + } + if (!left.IsEmpty()) { + m_blocks.Add(left); + } + if (!right.IsEmpty()) { + m_blocks.Add(right); + } } + } - if (combineNow) - Minimize(); + if (combineNow) { + Minimize(); + } - return done; + return done; } -bool wxBlockDoubleSelection::SelectBlock( const wxBlockDouble &block, bool combineNow) +bool wxBlockDoubleSelection::SelectBlock(const wxBlockDouble &block, bool combineNow) { - // It's valid to select a block with a width and height 0 since that means that point - //wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") ); - - wxArrayBlockDouble extra; - extra.Add(block); - wxBlockDouble top, bottom, left, right; - - for (int n=0; n 0) - { - done = m_blocks[n].Combine(extra[k], top, bottom, left, right); - if (done) - { - extra.RemoveAt(k); - k--; - } - } - else - { - done = extra[k].Combine(m_blocks[n], top, bottom, left, right); - if (done) - { - m_blocks.RemoveAt(n); - n = -1; - } - } - } - - if (done) - { - if (!top.IsEmpty()) extra.Add(top); - if (!bottom.IsEmpty()) extra.Add(bottom); - if (!left.IsEmpty()) extra.Add(left); - if (!right.IsEmpty()) extra.Add(right); - //DoMinimize( extra ); - if (n == -1) - break; - } + // It's valid to select a block with a width and height 0 since that means that point + // wxCHECK_MSG(!block.IsEmpty(), false, wxT("Invalid block") ); + + wxArrayBlockDouble extra; + extra.Add(block); + wxBlockDouble top, bottom, left, right; + + for (int n = 0; n < int(m_blocks.GetCount()); n++) { + for (int k = 0; k < int(extra.GetCount()); k++) { + bool done = false; + + // Doubles are different than ints - roundoff error problems + // always use the bigger block to soak up the smaller blocks + // this reduces problems with tiny roundoff error produced blocks + if (m_blocks[n].Intersects(extra[k])) { + if (m_blocks[n].Contains(extra[k])) { + extra.RemoveAt(k); + k--; + continue; } - } + else if (extra[k].Contains(m_blocks[n])) { + m_blocks.RemoveAt(n); + n = -1; + break; + } + else if (m_blocks[n].IsLarger(extra[k]) > 0) { + done = m_blocks[n].Combine(extra[k], top, bottom, left, right); + if (done) { + extra.RemoveAt(k); + k--; + } + } + else { + done = extra[k].Combine(m_blocks[n], top, bottom, left, right); + if (done) { + m_blocks.RemoveAt(n); + n = -1; + } + } + } - if (extra.GetCount() > 0u) - { - WX_APPEND_ARRAY(m_blocks, extra); - if (combineNow) - Minimize(); + if (done) { + if (!top.IsEmpty()) { + extra.Add(top); + } + if (!bottom.IsEmpty()) { + extra.Add(bottom); + } + if (!left.IsEmpty()) { + extra.Add(left); + } + if (!right.IsEmpty()) { + extra.Add(right); + } + // DoMinimize( extra ); + if (n == -1) { + break; + } + } + } + } - return true; + if (extra.GetCount() > 0u) { + WX_APPEND_ARRAY(m_blocks, extra); + if (combineNow) { + Minimize(); } - return false; + return true; + } + + return false; } bool wxBlockDoubleSelection::Minimize() { - bool ret = DoMinimize(m_blocks); - Sort(m_sort); - return ret; + bool ret = DoMinimize(m_blocks); + Sort(m_sort); + return ret; } bool wxBlockDoubleSelection::DoMinimize(wxArrayBlockDouble &blocks) { - int n; - for (n=0; n<1000; n++) // should probably just take < 10 at most - { - if (!DoDoMinimize(blocks)) break; + int n; + for (n = 0; n < 1000; n++) // should probably just take < 10 at most + { + if (!DoDoMinimize(blocks)) { + break; } + } #ifdef CHECK_BLOCK_OVERLAP - for (size_t a=0; a= int(m_blocks.GetCount()))) - return false; - - // first time here - if (m_block_index < 0) - { - m_block_index = 0; - pt = m_pt = m_blocks[m_block_index].GetLeftTop(); - return true; - } + wxCHECK_MSG(m_type == wxBISI_POINT, false, wxT("wrong selection type")); + if ((m_blocks.GetCount() < 1u) || (m_block_index >= int(m_blocks.GetCount()))) { + return false; + } - // at end of block swap to new one - if (m_pt == m_blocks[m_block_index].GetRightBottom()) - { - ++m_block_index; - if (int(m_blocks.GetCount()) > m_block_index) - { - pt = m_pt = m_blocks[m_block_index].GetLeftTop(); - return true; - } - else // past end nothing more to check - return false; + // first time here + if (m_block_index < 0) { + m_block_index = 0; + pt = m_pt = m_blocks[m_block_index].GetLeftTop(); + return true; + } + + // at end of block swap to new one + if (m_pt == m_blocks[m_block_index].GetRightBottom()) { + ++m_block_index; + if (int(m_blocks.GetCount()) > m_block_index) { + pt = m_pt = m_blocks[m_block_index].GetLeftTop(); + return true; } - // at end of col, down to next row - if (m_pt.m_x == m_blocks[m_block_index].GetRight()) - { - m_pt.m_x = m_blocks[m_block_index].m_x1; - m_pt.m_y++; - - pt = m_pt; - return true; + else { // past end nothing more to check + return false; } + } + // at end of col, down to next row + if (m_pt.m_x == m_blocks[m_block_index].GetRight()) { + m_pt.m_x = m_blocks[m_block_index].m_x1; + m_pt.m_y++; - // increment the col - m_pt.m_x++; pt = m_pt; - return true; + } + + // increment the col + m_pt.m_x++; + pt = m_pt; + + return true; } bool wxBlockIntSelectionIterator::IsInSelection(const wxPoint2DInt &pt) const { - int n, count = m_blocks.GetCount(); - for (n=0; nGetBackgroundColour()); + m_bmpCombo = owner; + m_last_selection = -1; + SetBackgroundColour(m_bmpCombo->GetBackgroundColour()); } -void wxBitmapComboPopupChild::OnPaint( wxPaintEvent &WXUNUSED(event) ) +void wxBitmapComboPopupChild::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc(this); - PrepareDC(dc); - //dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID)); - //dc.Clear(); - - dc.SetFont(m_bmpCombo->GetFont()); - - int y = 0, dy = m_bmpCombo->GetItemSize().y; - wxPoint origin = dc.GetDeviceOrigin(); - wxSize clientSize = GetClientSize(); - - for (int n=0; nGetCount(); n++) - { - if (y + dy > -origin.y) - { - dc.SetDeviceOrigin(origin.x, origin.y + y + 1); - m_bmpCombo->DrawItem(dc, n); - } - - y += dy; - if (y > -origin.y + clientSize.y) - break; + wxPaintDC dc(this); + PrepareDC(dc); + // dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID)); + // dc.Clear(); + + dc.SetFont(m_bmpCombo->GetFont()); + + int y = 0, dy = m_bmpCombo->GetItemSize().y; + wxPoint origin = dc.GetDeviceOrigin(); + wxSize clientSize = GetClientSize(); + + for (int n = 0; n < m_bmpCombo->GetCount(); n++) { + if (y + dy > -origin.y) { + dc.SetDeviceOrigin(origin.x, origin.y + y + 1); + m_bmpCombo->DrawItem(dc, n); } - dc.SetDeviceOrigin(0, 0); - PrepareDC(dc); // reset back + y += dy; + if (y > -origin.y + clientSize.y) { + break; + } + } - if (m_bmpCombo->GetSelection() >= 0) - { - if (m_last_selection < 0) - m_last_selection = m_bmpCombo->GetSelection(); + dc.SetDeviceOrigin(0, 0); + PrepareDC(dc); // reset back - DrawSelection(m_last_selection, dc); + if (m_bmpCombo->GetSelection() >= 0) { + if (m_last_selection < 0) { + m_last_selection = m_bmpCombo->GetSelection(); } + + DrawSelection(m_last_selection, dc); + } } -void wxBitmapComboPopupChild::OnMouse( wxMouseEvent &event ) +void wxBitmapComboPopupChild::OnMouse(wxMouseEvent &event) { - wxPoint mouse = event.GetPosition(); - CalcUnscrolledPosition(mouse.x, mouse.y, &mouse.x, &mouse.y); - - //wxPrintf(wxT("bmpcombo mouse %d %d\n"), mouse.x, mouse.y); fflush(stdout); + wxPoint mouse = event.GetPosition(); + CalcUnscrolledPosition(mouse.x, mouse.y, &mouse.x, &mouse.y); - // Get selection from mouse pos, force valid - int sel = m_bmpCombo->GetItemSize().y != 0 ? mouse.y/m_bmpCombo->GetItemSize().y : -1; - if (sel < 0) - sel = 0; - else if (sel >= m_bmpCombo->GetCount()) - sel = m_bmpCombo->GetCount()-1; + // wxPrintf(wxT("bmpcombo mouse %d %d\n"), mouse.x, mouse.y); fflush(stdout); - if (event.LeftDown()) - { - // quickly show user what they selected before hiding it - if (sel != m_last_selection) - { - wxClientDC dc(this); - PrepareDC(dc); - if (m_last_selection >= 0) - DrawSelection(m_last_selection, dc); - if (sel >= 0) - DrawSelection(sel, dc); + // Get selection from mouse pos, force valid + int sel = m_bmpCombo->GetItemSize().y != 0 ? mouse.y / m_bmpCombo->GetItemSize().y : -1; + if (sel < 0) { + sel = 0; + } + else if (sel >= m_bmpCombo->GetCount()) { + sel = m_bmpCombo->GetCount() - 1; + } - m_last_selection = sel; - } + if (event.LeftDown()) { + // quickly show user what they selected before hiding it + if (sel != m_last_selection) { + wxClientDC dc(this); + PrepareDC(dc); + if (m_last_selection >= 0) { + DrawSelection(m_last_selection, dc); + } + if (sel >= 0) { + DrawSelection(sel, dc); + } - m_bmpCombo->SetSelection(sel, true); - m_bmpCombo->HidePopup(); - return; + m_last_selection = sel; } -} -void wxBitmapComboPopupChild::OnKeyDown( wxKeyEvent &event ) -{ - int sel = m_last_selection; - - switch (event.GetKeyCode()) - { - case WXK_ESCAPE : - { - m_bmpCombo->HidePopup(); - return; - } - case WXK_RETURN : - { - m_bmpCombo->SetSelection(sel, true); - m_bmpCombo->HidePopup(); - return; - } - case WXK_UP : sel--; break; - case WXK_DOWN : sel++; break; - default : event.Skip(true); return; + m_bmpCombo->SetSelection(sel, true); + m_bmpCombo->HidePopup(); + return; + } +} + +void wxBitmapComboPopupChild::OnKeyDown(wxKeyEvent &event) +{ + int sel = m_last_selection; + + switch (event.GetKeyCode()) { + case WXK_ESCAPE: { + m_bmpCombo->HidePopup(); + return; + } + case WXK_RETURN: { + m_bmpCombo->SetSelection(sel, true); + m_bmpCombo->HidePopup(); + return; + } + case WXK_UP: + sel--; + break; + case WXK_DOWN: + sel++; + break; + default: + event.Skip(true); + return; + } + + if (sel < 0) { + sel = 0; + } + if (sel >= m_bmpCombo->GetCount()) { + sel = m_bmpCombo->GetCount() - 1; + } + + if (sel != m_last_selection) { + wxClientDC dc(this); + PrepareDC(dc); + if (m_last_selection >= 0) { + DrawSelection(m_last_selection, dc); } - if (sel < 0) - sel = 0; - if (sel >= m_bmpCombo->GetCount()) - sel = m_bmpCombo->GetCount()-1; - - if (sel != m_last_selection) - { - wxClientDC dc(this); - PrepareDC(dc); - if (m_last_selection>=0) - DrawSelection(m_last_selection, dc); - - if (sel>=0) - DrawSelection(sel, dc); - - m_last_selection = sel; + if (sel >= 0) { + DrawSelection(sel, dc); } + + m_last_selection = sel; + } } -void wxBitmapComboPopupChild::DrawSelection( int n, wxDC& dc ) +void wxBitmapComboPopupChild::DrawSelection(int n, wxDC &dc) { - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.SetPen(*wxBLACK_PEN); - dc.SetLogicalFunction(wxINVERT); - int height = m_bmpCombo->GetItemSize().y; - dc.DrawRectangle(0, wxMax(0,height*n-1), GetClientSize().x, height+2); - dc.SetLogicalFunction(wxCOPY); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.SetPen(*wxBLACK_PEN); + dc.SetLogicalFunction(wxINVERT); + int height = m_bmpCombo->GetItemSize().y; + dc.DrawRectangle(0, wxMax(0, height * n - 1), GetClientSize().x, height + 2); + dc.SetLogicalFunction(wxCOPY); } // ========================================================================== // wxBitmapComboLabel - the main "window" to the left of the dropdown button // ========================================================================== -IMPLEMENT_DYNAMIC_CLASS( wxBitmapComboLabel, wxWindow ) +IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboLabel, wxWindow) BEGIN_EVENT_TABLE(wxBitmapComboLabel, wxWindow) - EVT_PAINT( wxBitmapComboLabel::OnPaint ) - EVT_CHAR( wxBitmapComboLabel::OnChar ) +EVT_PAINT(wxBitmapComboLabel::OnPaint) +EVT_CHAR(wxBitmapComboLabel::OnChar) END_EVENT_TABLE() -void wxBitmapComboLabel::OnChar( wxKeyEvent &event ) +void wxBitmapComboLabel::OnChar(wxKeyEvent &event) { - switch (event.GetKeyCode()) - { - case WXK_UP : m_bmpCombo->SetNextSelection(false, true); break; - case WXK_DOWN : m_bmpCombo->SetNextSelection(true, true); break; - default : break; - } + switch (event.GetKeyCode()) { + case WXK_UP: + m_bmpCombo->SetNextSelection(false, true); + break; + case WXK_DOWN: + m_bmpCombo->SetNextSelection(true, true); + break; + default: + break; + } } -void wxBitmapComboLabel::OnPaint( wxPaintEvent &WXUNUSED(event) ) +void wxBitmapComboLabel::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc(this); - dc.SetFont(m_bmpCombo->GetFont()); - //dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID)); - //dc.Clear(); - dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID)); - dc.SetPen(*wxTRANSPARENT_PEN); - dc.DrawRectangle(wxRect(wxPoint(0,0), GetClientSize())); + wxPaintDC dc(this); + dc.SetFont(m_bmpCombo->GetFont()); + // dc.SetBackground(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID)); + // dc.Clear(); + dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID)); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(wxRect(wxPoint(0, 0), GetClientSize())); - const int sel = m_bmpCombo->GetSelection(); - if ((sel >= 0) && (sel < m_bmpCombo->GetCount())) - m_bmpCombo->DrawItem(dc, sel); + const int sel = m_bmpCombo->GetSelection(); + if ((sel >= 0) && (sel < m_bmpCombo->GetCount())) { + m_bmpCombo->DrawItem(dc, sel); + } } // ============================================================================ // wxBitmapComboBox // ============================================================================ -IMPLEMENT_DYNAMIC_CLASS( wxBitmapComboBox, DropDownBase ) +IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboBox, DropDownBase) -BEGIN_EVENT_TABLE(wxBitmapComboBox,DropDownBase) - EVT_SIZE( wxBitmapComboBox::OnSize ) +BEGIN_EVENT_TABLE(wxBitmapComboBox, DropDownBase) +EVT_SIZE(wxBitmapComboBox::OnSize) END_EVENT_TABLE() wxBitmapComboBox::~wxBitmapComboBox() { - while (m_bitmaps.GetCount() > 0u) - { - wxBitmap *bmp = (wxBitmap*)m_bitmaps.Item(0); - m_bitmaps.RemoveAt(0); - delete bmp; - } + while (m_bitmaps.GetCount() > 0u) { + wxBitmap *bmp = (wxBitmap *)m_bitmaps.Item(0); + m_bitmaps.RemoveAt(0); + delete bmp; + } } void wxBitmapComboBox::Init() { - m_labelWin = NULL; - m_frozen = true; - m_selection = 0; - m_win_border = 0; - m_label_style = wxBMPCOMBO_LEFT; + m_labelWin = NULL; + m_frozen = true; + m_selection = 0; + m_win_border = 0; + m_label_style = wxBMPCOMBO_LEFT; } -bool wxBitmapComboBox::Create( wxWindow* parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - long style, const wxValidator& val, - const wxString& name) +bool wxBitmapComboBox::Create(wxWindow *parent, wxWindowID id, const wxPoint &pos, + const wxSize &size, long style, const wxValidator &val, + const wxString &name) { - if (!DropDownBase::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN,val,name)) - return false; + if (!DropDownBase::Create(parent, id, pos, size, wxNO_BORDER | wxCLIP_CHILDREN, val, name)) { + return false; + } - m_labelWin = new wxBitmapComboLabel(this); - m_win_border = m_labelWin->GetSize().x - m_labelWin->GetClientSize().x; + m_labelWin = new wxBitmapComboLabel(this); + m_win_border = m_labelWin->GetSize().x - m_labelWin->GetClientSize().x; - SetBackgroundColour(*wxWHITE); + SetBackgroundColour(*wxWHITE); - m_frozen = false; - CalcLayout(); + m_frozen = false; + CalcLayout(); - wxSize bestSize = DoGetBestSize(); - SetSize( wxSize(size.x < 0 ? bestSize.x : size.x, - size.y < 0 ? bestSize.y : size.y) ); + wxSize bestSize = DoGetBestSize(); + SetSize(wxSize(size.x < 0 ? bestSize.x : size.x, size.y < 0 ? bestSize.y : size.y)); - return SetButtonStyle(style); + return SetButtonStyle(style); } -#define BMPCOMBO_LABEL_MASK (wxBMPCOMBO_LEFT|wxBMPCOMBO_RIGHT) +#define BMPCOMBO_LABEL_MASK (wxBMPCOMBO_LEFT | wxBMPCOMBO_RIGHT) bool wxBitmapComboBox::SetButtonStyle(long style) { - style &= BMPCOMBO_LABEL_MASK; // strip off extras + style &= BMPCOMBO_LABEL_MASK; // strip off extras - int n_styles = 0; - if (style & wxBMPCOMBO_LEFT) n_styles++; - if (style & wxBMPCOMBO_RIGHT) n_styles++; - wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxBitmapComboBox label position allowed")); - if (n_styles < 1) style |= (m_label_style & BMPCOMBO_LABEL_MASK); + int n_styles = 0; + if (style & wxBMPCOMBO_LEFT) { + n_styles++; + } + if (style & wxBMPCOMBO_RIGHT) { + n_styles++; + } + wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxBitmapComboBox label position allowed")); + if (n_styles < 1) { + style |= (m_label_style & BMPCOMBO_LABEL_MASK); + } - m_label_style = style; + m_label_style = style; - m_labelWin->Refresh(true); + m_labelWin->Refresh(true); - return true; + return true; } -void wxBitmapComboBox::OnSize( wxSizeEvent& event ) +void wxBitmapComboBox::OnSize(wxSizeEvent &event) { - event.Skip(); + event.Skip(); - if (!m_labelWin || !m_dropdownButton) return; + if (!m_labelWin || !m_dropdownButton) { + return; + } - wxSize size = GetClientSize(); - //wxPrintf(wxT("ComboOnSize %d %d\n"), size.x, size.y); - int width = size.x - ((wxWindow*)m_dropdownButton)->GetSize().x; - m_labelWin->SetSize(0, 0, width, size.y); + wxSize size = GetClientSize(); + // wxPrintf(wxT("ComboOnSize %d %d\n"), size.x, size.y); + int width = size.x - ((wxWindow *)m_dropdownButton)->GetSize().x; + m_labelWin->SetSize(0, 0, width, size.y); } void wxBitmapComboBox::DoSetSize(int x, int y, int width, int height, int sizeFlags) { -/* - wxSize curSize( GetSize() ); + /* + wxSize curSize( GetSize() ); - if (width == -1) - width = curSize.GetWidth(); - if (height == -1) - height = curSize.GetHeight(); -*/ - DropDownBase::DoSetSize(x, y, width, height, sizeFlags); -/* - width = width - ((wxWindow*)m_dropdownButton)->GetSize().x; - m_labelWin->SetSize(0, 0, width, height); -*/ + if (width == -1) + width = curSize.GetWidth(); + if (height == -1) + height = curSize.GetHeight(); + */ + DropDownBase::DoSetSize(x, y, width, height, sizeFlags); + /* + width = width - ((wxWindow*)m_dropdownButton)->GetSize().x; + m_labelWin->SetSize(0, 0, width, height); + */ } wxSize wxBitmapComboBox::DoGetBestSize() const { - if (GetCount() == 0) return DropDownBase::DoGetBestSize(); + if (GetCount() == 0) { + return DropDownBase::DoGetBestSize(); + } - wxSize size(0,0); - size.x = m_labelSize.x + m_bitmapSize.x + (m_labelSize.x != 0 ? BORDER*2 : 0); - size.y = wxMax(m_labelSize.y, m_bitmapSize.y) + m_win_border; + wxSize size(0, 0); + size.x = m_labelSize.x + m_bitmapSize.x + (m_labelSize.x != 0 ? BORDER * 2 : 0); + size.y = wxMax(m_labelSize.y, m_bitmapSize.y) + m_win_border; - size.x += m_win_border + DROPDOWN_DROP_WIDTH; - if (size.y < DROPDOWN_DROP_HEIGHT) size.y = DROPDOWN_DROP_HEIGHT; + size.x += m_win_border + DROPDOWN_DROP_WIDTH; + if (size.y < DROPDOWN_DROP_HEIGHT) { + size.y = DROPDOWN_DROP_HEIGHT; + } - return size; + return size; } int wxBitmapComboBox::DoGetBestDropHeight(int max_height) { - int count = GetCount(); - if (count < 1) return -1; + int count = GetCount(); + if (count < 1) { + return -1; + } - // add one for drawing selection rect - return wxMin(m_itemSize.y*count + m_win_border+1, max_height); + // add one for drawing selection rect + return wxMin(m_itemSize.y * count + m_win_border + 1, max_height); } bool wxBitmapComboBox::DoShowPopup() { - if (m_popupWin) - { - wxBitmapComboPopupChild *popChild = new wxBitmapComboPopupChild(m_popupWin, this); - m_popupWin->SetChild(popChild); - - if (popChild) - { - popChild->m_last_selection = GetSelection(); - int scr_pos = m_selection > 0 ? m_selection*m_itemSize.y-1 : 0; - int count = GetCount(); - popChild->SetScrollbars(1, 1, m_itemSize.x, m_itemSize.y*count+1, 0, scr_pos); - } + if (m_popupWin) { + wxBitmapComboPopupChild *popChild = new wxBitmapComboPopupChild(m_popupWin, this); + m_popupWin->SetChild(popChild); + + if (popChild) { + popChild->m_last_selection = GetSelection(); + int scr_pos = m_selection > 0 ? m_selection * m_itemSize.y - 1 : 0; + int count = GetCount(); + popChild->SetScrollbars(1, 1, m_itemSize.x, m_itemSize.y * count + 1, 0, scr_pos); } + } - return DropDownBase::DoShowPopup(); + return DropDownBase::DoShowPopup(); } void wxBitmapComboBox::HidePopup() { - DropDownBase::HidePopup(); + DropDownBase::HidePopup(); - // FIXME - MSW destroys the sunken border of labelWin when in toolbar - // a refresh doesn't help + // FIXME - MSW destroys the sunken border of labelWin when in toolbar + // a refresh doesn't help } void wxBitmapComboBox::Thaw() { - m_frozen = false; - CalcLayout(); - if (m_labelWin) - m_labelWin->Refresh(); + m_frozen = false; + CalcLayout(); + if (m_labelWin) { + m_labelWin->Refresh(); + } } void wxBitmapComboBox::CalcLayout() { - if (m_frozen) return; - - int height = 0, width = 0; - m_itemSize = m_labelSize = m_bitmapSize = wxSize(0,0); - int count = GetCount(); - wxBitmap bmp; - - for (int n=0; n m_bitmapSize.x) m_bitmapSize.x = width; - if (height > m_bitmapSize.y) m_bitmapSize.y = height; - } - if (!m_labels[n].IsEmpty()) - { - GetTextExtent(m_labels[n], &width, &height); - - if (width > m_labelSize.x) m_labelSize.x = width; - if (height > m_labelSize.y) m_labelSize.y = height; - } + if (m_frozen) { + return; + } + + int height = 0, width = 0; + m_itemSize = m_labelSize = m_bitmapSize = wxSize(0, 0); + int count = GetCount(); + wxBitmap bmp; + + for (int n = 0; n < count; n++) { + bmp = GetBitmap(n); + if (bmp.Ok()) { + width = bmp.GetWidth(); + height = bmp.GetHeight(); + + if (width > m_bitmapSize.x) { + m_bitmapSize.x = width; + } + if (height > m_bitmapSize.y) { + m_bitmapSize.y = height; + } } - - m_itemSize.x = m_labelSize.x + m_bitmapSize.x + m_win_border; - m_itemSize.y = wxMax(m_labelSize.y, m_bitmapSize.y) + m_win_border; -} - -void wxBitmapComboBox::CalcLabelBitmapPos(int n, const wxSize &area, wxPoint &labelPos, wxPoint &bitmapPos) const -{ - labelPos = bitmapPos = wxPoint(0,0); - - int bw = 0, bh = 0; - int lw = 0, lh = 0; - - if (GetBitmap(n).Ok()) - { - bw = GetBitmap(n).GetWidth(); - bh = GetBitmap(n).GetHeight(); - } - if (!m_labels[n].IsEmpty()) - { - GetTextExtent(m_labels[n], &lw, &lh); - } - - if (m_bitmapSize.x == 0) // There aren't any bitmaps, left align label - { - labelPos = wxPoint(BORDER, (area.y-lh)/2); - } - else if (m_labelSize.x == 0) // There aren't any labels, center bitmap - { - bitmapPos = wxPoint((area.x-bw)/2, (area.y-bh)/2); - } - else if ((m_label_style & wxBMPCOMBO_RIGHT) != 0) - { - labelPos = wxPoint(m_bitmapSize.x+BORDER, (area.y - lh)/2); - bitmapPos = wxPoint((m_bitmapSize.x-bw)/2, (area.y - bh)/2); - } - else // if ((m_label_style & wxBMPCOMBO_LEFT) != 0) - { - labelPos = wxPoint(BORDER, (area.y - lh)/2); - bitmapPos = wxPoint(BORDER*2 + m_labelSize.x + (area.x - BORDER*2 - m_labelSize.x - bw)/2, (area.y - bh)/2); + if (!m_labels[n].IsEmpty()) { + GetTextExtent(m_labels[n], &width, &height); + + if (width > m_labelSize.x) { + m_labelSize.x = width; + } + if (height > m_labelSize.y) { + m_labelSize.y = height; + } } + } + + m_itemSize.x = m_labelSize.x + m_bitmapSize.x + m_win_border; + m_itemSize.y = wxMax(m_labelSize.y, m_bitmapSize.y) + m_win_border; +} + +void wxBitmapComboBox::CalcLabelBitmapPos(int n, const wxSize &area, wxPoint &labelPos, + wxPoint &bitmapPos) const +{ + labelPos = bitmapPos = wxPoint(0, 0); + + int bw = 0, bh = 0; + int lw = 0, lh = 0; + + if (GetBitmap(n).Ok()) { + bw = GetBitmap(n).GetWidth(); + bh = GetBitmap(n).GetHeight(); + } + if (!m_labels[n].IsEmpty()) { + GetTextExtent(m_labels[n], &lw, &lh); + } + + if (m_bitmapSize.x == 0) // There aren't any bitmaps, left align label + { + labelPos = wxPoint(BORDER, (area.y - lh) / 2); + } + else if (m_labelSize.x == 0) // There aren't any labels, center bitmap + { + bitmapPos = wxPoint((area.x - bw) / 2, (area.y - bh) / 2); + } + else if ((m_label_style & wxBMPCOMBO_RIGHT) != 0) { + labelPos = wxPoint(m_bitmapSize.x + BORDER, (area.y - lh) / 2); + bitmapPos = wxPoint((m_bitmapSize.x - bw) / 2, (area.y - bh) / 2); + } + else // if ((m_label_style & wxBMPCOMBO_LEFT) != 0) + { + labelPos = wxPoint(BORDER, (area.y - lh) / 2); + bitmapPos = + wxPoint(BORDER * 2 + m_labelSize.x + (area.x - BORDER * 2 - m_labelSize.x - bw) / 2, + (area.y - bh) / 2); + } } void wxBitmapComboBox::DrawItem(wxDC &dc, int n) const { - wxSize itemSize(GetItemSize()); //((wxWindow*)GetLabelWindow())->GetClientSize().x, dy); + wxSize itemSize(GetItemSize()); //((wxWindow*)GetLabelWindow())->GetClientSize().x, dy); - wxPoint labelPos, bitmapPos; - CalcLabelBitmapPos(n, itemSize, labelPos, bitmapPos); + wxPoint labelPos, bitmapPos; + CalcLabelBitmapPos(n, itemSize, labelPos, bitmapPos); - if (GetBitmap(n).Ok()) - dc.DrawBitmap(GetBitmap(n), bitmapPos.x, bitmapPos.y, true); - if (!GetLabel(n).IsEmpty()) - dc.DrawText(GetLabel(n), labelPos.x, labelPos.y); + if (GetBitmap(n).Ok()) { + dc.DrawBitmap(GetBitmap(n), bitmapPos.x, bitmapPos.y, true); + } + if (!GetLabel(n).IsEmpty()) { + dc.DrawText(GetLabel(n), labelPos.x, labelPos.y); + } } void wxBitmapComboBox::Append(const wxString &label, const wxBitmap &bitmap, int count) { - for (int n=0; n=0) && (n= 0) && (n < GetCount()), wxT("invalid index")); - m_labels.Insert(label, n); - m_bitmaps.Insert(new wxBitmap(bitmap), n); - CalcLayout(); + m_labels.Insert(label, n); + m_bitmaps.Insert(new wxBitmap(bitmap), n); + CalcLayout(); } void wxBitmapComboBox::Clear() { - m_labels.Clear(); - while (m_bitmaps.GetCount() > 0u) - { - wxBitmap *bmp = (wxBitmap*)m_bitmaps.Item(0); - m_bitmaps.RemoveAt(0); - delete bmp; - } - CalcLayout(); + m_labels.Clear(); + while (m_bitmaps.GetCount() > 0u) { + wxBitmap *bmp = (wxBitmap *)m_bitmaps.Item(0); + m_bitmaps.RemoveAt(0); + delete bmp; + } + CalcLayout(); } -void wxBitmapComboBox::Delete( int n, int count ) +void wxBitmapComboBox::Delete(int n, int count) { - wxCHECK_RET((n>=0) && (count>0) && (n+count<=GetCount()), wxT("invalid index")); + wxCHECK_RET((n >= 0) && (count > 0) && (n + count <= GetCount()), wxT("invalid index")); - for (int i=0; i=0) && (n < GetCount()), wxEmptyString, wxT("invalid index")); - return m_labels[n]; + wxCHECK_MSG((n >= 0) && (n < GetCount()), wxEmptyString, wxT("invalid index")); + return m_labels[n]; } -wxBitmap wxBitmapComboBox::GetBitmap( int n ) const +wxBitmap wxBitmapComboBox::GetBitmap(int n) const { - wxCHECK_MSG((n>=0) && (n < GetCount()), wxNullBitmap, wxT("invalid index")); - return *(wxBitmap *)m_bitmaps.Item(n); + wxCHECK_MSG((n >= 0) && (n < GetCount()), wxNullBitmap, wxT("invalid index")); + return *(wxBitmap *)m_bitmaps.Item(n); } -void wxBitmapComboBox::SetSelection( int n, bool send_event ) +void wxBitmapComboBox::SetSelection(int n, bool send_event) { - wxCHECK_RET((n>=0) && (n < GetCount()), wxT("invalid index")); - m_selection = n; - m_labelWin->Refresh(true); + wxCHECK_RET((n >= 0) && (n < GetCount()), wxT("invalid index")); + m_selection = n; + m_labelWin->Refresh(true); - if (send_event) - { - wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, GetId() ); - event.SetInt( m_selection ); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent( event ); - } + if (send_event) { + wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, GetId()); + event.SetInt(m_selection); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); + } } void wxBitmapComboBox::SetNextSelection(bool foward, bool send_event) { - const int count = GetCount(); - if (count == 0) return; + const int count = GetCount(); + if (count == 0) { + return; + } - int sel = m_selection; + int sel = m_selection; - if (foward) - { - if ((sel < 0) || (sel == count - 1)) - sel = 0; - else - sel++; + if (foward) { + if ((sel < 0) || (sel == count - 1)) { + sel = 0; + } + else { + sel++; } - else - { - if (sel <= 0) - sel = count - 1; - else - sel--; + } + else { + if (sel <= 0) { + sel = count - 1; } + else { + sel--; + } + } - SetSelection(sel, send_event); + SetSelection(sel, send_event); } void wxBitmapComboBox::SetLabel(int n, const wxString &label) { - wxCHECK_RET( (n>=0) && (n < GetCount()), wxT("invalid index")); - m_labels[n] = label; - CalcLayout(); + wxCHECK_RET((n >= 0) && (n < GetCount()), wxT("invalid index")); + m_labels[n] = label; + CalcLayout(); - if (n == m_selection) m_labelWin->Refresh(false); + if (n == m_selection) { + m_labelWin->Refresh(false); + } } void wxBitmapComboBox::SetBitmap(int n, const wxBitmap &bitmap) { - wxCHECK_RET((n>=0) && (n < GetCount()), wxT("invalid index")); - *((wxBitmap*)m_bitmaps.Item(n)) = bitmap; - CalcLayout(); + wxCHECK_RET((n >= 0) && (n < GetCount()), wxT("invalid index")); + *((wxBitmap *)m_bitmaps.Item(n)) = bitmap; + CalcLayout(); - if (n == m_selection) m_labelWin->Refresh(false); + if (n == m_selection) { + m_labelWin->Refresh(false); + } } bool wxBitmapComboBox::SetBackgroundColour(const wxColour &colour) { - // not a failure for wx 2.5.x since InheritAttributes calls this - // from wxWindow::Create - if (m_labelWin) - { - m_labelWin->SetBackgroundColour(colour); - m_labelWin->Refresh(); - } - return DropDownBase::SetBackgroundColour(colour); + // not a failure for wx 2.5.x since InheritAttributes calls this + // from wxWindow::Create + if (m_labelWin) { + m_labelWin->SetBackgroundColour(colour); + m_labelWin->Refresh(); + } + return DropDownBase::SetBackgroundColour(colour); } diff --git a/src/labenski/src/dropdown.cpp b/src/labenski/src/dropdown.cpp index 13ec09660..5cbf8f7f1 100644 --- a/src/labenski/src/dropdown.cpp +++ b/src/labenski/src/dropdown.cpp @@ -13,12 +13,12 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/control.h" - #include "wx/bitmap.h" +#include "wx/control.h" +#include "wx/bitmap.h" #endif // WX_PRECOMP #include "wx/timer.h" @@ -28,15 +28,10 @@ /* XPM */ static const char *down_arrow_xpm_data[] = { -/* columns rows colors chars-per-pixel */ -"7 4 2 1", -" c None", -"a c Black", -/* pixels */ -"aaaaaaa", -" aaaaa ", -" aaa ", -" a "}; + /* columns rows colors chars-per-pixel */ + "7 4 2 1", " c None", "a c Black", + /* pixels */ + "aaaaaaa", " aaaaa ", " aaa ", " a "}; #define IDD_DROPDOWN_BUTTON 100 @@ -46,368 +41,377 @@ static wxBitmap s_dropdownBitmap; // all buttons share the same bitmap // DropDownPopup // ========================================================================== #define USE_POPUP_TIMER 0 // FIXME after 2.5.4 we don't need either -#define USE_POPUP_IDLE 0 +#define USE_POPUP_IDLE 0 -IMPLEMENT_DYNAMIC_CLASS( DropDownPopup, wxPopupTransientWindow ) +IMPLEMENT_DYNAMIC_CLASS(DropDownPopup, wxPopupTransientWindow) BEGIN_EVENT_TABLE(DropDownPopup, wxPopupTransientWindow) - EVT_KEY_DOWN(DropDownPopup::OnKeyDown) - EVT_MOUSE_EVENTS(DropDownPopup::OnMouse) +EVT_KEY_DOWN(DropDownPopup::OnKeyDown) +EVT_MOUSE_EVENTS(DropDownPopup::OnMouse) #if USE_POPUP_TIMER - EVT_TIMER( wxID_ANY, DropDownPopup::OnTimer ) +EVT_TIMER(wxID_ANY, DropDownPopup::OnTimer) #endif // USE_POPUP_TIMER #if USE_POPUP_IDLE - EVT_IDLE( DropDownPopup::OnIdle ) // use Connect/Disconnect instead -#endif // USE_POPUP_IDLE +EVT_IDLE(DropDownPopup::OnIdle) // use Connect/Disconnect instead +#endif // USE_POPUP_IDLE END_EVENT_TABLE() bool DropDownPopup::Create(DropDownBase *parent, int style) { - m_owner = parent; - return wxPopupTransientWindow::Create(parent, style); + m_owner = parent; + return wxPopupTransientWindow::Create(parent, style); } void DropDownPopup::Init() { - m_owner = NULL; - m_childWin = NULL; - m_timer = NULL; - m_popped_handler = false; + m_owner = NULL; + m_childWin = NULL; + m_timer = NULL; + m_popped_handler = false; } -DropDownPopup::~DropDownPopup() -{ - StopTimer(); -} +DropDownPopup::~DropDownPopup() { StopTimer(); } void DropDownPopup::StartTimer() { #if USE_POPUP_TIMER - if (!m_timer) - m_timer = new wxTimer(this, wxID_ANY); + if (!m_timer) { + m_timer = new wxTimer(this, wxID_ANY); + } - m_timer->Start(200, false); + m_timer->Start(200, false); #endif // USE_POPUP_TIMER } void DropDownPopup::StopTimer() { - if (m_timer) - { - if (m_timer->IsRunning()) - m_timer->Stop(); - delete m_timer; - m_timer = NULL; + if (m_timer) { + if (m_timer->IsRunning()) { + m_timer->Stop(); } + delete m_timer; + m_timer = NULL; + } } -void DropDownPopup::PushPopupHandler(wxWindow* child) +void DropDownPopup::PushPopupHandler(wxWindow *child) { - if (child && m_handlerPopup && m_popped_handler) - { - m_popped_handler = false; - - if (child->GetEventHandler() != (wxEvtHandler*)m_handlerPopup) - child->PushEventHandler((wxEvtHandler*)m_handlerPopup); - if (!child->HasCapture()) - child->CaptureMouse(); + if (child && m_handlerPopup && m_popped_handler) { + m_popped_handler = false; - child->SetFocus(); + if (child->GetEventHandler() != (wxEvtHandler *)m_handlerPopup) { + child->PushEventHandler((wxEvtHandler *)m_handlerPopup); + } + if (!child->HasCapture()) { + child->CaptureMouse(); } + + child->SetFocus(); + } } -void DropDownPopup::PopPopupHandler(wxWindow* child) +void DropDownPopup::PopPopupHandler(wxWindow *child) { - if (child && m_handlerPopup && !m_popped_handler) - { - m_popped_handler = true; - - if (child->GetEventHandler() == (wxEvtHandler*)m_handlerPopup) - child->PopEventHandler(false); - if (child->HasCapture()) - child->ReleaseMouse(); + if (child && m_handlerPopup && !m_popped_handler) { + m_popped_handler = true; - child->SetFocus(); + if (child->GetEventHandler() == (wxEvtHandler *)m_handlerPopup) { + child->PopEventHandler(false); + } + if (child->HasCapture()) { + child->ReleaseMouse(); } + + child->SetFocus(); + } } -void DropDownPopup::OnTimer( wxTimerEvent &WXUNUSED(event) ) +void DropDownPopup::OnTimer(wxTimerEvent &WXUNUSED(event)) { - if (!IsShown()) return; + if (!IsShown()) { + return; + } + + m_mouse = ScreenToClient(wxGetMousePosition()); + + wxWindow *child = GetChild(); + if (!child) { + return; // nothing to do + } + + wxRect clientRect(GetClientRect()); + // wxPrintf(wxT("**DropDownPopup::OnTimer mouse %d %d -- %d %d %d\n"), m_mouse.x, m_mouse.y, + // m_popped_handler, m_child, m_handlerPopup); fflush(stdout); + // pop the event handler if inside the child window or + // restore the event handler if not in the child window +#if wxCHECK_VERSION(2, 7, 0) + if (clientRect.Contains(m_mouse)) +#else + if (clientRect.Inside(m_mouse)) +#endif + PopPopupHandler(child); + else { + PushPopupHandler(child); + } +} +void DropDownPopup::OnIdle(wxIdleEvent &event) +{ + if (IsShown()) { m_mouse = ScreenToClient(wxGetMousePosition()); + wxPrintf(wxT("OnIdle mouse %d %d\n"), m_mouse.x, m_mouse.y); wxWindow *child = GetChild(); - if (!child) return; // nothing to do + if (!child) { + return; // nothing to do + } wxRect clientRect(GetClientRect()); - //wxPrintf(wxT("**DropDownPopup::OnTimer mouse %d %d -- %d %d %d\n"), m_mouse.x, m_mouse.y, m_popped_handler, m_child, m_handlerPopup); fflush(stdout); - // pop the event handler if inside the child window or - // restore the event handler if not in the child window -#if wxCHECK_VERSION(2,7,0) + // wxPrintf(wxT("**DropDownPopup::OnIdle mouse %d %d -- %d %d %d\n"), m_mouse.x, m_mouse.y, + // m_popped_handler, m_child, m_handlerPopup); fflush(stdout); + // pop the event handler if inside the child window or + // restore the event handler if not in the child window +#if wxCHECK_VERSION(2, 7, 0) if (clientRect.Contains(m_mouse)) #else if (clientRect.Inside(m_mouse)) #endif - PopPopupHandler(child); - else - PushPopupHandler(child); -} - -void DropDownPopup::OnIdle( wxIdleEvent& event ) -{ - if (IsShown()) - { - m_mouse = ScreenToClient(wxGetMousePosition()); - wxPrintf(wxT("OnIdle mouse %d %d\n"), m_mouse.x, m_mouse.y); - - wxWindow *child = GetChild(); - if (!child) return; // nothing to do - - wxRect clientRect(GetClientRect()); - //wxPrintf(wxT("**DropDownPopup::OnIdle mouse %d %d -- %d %d %d\n"), m_mouse.x, m_mouse.y, m_popped_handler, m_child, m_handlerPopup); fflush(stdout); - // pop the event handler if inside the child window or - // restore the event handler if not in the child window -#if wxCHECK_VERSION(2,7,0) - if (clientRect.Contains(m_mouse)) -#else - if (clientRect.Inside(m_mouse)) -#endif - PopPopupHandler(child); - else - PushPopupHandler(child); + PopPopupHandler(child); + else { + PushPopupHandler(child); } - event.Skip(); + } + event.Skip(); } -void DropDownPopup::OnMouse( wxMouseEvent& event ) +void DropDownPopup::OnMouse(wxMouseEvent &event) { - m_mouse = event.GetPosition(); - event.Skip(); + m_mouse = event.GetPosition(); + event.Skip(); } -void DropDownPopup::OnKeyDown( wxKeyEvent &event ) +void DropDownPopup::OnKeyDown(wxKeyEvent &event) { - if (GetChild() && GetChild()->ProcessEvent(event)) - event.Skip(false); - else - event.Skip(true); + if (GetChild() && GetChild()->ProcessEvent(event)) { + event.Skip(false); + } + else { + event.Skip(true); + } } -void DropDownPopup::SetChild(wxWindow *win) -{ - m_childWin = win; -} +void DropDownPopup::SetChild(wxWindow *win) { m_childWin = win; } void DropDownPopup::Popup(wxWindow *focus) { - wxPopupTransientWindow::Popup(focus); + wxPopupTransientWindow::Popup(focus); #if USE_POPUP_IDLE - Connect(wxID_ANY, wxEVT_IDLE, - (wxObjectEventFunction)(wxEventFunction)(wxIdleEventFunction) - &DropDownPopup::OnIdle, 0, this); -#endif //USE_POPUP_IDLE + Connect(wxID_ANY, wxEVT_IDLE, + (wxObjectEventFunction)(wxEventFunction)(wxIdleEventFunction)&DropDownPopup::OnIdle, 0, + this); +#endif // USE_POPUP_IDLE #if USE_POPUP_TIMER - // start the timer to track the mouse position - StartTimer(); -#endif //USE_POPUP_TIMER + // start the timer to track the mouse position + StartTimer(); +#endif // USE_POPUP_TIMER } void DropDownPopup::Dismiss() { #if USE_POPUP_IDLE - Disconnect(wxID_ANY, wxEVT_IDLE, - (wxObjectEventFunction)(wxEventFunction)(wxIdleEventFunction) - &DropDownPopup::OnIdle, 0, this); -#endif //USE_POPUP_IDLE + Disconnect(wxID_ANY, wxEVT_IDLE, + (wxObjectEventFunction)(wxEventFunction)(wxIdleEventFunction)&DropDownPopup::OnIdle, + 0, this); +#endif // USE_POPUP_IDLE #if USE_POPUP_TIMER - StopTimer(); -#endif //USE_POPUP_TIMER + StopTimer(); +#endif // USE_POPUP_TIMER - // restore the event handler if necessary for the base class Dismiss - wxWindow *child = GetChild(); - if (child) PushPopupHandler(child); + // restore the event handler if necessary for the base class Dismiss + wxWindow *child = GetChild(); + if (child) { + PushPopupHandler(child); + } - m_popped_handler = false; + m_popped_handler = false; - wxPopupTransientWindow::Dismiss(); + wxPopupTransientWindow::Dismiss(); } -bool DropDownPopup::ProcessLeftDown( wxMouseEvent &event ) +bool DropDownPopup::ProcessLeftDown(wxMouseEvent &event) { - m_mouse = event.GetPosition(); - //wxPrintf(wxT("DropDownPopup::ProcessLeftDown %d %d\n"), m_mouse.x, m_mouse.y); fflush(stdout); - - if (m_popped_handler) return true; // shouldn't ever get here, but just in case - - StopTimer(); - - // don't let the click on the dropdown button actually press it - wxCustomButton *dropBut = m_owner->GetDropDownButton(); - if (dropBut) - { - wxPoint dropMousePt = dropBut->ScreenToClient(ClientToScreen(m_mouse)); - if (dropBut->HitTest(dropMousePt) == wxHT_WINDOW_INSIDE) - { - m_ignore_popup = true; - Dismiss(); - return true; - } + m_mouse = event.GetPosition(); + // wxPrintf(wxT("DropDownPopup::ProcessLeftDown %d %d\n"), m_mouse.x, m_mouse.y); fflush(stdout); + + if (m_popped_handler) { + return true; // shouldn't ever get here, but just in case + } + + StopTimer(); + + // don't let the click on the dropdown button actually press it + wxCustomButton *dropBut = m_owner->GetDropDownButton(); + if (dropBut) { + wxPoint dropMousePt = dropBut->ScreenToClient(ClientToScreen(m_mouse)); + if (dropBut->HitTest(dropMousePt) == wxHT_WINDOW_INSIDE) { + m_ignore_popup = true; + Dismiss(); + return true; } + } -#if wxCHECK_VERSION(2,7,0) - if (GetClientRect().Contains(m_mouse)) +#if wxCHECK_VERSION(2, 7, 0) + if (GetClientRect().Contains(m_mouse)) #else - if (GetClientRect().Inside(m_mouse)) + if (GetClientRect().Inside(m_mouse)) #endif - return false; + return false; - Dismiss(); - return true; + Dismiss(); + return true; } // ============================================================================ // DropDownBase // ============================================================================ -IMPLEMENT_DYNAMIC_CLASS( DropDownBase, wxControl ) +IMPLEMENT_DYNAMIC_CLASS(DropDownBase, wxControl) BEGIN_EVENT_TABLE(DropDownBase, wxControl) - EVT_BUTTON(IDD_DROPDOWN_BUTTON, DropDownBase::OnDropButton) - EVT_SIZE( DropDownBase::OnSize ) +EVT_BUTTON(IDD_DROPDOWN_BUTTON, DropDownBase::OnDropButton) +EVT_SIZE(DropDownBase::OnSize) END_EVENT_TABLE() -DropDownBase::~DropDownBase() -{ -} +DropDownBase::~DropDownBase() {} void DropDownBase::Init() { - m_popupWin = NULL; - m_dropdownButton = NULL; + m_popupWin = NULL; + m_dropdownButton = NULL; } -bool DropDownBase::Create( wxWindow* parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - long style, const wxValidator& val, - const wxString& name) +bool DropDownBase::Create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, + long style, const wxValidator &val, const wxString &name) { - if (!wxControl::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN|style,val,name)) - return false; + if (!wxControl::Create(parent, id, pos, size, wxNO_BORDER | wxCLIP_CHILDREN | style, val, + name)) { + return false; + } - if (!s_dropdownBitmap.Ok()) - s_dropdownBitmap = wxBitmap(down_arrow_xpm_data); + if (!s_dropdownBitmap.Ok()) { + s_dropdownBitmap = wxBitmap(down_arrow_xpm_data); + } - m_dropdownButton = new wxCustomButton(this, IDD_DROPDOWN_BUTTON, - s_dropdownBitmap, - wxDefaultPosition, - wxSize(DROPDOWN_DROP_WIDTH, wxDefaultCoord), - wxCUSTBUT_BUTTON); + m_dropdownButton = + new wxCustomButton(this, IDD_DROPDOWN_BUTTON, s_dropdownBitmap, wxDefaultPosition, + wxSize(DROPDOWN_DROP_WIDTH, wxDefaultCoord), wxCUSTBUT_BUTTON); - return true; + return true; } -void DropDownBase::OnSize( wxSizeEvent& event ) +void DropDownBase::OnSize(wxSizeEvent &event) { - event.Skip(); -/* - if (!m_dropdownButton) return; + event.Skip(); + /* + if (!m_dropdownButton) return; - wxSize size = GetClientSize(); - wxPrintf(wxT("DropDownBase %d %d\n"), size.x, size.y); + wxSize size = GetClientSize(); + wxPrintf(wxT("DropDownBase %d %d\n"), size.x, size.y); - wxSize dropSize = m_dropdownButton->GetSize(); - m_dropdownButton->SetSize(size.x-dropSize.x, 0, dropSize.x, size.y); -*/ + wxSize dropSize = m_dropdownButton->GetSize(); + m_dropdownButton->SetSize(size.x-dropSize.x, 0, dropSize.x, size.y); + */ } void DropDownBase::DoSetSize(int x, int y, int width, int height, int sizeFlags) { - wxSize curSize( GetSize() ); + wxSize curSize(GetSize()); - if (width == -1) - width = curSize.GetWidth(); - if (height == -1) - height = curSize.GetHeight(); + if (width == -1) { + width = curSize.GetWidth(); + } + if (height == -1) { + height = curSize.GetHeight(); + } - wxControl::DoSetSize(x, y, width, height, sizeFlags); + wxControl::DoSetSize(x, y, width, height, sizeFlags); - wxSize dropSize = m_dropdownButton->GetSize(); - m_dropdownButton->SetSize(width-dropSize.x, 0, dropSize.x, height); + wxSize dropSize = m_dropdownButton->GetSize(); + m_dropdownButton->SetSize(width - dropSize.x, 0, dropSize.x, height); } -wxSize DropDownBase::DoGetBestSize() const -{ - return wxSize(95, DROPDOWN_DROP_HEIGHT); -} +wxSize DropDownBase::DoGetBestSize() const { return wxSize(95, DROPDOWN_DROP_HEIGHT); } bool DropDownBase::ShowPopup() { - int x = 0, y = GetSize().y; - ClientToScreen( &x, &y ); + int x = 0, y = GetSize().y; + ClientToScreen(&x, &y); - // control too low, can't show scrollbar, don't bother displaying - wxRect displayRect = wxGetClientDisplayRect(); - if (displayRect.GetBottom() - y < DROPDOWN_DROP_HEIGHT) return false; + // control too low, can't show scrollbar, don't bother displaying + wxRect displayRect = wxGetClientDisplayRect(); + if (displayRect.GetBottom() - y < DROPDOWN_DROP_HEIGHT) { + return false; + } - int width = GetSize().x; - int height = DoGetBestDropHeight(displayRect.GetBottom() - y); - if (height < 1) return false; + int width = GetSize().x; + int height = DoGetBestDropHeight(displayRect.GetBottom() - y); + if (height < 1) { + return false; + } - m_popupWin = new DropDownPopup(this); + m_popupWin = new DropDownPopup(this); - m_popupWin->SetSize(x, y, width, height); - if (m_popupWin->GetChild()) - m_popupWin->GetChild()->SetSize(width, height); + m_popupWin->SetSize(x, y, width, height); + if (m_popupWin->GetChild()) { + m_popupWin->GetChild()->SetSize(width, height); + } - //wxPrintf(wxT("ShowPopup %d %d, %d %d -- %d\n"), width, height, m_popupWin->GetSize().x, m_popupWin->GetSize().y, m_popupWin->GetMinHeight()); + // wxPrintf(wxT("ShowPopup %d %d, %d %d -- %d\n"), width, height, m_popupWin->GetSize().x, + // m_popupWin->GetSize().y, m_popupWin->GetMinHeight()); - return DoShowPopup(); + return DoShowPopup(); } bool DropDownBase::DoShowPopup() { - if (m_popupWin) - { - if (m_popupWin->GetChild()) - m_popupWin->GetChild()->SetSize(m_popupWin->GetClientSize()); - - m_popupWin->Popup(this); - return true; + if (m_popupWin) { + if (m_popupWin->GetChild()) { + m_popupWin->GetChild()->SetSize(m_popupWin->GetClientSize()); } - return false; + m_popupWin->Popup(this); + return true; + } + + return false; } void DropDownBase::HidePopup() { - if (m_popupWin) - { - m_popupWin->Dismiss(); - m_popupWin->Destroy(); - m_popupWin = NULL; - } + if (m_popupWin) { + m_popupWin->Dismiss(); + m_popupWin->Destroy(); + m_popupWin = NULL; + } - m_dropdownButton->Refresh(true); // MSW help in toolbar + m_dropdownButton->Refresh(true); // MSW help in toolbar } -bool DropDownBase::IsPopupShown() -{ - return m_popupWin && m_popupWin->IsShown(); -} +bool DropDownBase::IsPopupShown() { return m_popupWin && m_popupWin->IsShown(); } -void DropDownBase::OnDropButton( wxCommandEvent &WXUNUSED(event)) +void DropDownBase::OnDropButton(wxCommandEvent &WXUNUSED(event)) { - if (m_popupWin && m_popupWin->m_ignore_popup) - { - m_popupWin->m_ignore_popup = false; - return; - } - - if (IsPopupShown()) - HidePopup(); - else - ShowPopup(); + if (m_popupWin && m_popupWin->m_ignore_popup) { + m_popupWin->m_ignore_popup = false; + return; + } + + if (IsPopupShown()) { + HidePopup(); + } + else { + ShowPopup(); + } } diff --git a/src/labenski/src/fourier.c b/src/labenski/src/fourier.c index 445d2d073..97406eb32 100644 --- a/src/labenski/src/fourier.c +++ b/src/labenski/src/fourier.c @@ -36,66 +36,67 @@ #include "wx/plotctrl/fourier.h" -#define BITS_PER_WORD (sizeof(unsigned) * 8) -#define DDC_PI (3.14159265358979323846) +#define BITS_PER_WORD (sizeof(unsigned) * 8) +#define DDC_PI (3.14159265358979323846) /*--- start of file fftmisc.c---*/ // #define IsPowerOfTwo(x) (((x)<2) || ((x)&((x)-1)) ? false : true) // returns 1 if the numver is a power of two else 0 -int IsPowerOfTwo ( unsigned x ) +int IsPowerOfTwo(unsigned x) { - if ( x < 2 ) - return 0; + if (x < 2) { + return 0; + } - if ( x & (x-1) ) // Thanks to 'byang' for this cute trick! - return 0; + if (x & (x - 1)) { // Thanks to 'byang' for this cute trick! + return 0; + } - return 1; + return 1; } // returns the number of bits needed -unsigned NumberOfBitsNeeded ( unsigned PowerOfTwo ) +unsigned NumberOfBitsNeeded(unsigned PowerOfTwo) { - unsigned i; + unsigned i; - for ( i=0; ; i++ ) - { - if ( PowerOfTwo & (1 << i) ) - return i; + for (i = 0;; i++) { + if (PowerOfTwo & (1 << i)) { + return i; } + } - return 0; + return 0; } -unsigned ReverseBits ( unsigned index, unsigned NumBits ) +unsigned ReverseBits(unsigned index, unsigned NumBits) { - unsigned i, rev; + unsigned i, rev; - for ( i=rev=0; i < NumBits; i++ ) - { - rev = (rev << 1) | (index & 1); - index >>= 1; - } + for (i = rev = 0; i < NumBits; i++) { + rev = (rev << 1) | (index & 1); + index >>= 1; + } - return rev; + return rev; } -double Index_to_frequency ( unsigned NumSamples, unsigned Index ) +double Index_to_frequency(unsigned NumSamples, unsigned Index) { - if ( Index >= NumSamples ) - return 0.0; - else if ( Index <= NumSamples/2 ) - return (double)Index / (double)NumSamples; - - return -(double)(NumSamples-Index) / (double)NumSamples; + if (Index >= NumSamples) { + return 0.0; + } + else if (Index <= NumSamples / 2) { + return (double)Index / (double)NumSamples; + } + + return -(double)(NumSamples - Index) / (double)NumSamples; } - /*--- end of file fftmisc.c---*/ - /*============================================================================ fourierd.c - Don Cross @@ -115,134 +116,119 @@ double Index_to_frequency ( unsigned NumSamples, unsigned Index ) ============================================================================*/ -#define CHECKPOINTERDOUBLE(p) if (CheckPointerDouble(p,#p) == 0) return 0; +#define CHECKPOINTERDOUBLE(p) \ + if (CheckPointerDouble(p, #p) == 0) \ + return 0; -static int CheckPointerDouble ( void *p, char *name ) +static int CheckPointerDouble(void *p, char *name) { - if ( p == NULL ) - { - fprintf ( stderr, "Error in fft_double(): %s == NULL\n", name ); - return 0; - } - return 1; + if (p == NULL) { + fprintf(stderr, "Error in fft_double(): %s == NULL\n", name); + return 0; + } + return 1; } -int fft_double ( - unsigned NumSamples, - int InverseTransform, - double *RealIn, - double *ImagIn, - double *RealOut, - double *ImagOut ) +int fft_double(unsigned NumSamples, int InverseTransform, double *RealIn, double *ImagIn, + double *RealOut, double *ImagOut) { - unsigned NumBits; /* Number of bits needed to store indices */ - unsigned i, j, k, n; - unsigned BlockSize, BlockEnd; - - double angle_numerator = -2.0 * DDC_PI; // this is - to match matlab - double tr, ti; /* temp real, temp imaginary */ - - if ( !IsPowerOfTwo(NumSamples) || (NumSamples < 2) ) - { - fprintf ( - stderr, - "Error in fft(): NumSamples=%u is not power of two\n", - NumSamples ); - - return 0; - } - - if ( InverseTransform ) - angle_numerator = -angle_numerator; - - CHECKPOINTERDOUBLE ( RealIn ); - CHECKPOINTERDOUBLE ( RealOut ); - CHECKPOINTERDOUBLE ( ImagOut ); + unsigned NumBits; /* Number of bits needed to store indices */ + unsigned i, j, k, n; + unsigned BlockSize, BlockEnd; - NumBits = NumberOfBitsNeeded ( NumSamples ); + double angle_numerator = -2.0 * DDC_PI; // this is - to match matlab + double tr, ti; /* temp real, temp imaginary */ - /* - ** Do simultaneous data copy and bit-reversal ordering into outputs... - */ + if (!IsPowerOfTwo(NumSamples) || (NumSamples < 2)) { + fprintf(stderr, "Error in fft(): NumSamples=%u is not power of two\n", NumSamples); - for ( i=0; i < NumSamples; i++ ) - { - j = ReverseBits ( i, NumBits ); - RealOut[j] = RealIn[i]; - ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn[i]; + return 0; + } + + if (InverseTransform) { + angle_numerator = -angle_numerator; + } + + CHECKPOINTERDOUBLE(RealIn); + CHECKPOINTERDOUBLE(RealOut); + CHECKPOINTERDOUBLE(ImagOut); + + NumBits = NumberOfBitsNeeded(NumSamples); + + /* + ** Do simultaneous data copy and bit-reversal ordering into outputs... + */ + + for (i = 0; i < NumSamples; i++) { + j = ReverseBits(i, NumBits); + RealOut[j] = RealIn[i]; + ImagOut[j] = (ImagIn == NULL) ? 0.0 : ImagIn[i]; + } + + /* + ** Do the FFT itself... + */ + + BlockEnd = 1; + for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) { + double delta_angle = angle_numerator / (double)BlockSize; + double sm2 = sin(-2 * delta_angle); + double sm1 = sin(-delta_angle); + double cm2 = cos(-2 * delta_angle); + double cm1 = cos(-delta_angle); + double w = 2 * cm1; + /* double ar[3], ai[3]; replaced array with fixed vals below - labenski */ + double ar0, ar1, ar2, ai0, ai1, ai2; + + for (i = 0; i < NumSamples; i += BlockSize) { + ar2 = cm2; + ar1 = cm1; + + ai2 = sm2; + ai1 = sm1; + + for (j = i, n = 0; n < BlockEnd; j++, n++) { + ar0 = w * ar1 - ar2; + ar2 = ar1; + ar1 = ar0; + + ai0 = w * ai1 - ai2; + ai2 = ai1; + ai1 = ai0; + + k = j + BlockEnd; + tr = ar0 * RealOut[k] - ai0 * ImagOut[k]; + ti = ar0 * ImagOut[k] + ai0 * RealOut[k]; + + RealOut[k] = RealOut[j] - tr; + ImagOut[k] = ImagOut[j] - ti; + + RealOut[j] += tr; + ImagOut[j] += ti; + } } - /* - ** Do the FFT itself... - */ - - BlockEnd = 1; - for ( BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1 ) - { - double delta_angle = angle_numerator / (double)BlockSize; - double sm2 = sin ( -2 * delta_angle ); - double sm1 = sin ( -delta_angle ); - double cm2 = cos ( -2 * delta_angle ); - double cm1 = cos ( -delta_angle ); - double w = 2 * cm1; - /* double ar[3], ai[3]; replaced array with fixed vals below - labenski */ - double ar0, ar1, ar2, ai0, ai1, ai2; - - for ( i=0; i < NumSamples; i += BlockSize ) - { - ar2 = cm2; - ar1 = cm1; - - ai2 = sm2; - ai1 = sm1; - - for ( j=i, n=0; n < BlockEnd; j++, n++ ) - { - ar0 = w*ar1 - ar2; - ar2 = ar1; - ar1 = ar0; - - ai0 = w*ai1 - ai2; - ai2 = ai1; - ai1 = ai0; - - k = j + BlockEnd; - tr = ar0*RealOut[k] - ai0*ImagOut[k]; - ti = ar0*ImagOut[k] + ai0*RealOut[k]; - - RealOut[k] = RealOut[j] - tr; - ImagOut[k] = ImagOut[j] - ti; - - RealOut[j] += tr; - ImagOut[j] += ti; - } - } - - BlockEnd = BlockSize; - } + BlockEnd = BlockSize; + } - /* - ** Need to normalize if inverse transform... - */ + /* + ** Need to normalize if inverse transform... + */ - if ( InverseTransform ) - { - double denom = (double)NumSamples; + if (InverseTransform) { + double denom = (double)NumSamples; - for ( i=0; i < NumSamples; i++ ) - { - RealOut[i] /= denom; - ImagOut[i] /= denom; - } + for (i = 0; i < NumSamples; i++) { + RealOut[i] /= denom; + ImagOut[i] /= denom; } + } - return 1; + return 1; } - /*--- end of file fourierd.c ---*/ - /*============================================================================ fourierf.c - Don Cross @@ -262,128 +248,115 @@ int fft_double ( ============================================================================*/ -#define CHECKPOINTERFLOAT(p) if (CheckPointerFloat(p,#p) == 0) return 0; +#define CHECKPOINTERFLOAT(p) \ + if (CheckPointerFloat(p, #p) == 0) \ + return 0; -static int CheckPointerFloat ( void *p, char *name ) +static int CheckPointerFloat(void *p, char *name) { - if ( p == NULL ) - { - fprintf ( stderr, "Error in fft_float(): %s == NULL\n", name ); - return 0; - } - return 1; + if (p == NULL) { + fprintf(stderr, "Error in fft_float(): %s == NULL\n", name); + return 0; + } + return 1; } -int fft_float ( - unsigned NumSamples, - int InverseTransform, - float *RealIn, - float *ImagIn, - float *RealOut, - float *ImagOut ) +int fft_float(unsigned NumSamples, int InverseTransform, float *RealIn, float *ImagIn, + float *RealOut, float *ImagOut) { - unsigned NumBits; /* Number of bits needed to store indices */ - unsigned i, j, k, n; - unsigned BlockSize, BlockEnd; + unsigned NumBits; /* Number of bits needed to store indices */ + unsigned i, j, k, n; + unsigned BlockSize, BlockEnd; - double angle_numerator = -2.0 * DDC_PI; // this is - to match matlab - double tr, ti; /* temp real, temp imaginary */ + double angle_numerator = -2.0 * DDC_PI; // this is - to match matlab + double tr, ti; /* temp real, temp imaginary */ - if ( !IsPowerOfTwo(NumSamples) || (NumSamples < 2) ) - { - fprintf ( - stderr, - "Error in fft(): NumSamples=%u is not power of two\n", - NumSamples ); + if (!IsPowerOfTwo(NumSamples) || (NumSamples < 2)) { + fprintf(stderr, "Error in fft(): NumSamples=%u is not power of two\n", NumSamples); - return 0; - } - - if ( InverseTransform ) - angle_numerator = -angle_numerator; - - CHECKPOINTERFLOAT ( RealIn ); - CHECKPOINTERFLOAT ( RealOut ); - CHECKPOINTERFLOAT ( ImagOut ); - - NumBits = NumberOfBitsNeeded ( NumSamples ); - - /* - ** Do simultaneous data copy and bit-reversal ordering into outputs... - */ - - for ( i=0; i < NumSamples; i++ ) - { - j = ReverseBits ( i, NumBits ); - RealOut[j] = RealIn[i]; - ImagOut[j] = (ImagIn == NULL) ? (float)0.0 : ImagIn[i]; + return 0; + } + + if (InverseTransform) { + angle_numerator = -angle_numerator; + } + + CHECKPOINTERFLOAT(RealIn); + CHECKPOINTERFLOAT(RealOut); + CHECKPOINTERFLOAT(ImagOut); + + NumBits = NumberOfBitsNeeded(NumSamples); + + /* + ** Do simultaneous data copy and bit-reversal ordering into outputs... + */ + + for (i = 0; i < NumSamples; i++) { + j = ReverseBits(i, NumBits); + RealOut[j] = RealIn[i]; + ImagOut[j] = (ImagIn == NULL) ? (float)0.0 : ImagIn[i]; + } + + /* + ** Do the FFT itself... + */ + + BlockEnd = 1; + for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) { + double delta_angle = angle_numerator / (double)BlockSize; + double sm2 = sin(-2 * delta_angle); + double sm1 = sin(-delta_angle); + double cm2 = cos(-2 * delta_angle); + double cm1 = cos(-delta_angle); + double w = 2 * cm1; + /* double ar[3], ai[3]; replaced array with fixed vals below - labenski */ + double ar0, ar1, ar2, ai0, ai1, ai2; + /* double temp; */ + + for (i = 0; i < NumSamples; i += BlockSize) { + ar2 = cm2; + ar1 = cm1; + + ai2 = sm2; + ai1 = sm1; + + for (j = i, n = 0; n < BlockEnd; j++, n++) { + ar0 = w * ar1 - ar2; + ar2 = ar1; + ar1 = ar0; + + ai0 = w * ai1 - ai2; + ai2 = ai1; + ai1 = ai0; + + k = j + BlockEnd; + tr = ar0 * RealOut[k] - ai0 * ImagOut[k]; + ti = ar0 * ImagOut[k] + ai0 * RealOut[k]; + + RealOut[k] = (float)(RealOut[j] - tr); + ImagOut[k] = (float)(ImagOut[j] - ti); + + RealOut[j] += (float)tr; + ImagOut[j] += (float)ti; + } } - /* - ** Do the FFT itself... - */ - - BlockEnd = 1; - for ( BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1 ) - { - double delta_angle = angle_numerator / (double)BlockSize; - double sm2 = sin ( -2 * delta_angle ); - double sm1 = sin ( -delta_angle ); - double cm2 = cos ( -2 * delta_angle ); - double cm1 = cos ( -delta_angle ); - double w = 2 * cm1; - /* double ar[3], ai[3]; replaced array with fixed vals below - labenski */ - double ar0, ar1, ar2, ai0, ai1, ai2; - /* double temp; */ - - for ( i=0; i < NumSamples; i += BlockSize ) - { - ar2 = cm2; - ar1 = cm1; - - ai2 = sm2; - ai1 = sm1; - - for ( j=i, n=0; n < BlockEnd; j++, n++ ) - { - ar0 = w*ar1 - ar2; - ar2 = ar1; - ar1 = ar0; - - ai0 = w*ai1 - ai2; - ai2 = ai1; - ai1 = ai0; - - k = j + BlockEnd; - tr = ar0*RealOut[k] - ai0*ImagOut[k]; - ti = ar0*ImagOut[k] + ai0*RealOut[k]; - - RealOut[k] = (float)(RealOut[j] - tr); - ImagOut[k] = (float)(ImagOut[j] - ti); - - RealOut[j] += (float)tr; - ImagOut[j] += (float)ti; - } - } - - BlockEnd = BlockSize; - } + BlockEnd = BlockSize; + } - /* - ** Need to normalize if inverse transform... - */ + /* + ** Need to normalize if inverse transform... + */ - if ( InverseTransform ) - { - float denom = (float)NumSamples; + if (InverseTransform) { + float denom = (float)NumSamples; - for ( i=0; i < NumSamples; i++ ) - { - RealOut[i] /= denom; - ImagOut[i] /= denom; - } + for (i = 0; i < NumSamples; i++) { + RealOut[i] /= denom; + ImagOut[i] /= denom; } - return 1; + } + return 1; } /*--- end of file fourierf.c ---*/ diff --git a/src/labenski/src/fparser.cpp b/src/labenski/src/fparser.cpp index 52b512cab..61b99f973 100644 --- a/src/labenski/src/fparser.cpp +++ b/src/labenski/src/fparser.cpp @@ -11,41 +11,41 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/defs.h" - #include "wx/string.h" +#include "wx/defs.h" +#include "wx/string.h" #endif #if defined(__VISUALC__) && wxUSE_DEBUG_NEW_ALWAYS && defined(new) - #undef new // turn off wxWidgets debug code +#undef new // turn off wxWidgets debug code #endif // Turn off warnings generated from MSVC's buggy std:: lib header files. #if defined(__VISUALC__) - #include - #pragma warning(disable: 4018) // signed/unsigned mismatch - #pragma warning(disable: 4100) // unreferenced formal parameter - #pragma warning(disable: 4146) // unary minus operator applied to unsigned type, - // result still unsigned - #pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', - // possible loss of data - #pragma warning(disable: 4245) // conversion from 'type1' to 'type2', signed/unsigned - // mismatch - #pragma warning(disable: 4511) // 'class' : copy constructor could not be generated - #pragma warning(disable: 4512) // 'class' : assignment operator could not be generated - #pragma warning(disable: 4663) // C++ language change: to explicitly specialize class - // template 'vector' - #pragma warning(disable: 4710) // 'function' : function not inlined - #pragma warning(disable: 4786) // identifier was truncated to 'number' characters +#include +#pragma warning(disable : 4018) // signed/unsigned mismatch +#pragma warning(disable : 4100) // unreferenced formal parameter +#pragma warning(disable : 4146) // unary minus operator applied to unsigned type, + // result still unsigned +#pragma warning(disable : 4244) // 'conversion' conversion from 'type1' to 'type2', + // possible loss of data +#pragma warning(disable : 4245) // conversion from 'type1' to 'type2', signed/unsigned + // mismatch +#pragma warning(disable : 4511) // 'class' : copy constructor could not be generated +#pragma warning(disable : 4512) // 'class' : assignment operator could not be generated +#pragma warning(disable : 4663) // C++ language change: to explicitly specialize class + // template 'vector' +#pragma warning(disable : 4710) // 'function' : function not inlined +#pragma warning(disable : 4786) // identifier was truncated to 'number' characters #endif // Comment out the following line if your compiler supports the (non-standard) // asinh, acosh and atanh functions and you want them to be supported. If // you are not sure, just leave it (those function will then not be supported). -//#define NO_ASINH +// #define NO_ASINH #if defined(__VISUALC__) || defined(__BORLANDC__) // || defined(__WATCOMC__) // use our own asin/cos/tanh functions from since compilier doesn't have them @@ -55,58 +55,62 @@ double logoneplusx(double x) { - if (x == 0.0) - return 0.0; - else if ((x < -0.2928) || (x > 0.4142)) - return log(1.0 + x); - else - { - double z = x/(x + 2.0); - double y = z*z; - return z*(2.0+y*(0.666666666663366+y*(0.400000001206045+y* - (0.285714091590488+y*(0.22223823332791+y* - (0.1811136267967+y*0.16948212488)))))); - } + if (x == 0.0) { + return 0.0; + } + else if ((x < -0.2928) || (x > 0.4142)) { + return log(1.0 + x); + } + else { + double z = x / (x + 2.0); + double y = z * z; + return z * + (2.0 + + y * (0.666666666663366 + + y * (0.400000001206045 + + y * (0.285714091590488 + + y * (0.22223823332791 + y * (0.1811136267967 + y * 0.16948212488)))))); + } } double asinh(double x) { - if (fabs(x) > 1.0E10) - return ((x > 0.0) ? 0.69314718055995+log(fabs(x)) : - -0.69314718055995+log(fabs(x))); - else - { - double y = x*x; - return ((x == 0.0) ? 0.0 : ((x > 0.0) ? - logoneplusx(fabs(x)+y/(1.0+sqrt(1.0+y))) : - -logoneplusx(fabs(x)+y/(1.0+sqrt(1.0+y))))); - } + if (fabs(x) > 1.0E10) { + return ((x > 0.0) ? 0.69314718055995 + log(fabs(x)) : -0.69314718055995 + log(fabs(x))); + } + else { + double y = x * x; + return ((x == 0.0) ? 0.0 + : ((x > 0.0) ? logoneplusx(fabs(x) + y / (1.0 + sqrt(1.0 + y))) + : -logoneplusx(fabs(x) + y / (1.0 + sqrt(1.0 + y))))); + } } double acosh(double x) { - return ((x <= 1.0) ? 0.0 : ((x > 1.0E10) ? 0.69314718055995+log(x) : - log(x+sqrt((x-1.0)*(x+1.0))))); + return ((x <= 1.0) + ? 0.0 + : ((x > 1.0E10) ? 0.69314718055995 + log(x) : log(x + sqrt((x - 1.0) * (x + 1.0))))); } double atanh(double x) { - double ax = fabs(x); - if (ax >= 1.0) - return ((x > 0.0) ? DBL_MAX : -DBL_MAX); - else - { - return ((x == 0) ? 0.0 : ((x > 0.0) ? 0.5*logoneplusx(2.0*ax/(1.0-ax)) : - -0.5*logoneplusx(2.0*ax/(1.0-ax)))); - } + double ax = fabs(x); + if (ax >= 1.0) { + return ((x > 0.0) ? DBL_MAX : -DBL_MAX); + } + else { + return ((x == 0) ? 0.0 + : ((x > 0.0) ? 0.5 * logoneplusx(2.0 * ax / (1.0 - ax)) + : -0.5 * logoneplusx(2.0 * ax / (1.0 - ax)))); + } } #endif // Uncomment the following line to disable the eval() function if it could // be too dangerous in the target application: -//#define DISABLE_EVAL - +// #define DISABLE_EVAL // Comment this line out if you are not going to use the optimizer and want // a slightly smaller library. The Optimize() method can still be called, @@ -123,107 +127,88 @@ double atanh(double x) // ---------------------------------------------------------------------------- // wxFunctionParser - a thin wrapper around FunctionParser // ---------------------------------------------------------------------------- -wxFunctionParser::wxFunctionParser() : m_ok(false) -{ - m_functionParser = new FunctionParser; -} -wxFunctionParser::wxFunctionParser(const wxFunctionParser& fP) -{ - m_functionParser = new FunctionParser(*fP.GetFunctionParser()); - m_function = fP.GetFunctionString(); - m_variables = fP.GetVariableString(); - m_ok = fP.Ok(); -} -wxFunctionParser::~wxFunctionParser() +wxFunctionParser::wxFunctionParser() : m_ok(false) { m_functionParser = new FunctionParser; } +wxFunctionParser::wxFunctionParser(const wxFunctionParser &fP) { - delete m_functionParser; + m_functionParser = new FunctionParser(*fP.GetFunctionParser()); + m_function = fP.GetFunctionString(); + m_variables = fP.GetVariableString(); + m_ok = fP.Ok(); } -int wxFunctionParser::Parse(const wxString& function, const wxString& vars, - bool useDegrees) +wxFunctionParser::~wxFunctionParser() { delete m_functionParser; } +int wxFunctionParser::Parse(const wxString &function, const wxString &vars, bool useDegrees) { - m_function = function; - m_variables = vars; + m_function = function; + m_variables = vars; - std::string Function = (const char*)wxConvUTF8.cWX2MB(function.c_str()); - std::string Vars = (const char*)wxConvUTF8.cWX2MB(vars.c_str()); + std::string Function = (const char *)wxConvUTF8.cWX2MB(function.c_str()); + std::string Vars = (const char *)wxConvUTF8.cWX2MB(vars.c_str()); - int ret = m_functionParser->Parse(Function, Vars, useDegrees); - m_ok = (ret == -1) && ErrorMsg().IsEmpty(); + int ret = m_functionParser->Parse(Function, Vars, useDegrees); + m_ok = (ret == -1) && ErrorMsg().IsEmpty(); - return ret; + return ret; } wxString wxFunctionParser::ErrorMsg() const { - const char *msg = m_functionParser->ErrorMsg(); - if (!msg) - return wxEmptyString; + const char *msg = m_functionParser->ErrorMsg(); + if (!msg) { + return wxEmptyString; + } - return wxConvUTF8.cMB2WX(msg); + return wxConvUTF8.cMB2WX(msg); } wxFunctionParser::ParseErrorType wxFunctionParser::GetParseErrorType() const { - return (wxFunctionParser::ParseErrorType)m_functionParser->GetParseErrorType(); -} -double wxFunctionParser::Eval(const double* Vars) -{ - return m_functionParser->Eval(Vars); -} -int wxFunctionParser::EvalError() const -{ - return m_functionParser->EvalError(); + return (wxFunctionParser::ParseErrorType)m_functionParser->GetParseErrorType(); } -bool wxFunctionParser::AddConstant(const wxString& name, double value) +double wxFunctionParser::Eval(const double *Vars) { return m_functionParser->Eval(Vars); } +int wxFunctionParser::EvalError() const { return m_functionParser->EvalError(); } +bool wxFunctionParser::AddConstant(const wxString &name, double value) { - std::string Name = (const char*)wxConvUTF8.cWX2MB(name.c_str()); - return m_functionParser->AddConstant(Name, value); + std::string Name = (const char *)wxConvUTF8.cWX2MB(name.c_str()); + return m_functionParser->AddConstant(Name, value); } -bool wxFunctionParser::AddFunction(const wxString& name, - FunctionPtr fP, unsigned paramsAmount) +bool wxFunctionParser::AddFunction(const wxString &name, FunctionPtr fP, unsigned paramsAmount) { - std::string Name = (const char*)wxConvUTF8.cWX2MB(name.c_str()); - return m_functionParser->AddFunction(Name, fP, paramsAmount); + std::string Name = (const char *)wxConvUTF8.cWX2MB(name.c_str()); + return m_functionParser->AddFunction(Name, fP, paramsAmount); } -bool wxFunctionParser::AddFunction(const wxString& name, wxFunctionParser& fP) +bool wxFunctionParser::AddFunction(const wxString &name, wxFunctionParser &fP) { - std::string Name = (const char*)wxConvUTF8.cWX2MB(name.c_str()); - return m_functionParser->AddFunction(Name, *fP.GetFunctionParser()); -} -void wxFunctionParser::Optimize() -{ - m_functionParser->Optimize(); -} -int wxFunctionParser::GetNumberVariables() const -{ - return m_functionParser->GetNumberVariables(); -} -bool wxFunctionParser::GetUseDegrees() const -{ - return m_functionParser->GetUseDegrees(); + std::string Name = (const char *)wxConvUTF8.cWX2MB(name.c_str()); + return m_functionParser->AddFunction(Name, *fP.GetFunctionParser()); } +void wxFunctionParser::Optimize() { m_functionParser->Optimize(); } +int wxFunctionParser::GetNumberVariables() const { return m_functionParser->GetNumberVariables(); } +bool wxFunctionParser::GetUseDegrees() const { return m_functionParser->GetUseDegrees(); } wxString wxFunctionParser::GetVariableName(size_t n) const { - int numVars = GetNumberVariables(); - if (int(n) >= numVars) return wxEmptyString; - wxString vars(GetVariableString()); - size_t i, count = 0, len = vars.Length(); - for (i = 0; i < len; i++) - { - if (n == count) - return vars.Mid(i).BeforeFirst(wxT(',')); - if (vars[i] == wxT(',')) - count++; + int numVars = GetNumberVariables(); + if (int(n) >= numVars) { + return wxEmptyString; + } + wxString vars(GetVariableString()); + size_t i, count = 0, len = vars.Length(); + for (i = 0; i < len; i++) { + if (n == count) { + return vars.Mid(i).BeforeFirst(wxT(',')); } + if (vars[i] == wxT(',')) { + count++; + } + } - return wxEmptyString; + return wxEmptyString; } -wxFunctionParser& wxFunctionParser::operator=(const wxFunctionParser& cpy) +wxFunctionParser &wxFunctionParser::operator=(const wxFunctionParser &cpy) { - *m_functionParser = *cpy.GetFunctionParser(); - m_function = cpy.GetFunctionString(); - m_variables = cpy.GetVariableString(); - m_ok = cpy.Ok(); - return *this; + *m_functionParser = *cpy.GetFunctionParser(); + m_function = cpy.GetFunctionString(); + m_variables = cpy.GetVariableString(); + m_ok = cpy.Ok(); + return *this; } //============================================================================ @@ -233,8 +218,9 @@ wxFunctionParser& wxFunctionParser::operator=(const wxFunctionParser& cpy) #include #include -#if defined(__VISUALC__) && (__VISUALC__ <= 1100) // for VC6 - non standard - namespace std {} +#if defined(__VISUALC__) && (__VISUALC__ <= 1100) // for VC6 - non standard +namespace std { +} #endif using namespace std; @@ -243,1345 +229,1514 @@ using namespace std; #define M_PI 3.1415926535897932384626433832795 #endif -namespace -{ +namespace { // The functions must be in alphabetical order: - enum OPCODE - { - cAbs, cAcos, +enum OPCODE { + cAbs, + cAcos, #ifndef NO_ASINH - cAcosh, + cAcosh, #endif - cAsin, + cAsin, #ifndef NO_ASINH - cAsinh, + cAsinh, #endif - cAtan, - cAtan2, + cAtan, + cAtan2, #ifndef NO_ASINH - cAtanh, + cAtanh, #endif - cCeil, cCos, cCosh, cCot, cCsc, + cCeil, + cCos, + cCosh, + cCot, + cCsc, #ifndef DISABLE_EVAL - cEval, + cEval, #endif - cExp, cFloor, cIf, cInt, cLog, cLog10, cMax, cMin, - cSec, cSin, cSinh, cSqrt, cTan, cTanh, - -// These do not need any ordering: - cImmed, cJump, - cNeg, cAdd, cSub, cMul, cDiv, cMod, cPow, - cEqual, cLess, cGreater, cAnd, cOr, - - cDeg, cRad, - - cFCall, cPCall, + cExp, + cFloor, + cIf, + cInt, + cLog, + cLog10, + cMax, + cMin, + cSec, + cSin, + cSinh, + cSqrt, + cTan, + cTanh, + + // These do not need any ordering: + cImmed, + cJump, + cNeg, + cAdd, + cSub, + cMul, + cDiv, + cMod, + cPow, + cEqual, + cLess, + cGreater, + cAnd, + cOr, + + cDeg, + cRad, + + cFCall, + cPCall, #ifdef SUPPORT_OPTIMIZER - cVar, cDup, cInv, + cVar, + cDup, + cInv, #endif - VarBegin - }; - - struct FuncDefinition - { - const char* name; - unsigned nameLength; - unsigned opcode; - unsigned params; - - // This is basically strcmp(), but taking 'nameLength' as string - // length (not ending '\0'): - bool operator<(const FuncDefinition& rhs) const - { - for(unsigned i = 0; i < nameLength; ++i) - { - if(i == rhs.nameLength) return false; - const char c1 = name[i], c2 = rhs.name[i]; - if(c1 < c2) return true; - if(c2 < c1) return false; - } - return nameLength < rhs.nameLength; - } - }; + VarBegin +}; +struct FuncDefinition { + const char *name; + unsigned nameLength; + unsigned opcode; + unsigned params; + + // This is basically strcmp(), but taking 'nameLength' as string + // length (not ending '\0'): + bool operator<(const FuncDefinition &rhs) const + { + for (unsigned i = 0; i < nameLength; ++i) { + if (i == rhs.nameLength) { + return false; + } + const char c1 = name[i], c2 = rhs.name[i]; + if (c1 < c2) { + return true; + } + if (c2 < c1) { + return false; + } + } + return nameLength < rhs.nameLength; + } +}; // This list must be in alphabetical order: - const FuncDefinition Functions[]= - { - { "abs", 3, cAbs, 1 }, - { "acos", 4, cAcos, 1 }, +const FuncDefinition Functions[] = { + {"abs", 3, cAbs, 1}, {"acos", 4, cAcos, 1}, #ifndef NO_ASINH - { "acosh", 5, cAcosh, 1 }, + {"acosh", 5, cAcosh, 1}, #endif - { "asin", 4, cAsin, 1 }, + {"asin", 4, cAsin, 1}, #ifndef NO_ASINH - { "asinh", 5, cAsinh, 1 }, + {"asinh", 5, cAsinh, 1}, #endif - { "atan", 4, cAtan, 1 }, - { "atan2", 5, cAtan2, 2 }, + {"atan", 4, cAtan, 1}, {"atan2", 5, cAtan2, 2}, #ifndef NO_ASINH - { "atanh", 5, cAtanh, 1 }, + {"atanh", 5, cAtanh, 1}, #endif - { "ceil", 4, cCeil, 1 }, - { "cos", 3, cCos, 1 }, - { "cosh", 4, cCosh, 1 }, - { "cot", 3, cCot, 1 }, - { "csc", 3, cCsc, 1 }, + {"ceil", 4, cCeil, 1}, {"cos", 3, cCos, 1}, {"cosh", 4, cCosh, 1}, {"cot", 3, cCot, 1}, + {"csc", 3, cCsc, 1}, #ifndef DISABLE_EVAL - { "eval", 4, cEval, 0 }, + {"eval", 4, cEval, 0}, #endif - { "exp", 3, cExp, 1 }, - { "floor", 5, cFloor, 1 }, - { "if", 2, cIf, 0 }, - { "int", 3, cInt, 1 }, - { "log", 3, cLog, 1 }, - { "log10", 5, cLog10, 1 }, - { "max", 3, cMax, 2 }, - { "min", 3, cMin, 2 }, - { "sec", 3, cSec, 1 }, - { "sin", 3, cSin, 1 }, - { "sinh", 4, cSinh, 1 }, - { "sqrt", 4, cSqrt, 1 }, - { "tan", 3, cTan, 1 }, - { "tanh", 4, cTanh, 1 } - }; - - const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]); - - - // BCB4 does not implement the standard lower_bound function. - // This is used instead: - const FuncDefinition* fp_lower_bound(const FuncDefinition* first, - const FuncDefinition* last, - const FuncDefinition& value) - { - while(first < last) - { - const FuncDefinition* middle = first+(last-first)/2; - if(*middle < value) first = middle+1; - else last = middle; - } - return last; - } + {"exp", 3, cExp, 1}, {"floor", 5, cFloor, 1}, {"if", 2, cIf, 0}, {"int", 3, cInt, 1}, + {"log", 3, cLog, 1}, {"log10", 5, cLog10, 1}, {"max", 3, cMax, 2}, {"min", 3, cMin, 2}, + {"sec", 3, cSec, 1}, {"sin", 3, cSin, 1}, {"sinh", 4, cSinh, 1}, {"sqrt", 4, cSqrt, 1}, + {"tan", 3, cTan, 1}, {"tanh", 4, cTanh, 1}}; +const unsigned FUNC_AMOUNT = sizeof(Functions) / sizeof(Functions[0]); - // Returns a pointer to the FuncDefinition instance which 'name' is - // the same as the one given by 'F'. If no such function name exists, - // returns 0. - inline const FuncDefinition* FindFunction(const char* F) - { - FuncDefinition func = { F, 0, 0, 0 }; - while(isalnum(F[func.nameLength])) ++func.nameLength; - if(func.nameLength) - { - const FuncDefinition* found = - fp_lower_bound(Functions, Functions+FUNC_AMOUNT, func); - if(found == Functions+FUNC_AMOUNT || func < *found) - return 0; - return found; - } - return 0; +// BCB4 does not implement the standard lower_bound function. +// This is used instead: +const FuncDefinition *fp_lower_bound(const FuncDefinition *first, const FuncDefinition *last, + const FuncDefinition &value) +{ + while (first < last) { + const FuncDefinition *middle = first + (last - first) / 2; + if (*middle < value) { + first = middle + 1; + } + else { + last = middle; } + } + return last; } +// Returns a pointer to the FuncDefinition instance which 'name' is +// the same as the one given by 'F'. If no such function name exists, +// returns 0. +inline const FuncDefinition *FindFunction(const char *F) +{ + FuncDefinition func = {F, 0, 0, 0}; + while (isalnum(F[func.nameLength])) { + ++func.nameLength; + } + if (func.nameLength) { + const FuncDefinition *found = fp_lower_bound(Functions, Functions + FUNC_AMOUNT, func); + if (found == Functions + FUNC_AMOUNT || func < *found) { + return 0; + } + return found; + } + return 0; +} +} // namespace //--------------------------------------------------------------------------- // Copy-on-write method //--------------------------------------------------------------------------- inline void FunctionParser::copyOnWrite() { - if(data->referenceCounter > 1) - { - Data* oldData = data; - data = new Data(*oldData); - --(oldData->referenceCounter); - data->referenceCounter = 1; - } + if (data->referenceCounter > 1) { + Data *oldData = data; + data = new Data(*oldData); + --(oldData->referenceCounter); + data->referenceCounter = 1; + } } - //--------------------------------------------------------------------------- // Constructors and destructors //--------------------------------------------------------------------------- //=========================================================================== -FunctionParser::FunctionParser(): - parseErrorType(FP_NO_ERROR), evalErrorType(0), - data(new Data) +FunctionParser::FunctionParser() : parseErrorType(FP_NO_ERROR), evalErrorType(0), data(new Data) { - data->referenceCounter = 1; + data->referenceCounter = 1; } FunctionParser::~FunctionParser() { - if(--(data->referenceCounter) == 0) - { - delete data; - } + if (--(data->referenceCounter) == 0) { + delete data; + } } -FunctionParser::FunctionParser(const FunctionParser& cpy): - parseErrorType(cpy.parseErrorType), - evalErrorType(cpy.evalErrorType), - data(cpy.data) +FunctionParser::FunctionParser(const FunctionParser &cpy) + : parseErrorType(cpy.parseErrorType), evalErrorType(cpy.evalErrorType), data(cpy.data) { - ++(data->referenceCounter); + ++(data->referenceCounter); } -FunctionParser& FunctionParser::operator=(const FunctionParser& cpy) +FunctionParser &FunctionParser::operator=(const FunctionParser &cpy) { - if(data != cpy.data) - { + if (data != cpy.data) { - if(--(data->referenceCounter) == 0) delete data; + if (--(data->referenceCounter) == 0) { + delete data; + } - parseErrorType = cpy.parseErrorType; - evalErrorType = cpy.evalErrorType; - data = cpy.data; + parseErrorType = cpy.parseErrorType; + evalErrorType = cpy.evalErrorType; + data = cpy.data; - ++(data->referenceCounter); - } + ++(data->referenceCounter); + } - return *this; + return *this; } - -FunctionParser::Data::Data(): - useDegreeConversion(false), - ByteCode(0), ByteCodeSize(0), - Immed(0), ImmedSize(0), - Stack(0), StackSize(0) -{} +FunctionParser::Data::Data() + : useDegreeConversion(false), ByteCode(0), ByteCodeSize(0), Immed(0), ImmedSize(0), Stack(0), + StackSize(0) +{ +} FunctionParser::Data::~Data() { - if(ByteCode) { delete[] ByteCode; ByteCode=0; } - if(Immed) { delete[] Immed; Immed=0; } - if(Stack) { delete[] Stack; Stack=0; } + if (ByteCode) { + delete[] ByteCode; + ByteCode = 0; + } + if (Immed) { + delete[] Immed; + Immed = 0; + } + if (Stack) { + delete[] Stack; + Stack = 0; + } } // Makes a deep-copy of Data: -FunctionParser::Data::Data(const Data& cpy): - varAmount(cpy.varAmount), useDegreeConversion(cpy.useDegreeConversion), - Variables(cpy.Variables), Constants(cpy.Constants), - FuncPtrNames(cpy.FuncPtrNames), FuncPtrs(cpy.FuncPtrs), - FuncParserNames(cpy.FuncParserNames), FuncParsers(cpy.FuncParsers), - ByteCode(0), ByteCodeSize(cpy.ByteCodeSize), - Immed(0), ImmedSize(cpy.ImmedSize), - Stack(0), StackSize(cpy.StackSize) -{ - if(ByteCodeSize) ByteCode = new unsigned[ByteCodeSize]; - if(ImmedSize) Immed = new double[ImmedSize]; - if(StackSize) Stack = new double[StackSize]; - - // MSVC doesn't allow i used twice in for loops - for(unsigned i=0; i& dest) - { - unsigned varNumber = VarBegin; - unsigned ind1 = 0, ind2; - - while(ind1 < Vars.size()) - { - if(!isalpha(Vars[ind1]) && Vars[ind1]!='_') return false; - for(ind2=ind1+1; ind2 &dest) +{ + unsigned varNumber = VarBegin; + unsigned ind1 = 0, ind2; + + while (ind1 < Vars.size()) { + if (!isalpha(Vars[ind1]) && Vars[ind1] != '_') { + return false; + } + for (ind2 = ind1 + 1; ind2 < Vars.size() && Vars[ind2] != ','; ++ind2) { + if (!isalnum(Vars[ind2]) && Vars[ind2] != '_') { + return false; + } + } + const string varName = Vars.substr(ind1, ind2 - ind1); - ind1 = ind2+1; - } - return true; + if (dest.insert(make_pair(varName, varNumber++)).second == false) { + return false; } + + ind1 = ind2 + 1; + } + return true; } +} // namespace -bool FunctionParser::isValidName(const std::string& name) const +bool FunctionParser::isValidName(const std::string &name) const { - if(name.empty() || (!isalpha(name[0]) && name[0] != '_')) return false; - for(unsigned i=0; iFuncParserNames) != - data->FuncParserNames.end() || - FindVariable(n, data->FuncPtrNames) != - data->FuncPtrNames.end()) - return false; + if (isValidName(name)) { + const char *n = name.c_str(); + if (FindVariable(n, data->FuncParserNames) != data->FuncParserNames.end() || + FindVariable(n, data->FuncPtrNames) != data->FuncPtrNames.end()) { + return false; + } - copyOnWrite(); + copyOnWrite(); - data->Constants[name] = value; - return true; - } - return false; + data->Constants[name] = value; + return true; + } + return false; } // Function pointers -bool FunctionParser::AddFunction(const std::string& name, - FunctionPtr func, unsigned paramsAmount) +bool FunctionParser::AddFunction(const std::string &name, FunctionPtr func, unsigned paramsAmount) { - if(paramsAmount == 0) return false; // Currently must be at least one + if (paramsAmount == 0) { + return false; // Currently must be at least one + } - if(isValidName(name)) - { - const char* n = name.c_str(); - if(FindVariable(n, data->FuncParserNames) != - data->FuncParserNames.end() || - FindConstant(n) != data->Constants.end()) - return false; + if (isValidName(name)) { + const char *n = name.c_str(); + if (FindVariable(n, data->FuncParserNames) != data->FuncParserNames.end() || + FindConstant(n) != data->Constants.end()) { + return false; + } - copyOnWrite(); + copyOnWrite(); - data->FuncPtrNames[name] = data->FuncPtrs.size(); - data->FuncPtrs.push_back(Data::FuncPtrData(func, paramsAmount)); - return true; - } - return false; + data->FuncPtrNames[name] = data->FuncPtrs.size(); + data->FuncPtrs.push_back(Data::FuncPtrData(func, paramsAmount)); + return true; + } + return false; } -bool FunctionParser::checkRecursiveLinking(const FunctionParser* fp) const +bool FunctionParser::checkRecursiveLinking(const FunctionParser *fp) const { - if(fp == this) return true; - for(unsigned i=0; idata->FuncParsers.size(); ++i) - if(checkRecursiveLinking(fp->data->FuncParsers[i])) return true; - return false; + if (fp == this) { + return true; + } + for (unsigned i = 0; i < fp->data->FuncParsers.size(); ++i) { + if (checkRecursiveLinking(fp->data->FuncParsers[i])) { + return true; + } + } + return false; } -bool FunctionParser::AddFunction(const std::string& name, - FunctionParser& parser) +bool FunctionParser::AddFunction(const std::string &name, FunctionParser &parser) { - if(parser.data->varAmount == 0) // Currently must be at least one - return false; - - if(isValidName(name)) - { - const char* n = name.c_str(); - if(FindVariable(n, data->FuncPtrNames) != data->FuncPtrNames.end() || - FindConstant(n) != data->Constants.end()) - return false; - - if(checkRecursiveLinking(&parser)) return false; + if (parser.data->varAmount == 0) { // Currently must be at least one + return false; + } - copyOnWrite(); + if (isValidName(name)) { + const char *n = name.c_str(); + if (FindVariable(n, data->FuncPtrNames) != data->FuncPtrNames.end() || + FindConstant(n) != data->Constants.end()) { + return false; + } - data->FuncParserNames[name] = data->FuncParsers.size(); - data->FuncParsers.push_back(&parser); - return true; + if (checkRecursiveLinking(&parser)) { + return false; } - return false; -} + copyOnWrite(); + data->FuncParserNames[name] = data->FuncParsers.size(); + data->FuncParsers.push_back(&parser); + return true; + } + return false; +} // Main parsing function // --------------------- -int FunctionParser::Parse(const std::string& Function, - const std::string& Vars, - bool useDegrees) +int FunctionParser::Parse(const std::string &Function, const std::string &Vars, bool useDegrees) { - copyOnWrite(); + copyOnWrite(); + data->Variables.clear(); - data->Variables.clear(); - - if(!ParseVars(Vars, data->Variables)) - { - parseErrorType = INVALID_VARS; - return Function.size(); - } - data->varAmount = data->Variables.size(); // this is for Eval() + if (!ParseVars(Vars, data->Variables)) { + parseErrorType = INVALID_VARS; + return Function.size(); + } + data->varAmount = data->Variables.size(); // this is for Eval() - const char* Func = Function.c_str(); + const char *Func = Function.c_str(); - parseErrorType = FP_NO_ERROR; + parseErrorType = FP_NO_ERROR; - int Result = CheckSyntax(Func); - if(Result>=0) return Result; + int Result = CheckSyntax(Func); + if (Result >= 0) { + return Result; + } - data->useDegreeConversion = useDegrees; - if(!Compile(Func)) return Function.size(); + data->useDegreeConversion = useDegrees; + if (!Compile(Func)) { + return Function.size(); + } - data->Variables.clear(); + data->Variables.clear(); - parseErrorType = FP_NO_ERROR; + parseErrorType = FP_NO_ERROR; - return -1; + return -1; } -namespace -{ - // Is given char an operator? - inline bool IsOperator(int c) - { - return strchr("+-*/%^=<>&|",c)!=NULL; - } +namespace { +// Is given char an operator? +inline bool IsOperator(int c) { return strchr("+-*/%^=<>&|", c) != NULL; } - // skip whitespace - inline void sws(const char* F, int& Ind) - { - while(F[Ind] && isspace(F[Ind])) ++Ind; - } +// skip whitespace +inline void sws(const char *F, int &Ind) +{ + while (F[Ind] && isspace(F[Ind])) { + ++Ind; + } } +} // namespace // Returns an iterator to the variable with the same name as 'F', or to // Variables.end() if no such variable exists: inline FunctionParser::Data::VarMap_t::const_iterator -FunctionParser::FindVariable(const char* F, const Data::VarMap_t& vars) const +FunctionParser::FindVariable(const char *F, const Data::VarMap_t &vars) const { - if(vars.size()) - { - unsigned ind = 0; - while(isalnum(F[ind]) || F[ind] == '_') ++ind; - if(ind) - { - string name(F, ind); - return vars.find(name); - } + if (vars.size()) { + unsigned ind = 0; + while (isalnum(F[ind]) || F[ind] == '_') { + ++ind; + } + if (ind) { + string name(F, ind); + return vars.find(name); } - return vars.end(); + } + return vars.end(); } inline FunctionParser::Data::ConstMap_t::const_iterator -FunctionParser::FindConstant(const char* F) const +FunctionParser::FindConstant(const char *F) const { - if(data->Constants.size()) - { - unsigned ind = 0; - while(isalnum(F[ind]) || F[ind] == '_') ++ind; - if(ind) - { - string name(F, ind); - return data->Constants.find(name); - } + if (data->Constants.size()) { + unsigned ind = 0; + while (isalnum(F[ind]) || F[ind] == '_') { + ++ind; + } + if (ind) { + string name(F, ind); + return data->Constants.find(name); } - return data->Constants.end(); + } + return data->Constants.end(); } //--------------------------------------------------------------------------- // Check function string syntax // ---------------------------- -int FunctionParser::CheckSyntax(const char* Function) -{ - const Data::VarMap_t& Variables = data->Variables; - const Data::ConstMap_t& Constants = data->Constants; - const Data::VarMap_t& FuncPtrNames = data->FuncPtrNames; - const Data::VarMap_t& FuncParserNames = data->FuncParserNames; - - vector functionParenthDepth; - - int Ind=0, ParenthCnt=0, c; - char* Ptr; - - while(true) - { - sws(Function, Ind); - c=Function[Ind]; - -// Check for valid operand (must appear) - - // Check for leading - - if(c=='-') { sws(Function, ++Ind); c=Function[Ind]; } - if(c==0) { parseErrorType=PREMATURE_EOS; return Ind; } - - // Check for math function - bool foundFunc = false; - const FuncDefinition* fptr = FindFunction(&Function[Ind]); - if(fptr) - { - Ind += fptr->nameLength; - foundFunc = true; - } - else - { - // Check for user-defined function - Data::VarMap_t::const_iterator fIter = - FindVariable(&Function[Ind], FuncPtrNames); - if(fIter != FuncPtrNames.end()) - { - Ind += fIter->first.size(); - foundFunc = true; - } - else - { - Data::VarMap_t::const_iterator pIter = - FindVariable(&Function[Ind], FuncParserNames); - if(pIter != FuncParserNames.end()) - { - Ind += pIter->first.size(); - foundFunc = true; - } - } - } - - if(foundFunc) - { - sws(Function, Ind); - c = Function[Ind]; - if(c!='(') { parseErrorType=EXPECT_PARENTH_FUNC; return Ind; } - functionParenthDepth.push_back(ParenthCnt+1); +int FunctionParser::CheckSyntax(const char *Function) +{ + const Data::VarMap_t &Variables = data->Variables; + const Data::ConstMap_t &Constants = data->Constants; + const Data::VarMap_t &FuncPtrNames = data->FuncPtrNames; + const Data::VarMap_t &FuncParserNames = data->FuncParserNames; + + vector functionParenthDepth; + + int Ind = 0, ParenthCnt = 0, c; + char *Ptr; + + while (true) { + sws(Function, Ind); + c = Function[Ind]; + + // Check for valid operand (must appear) + + // Check for leading - + if (c == '-') { + sws(Function, ++Ind); + c = Function[Ind]; + } + if (c == 0) { + parseErrorType = PREMATURE_EOS; + return Ind; + } + + // Check for math function + bool foundFunc = false; + const FuncDefinition *fptr = FindFunction(&Function[Ind]); + if (fptr) { + Ind += fptr->nameLength; + foundFunc = true; + } + else { + // Check for user-defined function + Data::VarMap_t::const_iterator fIter = FindVariable(&Function[Ind], FuncPtrNames); + if (fIter != FuncPtrNames.end()) { + Ind += fIter->first.size(); + foundFunc = true; + } + else { + Data::VarMap_t::const_iterator pIter = FindVariable(&Function[Ind], FuncParserNames); + if (pIter != FuncParserNames.end()) { + Ind += pIter->first.size(); + foundFunc = true; } - - // Check for opening parenthesis - if(c=='(') - { - ++ParenthCnt; - sws(Function, ++Ind); - if(Function[Ind]==')') { parseErrorType=EMPTY_PARENTH; return Ind;} - continue; - } - - // Check for number - if(isdigit(c) || (c=='.' && isdigit(Function[Ind+1]))) - { - strtod(&Function[Ind], &Ptr); - Ind += int(Ptr-&Function[Ind]); - sws(Function, Ind); - c = Function[Ind]; + } + } + + if (foundFunc) { + sws(Function, Ind); + c = Function[Ind]; + if (c != '(') { + parseErrorType = EXPECT_PARENTH_FUNC; + return Ind; + } + functionParenthDepth.push_back(ParenthCnt + 1); + } + + // Check for opening parenthesis + if (c == '(') { + ++ParenthCnt; + sws(Function, ++Ind); + if (Function[Ind] == ')') { + parseErrorType = EMPTY_PARENTH; + return Ind; + } + continue; + } + + // Check for number + if (isdigit(c) || (c == '.' && isdigit(Function[Ind + 1]))) { + strtod(&Function[Ind], &Ptr); + Ind += int(Ptr - &Function[Ind]); + sws(Function, Ind); + c = Function[Ind]; + } + else { // Check for variable + Data::VarMap_t::const_iterator vIter = FindVariable(&Function[Ind], Variables); + if (vIter != Variables.end()) { + Ind += vIter->first.size(); + } + else { + // Check for constant + Data::ConstMap_t::const_iterator cIter = FindConstant(&Function[Ind]); + if (cIter != Constants.end()) { + Ind += cIter->first.size(); } - else - { // Check for variable - Data::VarMap_t::const_iterator vIter = - FindVariable(&Function[Ind], Variables); - if(vIter != Variables.end()) - Ind += vIter->first.size(); - else - { - // Check for constant - Data::ConstMap_t::const_iterator cIter = - FindConstant(&Function[Ind]); - if(cIter != Constants.end()) - Ind += cIter->first.size(); - else - { parseErrorType=SYNTAX_ERROR; return Ind; } - } - sws(Function, Ind); - c = Function[Ind]; + else { + parseErrorType = SYNTAX_ERROR; + return Ind; } + } + sws(Function, Ind); + c = Function[Ind]; + } - // Check for closing parenthesis - while(c==')') - { - if(functionParenthDepth.size() && - functionParenthDepth.back() == ParenthCnt) - functionParenthDepth.pop_back(); - if((--ParenthCnt)<0) { parseErrorType=MISM_PARENTH; return Ind; } - sws(Function, ++Ind); - c=Function[Ind]; - } + // Check for closing parenthesis + while (c == ')') { + if (functionParenthDepth.size() && functionParenthDepth.back() == ParenthCnt) { + functionParenthDepth.pop_back(); + } + if ((--ParenthCnt) < 0) { + parseErrorType = MISM_PARENTH; + return Ind; + } + sws(Function, ++Ind); + c = Function[Ind]; + } -// If we get here, we have a legal operand and now a legal operator or -// end of string must follow + // If we get here, we have a legal operand and now a legal operator or + // end of string must follow - // Check for EOS - if(c==0) break; // The only way to end the checking loop without error - // Check for operator - if(!IsOperator(c) && - (c != ',' || functionParenthDepth.empty() || - functionParenthDepth.back() != ParenthCnt)) - { parseErrorType=EXPECT_OPERATOR; return Ind; } + // Check for EOS + if (c == 0) { + break; // The only way to end the checking loop without error + } + // Check for operator + if (!IsOperator(c) && + (c != ',' || functionParenthDepth.empty() || functionParenthDepth.back() != ParenthCnt)) { + parseErrorType = EXPECT_OPERATOR; + return Ind; + } -// If we get here, we have an operand and an operator; the next loop will -// check for another operand (must appear) - ++Ind; - } // while + // If we get here, we have an operand and an operator; the next loop will + // check for another operand (must appear) + ++Ind; + } // while - // Check that all opened parentheses are also closed - if(ParenthCnt>0) { parseErrorType=MISSING_PARENTH; return Ind; } + // Check that all opened parentheses are also closed + if (ParenthCnt > 0) { + parseErrorType = MISSING_PARENTH; + return Ind; + } -// The string is ok - parseErrorType=FP_NO_ERROR; - return -1; + // The string is ok + parseErrorType = FP_NO_ERROR; + return -1; } - // Compile function string to bytecode // ----------------------------------- -bool FunctionParser::Compile(const char* Function) -{ - if(data->ByteCode) { delete[] data->ByteCode; data->ByteCode=0; } - if(data->Immed) { delete[] data->Immed; data->Immed=0; } - if(data->Stack) { delete[] data->Stack; data->Stack=0; } - - vector byteCode; byteCode.reserve(1024); - tempByteCode = &byteCode; - - vector immed; immed.reserve(1024); - tempImmed = &immed; - - data->StackSize = StackPtr = 0; - - CompileExpression(Function, 0); - if(parseErrorType != FP_NO_ERROR) return false; +bool FunctionParser::Compile(const char *Function) +{ + if (data->ByteCode) { + delete[] data->ByteCode; + data->ByteCode = 0; + } + if (data->Immed) { + delete[] data->Immed; + data->Immed = 0; + } + if (data->Stack) { + delete[] data->Stack; + data->Stack = 0; + } + + vector byteCode; + byteCode.reserve(1024); + tempByteCode = &byteCode; + + vector immed; + immed.reserve(1024); + tempImmed = &immed; + + data->StackSize = StackPtr = 0; + + CompileExpression(Function, 0); + if (parseErrorType != FP_NO_ERROR) { + return false; + } - data->ByteCodeSize = byteCode.size(); - data->ImmedSize = immed.size(); + data->ByteCodeSize = byteCode.size(); + data->ImmedSize = immed.size(); - if(data->ByteCodeSize) - { - data->ByteCode = new unsigned[data->ByteCodeSize]; - memcpy(data->ByteCode, &byteCode[0], - sizeof(unsigned)*data->ByteCodeSize); - } - if(data->ImmedSize) - { - data->Immed = new double[data->ImmedSize]; - memcpy(data->Immed, &immed[0], - sizeof(double)*data->ImmedSize); - } - if(data->StackSize) - data->Stack = new double[data->StackSize]; + if (data->ByteCodeSize) { + data->ByteCode = new unsigned[data->ByteCodeSize]; + memcpy(data->ByteCode, &byteCode[0], sizeof(unsigned) * data->ByteCodeSize); + } + if (data->ImmedSize) { + data->Immed = new double[data->ImmedSize]; + memcpy(data->Immed, &immed[0], sizeof(double) * data->ImmedSize); + } + if (data->StackSize) { + data->Stack = new double[data->StackSize]; + } - return true; + return true; } +inline void FunctionParser::AddCompiledByte(unsigned c) { tempByteCode->push_back(c); } -inline void FunctionParser::AddCompiledByte(unsigned c) -{ - tempByteCode->push_back(c); -} - -inline void FunctionParser::AddImmediate(double i) -{ - tempImmed->push_back(i); -} +inline void FunctionParser::AddImmediate(double i) { tempImmed->push_back(i); } inline void FunctionParser::AddFunctionOpcode(unsigned opcode) { - if(data->useDegreeConversion) - switch(opcode) - { - case cCos: - case cCosh: - case cCot: - case cCsc: - case cSec: - case cSin: - case cSinh: - case cTan: - case cTanh: - AddCompiledByte(cRad); - } - - AddCompiledByte(opcode); - - if(data->useDegreeConversion) - switch(opcode) - { - case cAcos: + if (data->useDegreeConversion) { + switch (opcode) { + case cCos: + case cCosh: + case cCot: + case cCsc: + case cSec: + case cSin: + case cSinh: + case cTan: + case cTanh: + AddCompiledByte(cRad); + } + } + + AddCompiledByte(opcode); + + if (data->useDegreeConversion) { + switch (opcode) { + case cAcos: #ifndef NO_ASINH - case cAcosh: - case cAsinh: - case cAtanh: + case cAcosh: + case cAsinh: + case cAtanh: #endif - case cAsin: - case cAtan: - case cAtan2: - AddCompiledByte(cDeg); - } + case cAsin: + case cAtan: + case cAtan2: + AddCompiledByte(cDeg); + } + } } inline void FunctionParser::incStackPtr() { - if(++StackPtr > data->StackSize) ++(data->StackSize); + if (++StackPtr > data->StackSize) { + ++(data->StackSize); + } } - // Compile if() -int FunctionParser::CompileIf(const char* F, int ind) +int FunctionParser::CompileIf(const char *F, int ind) { - int ind2 = CompileExpression(F, ind, true); // condition - sws(F, ind2); - if(F[ind2] != ',') { parseErrorType=ILL_PARAMS_AMOUNT; return ind2; } - AddCompiledByte(cIf); - unsigned curByteCodeSize = tempByteCode->size(); - AddCompiledByte(0); // Jump index; to be set later - AddCompiledByte(0); // Immed jump index; to be set later - - --StackPtr; - - ind2 = CompileExpression(F, ind2+1, true); // then - sws(F, ind2); - if(F[ind2] != ',') { parseErrorType=ILL_PARAMS_AMOUNT; return ind2; } - AddCompiledByte(cJump); - unsigned curByteCodeSize2 = tempByteCode->size(); - unsigned curImmedSize2 = tempImmed->size(); - AddCompiledByte(0); // Jump index; to be set later - AddCompiledByte(0); // Immed jump index; to be set later - - --StackPtr; - - ind2 = CompileExpression(F, ind2+1, true); // else - sws(F, ind2); - if(F[ind2] != ')') { parseErrorType=ILL_PARAMS_AMOUNT; return ind2; } + int ind2 = CompileExpression(F, ind, true); // condition + sws(F, ind2); + if (F[ind2] != ',') { + parseErrorType = ILL_PARAMS_AMOUNT; + return ind2; + } + AddCompiledByte(cIf); + unsigned curByteCodeSize = tempByteCode->size(); + AddCompiledByte(0); // Jump index; to be set later + AddCompiledByte(0); // Immed jump index; to be set later + + --StackPtr; + + ind2 = CompileExpression(F, ind2 + 1, true); // then + sws(F, ind2); + if (F[ind2] != ',') { + parseErrorType = ILL_PARAMS_AMOUNT; + return ind2; + } + AddCompiledByte(cJump); + unsigned curByteCodeSize2 = tempByteCode->size(); + unsigned curImmedSize2 = tempImmed->size(); + AddCompiledByte(0); // Jump index; to be set later + AddCompiledByte(0); // Immed jump index; to be set later + + --StackPtr; + + ind2 = CompileExpression(F, ind2 + 1, true); // else + sws(F, ind2); + if (F[ind2] != ')') { + parseErrorType = ILL_PARAMS_AMOUNT; + return ind2; + } - // Set jump indices - (*tempByteCode)[curByteCodeSize] = curByteCodeSize2+1; - (*tempByteCode)[curByteCodeSize+1] = curImmedSize2; - (*tempByteCode)[curByteCodeSize2] = tempByteCode->size()-1; - (*tempByteCode)[curByteCodeSize2+1] = tempImmed->size(); + // Set jump indices + (*tempByteCode)[curByteCodeSize] = curByteCodeSize2 + 1; + (*tempByteCode)[curByteCodeSize + 1] = curImmedSize2; + (*tempByteCode)[curByteCodeSize2] = tempByteCode->size() - 1; + (*tempByteCode)[curByteCodeSize2 + 1] = tempImmed->size(); - return ind2+1; + return ind2 + 1; } -int FunctionParser::CompileFunctionParams(const char* F, int ind, - unsigned requiredParams) +int FunctionParser::CompileFunctionParams(const char *F, int ind, unsigned requiredParams) { - unsigned curStackPtr = StackPtr; - int ind2 = CompileExpression(F, ind); + unsigned curStackPtr = StackPtr; + int ind2 = CompileExpression(F, ind); - if(StackPtr != curStackPtr+requiredParams) - { parseErrorType=ILL_PARAMS_AMOUNT; return ind; } + if (StackPtr != curStackPtr + requiredParams) { + parseErrorType = ILL_PARAMS_AMOUNT; + return ind; + } - StackPtr -= requiredParams - 1; - sws(F, ind2); - return ind2+1; // F[ind2] is ')' + StackPtr -= requiredParams - 1; + sws(F, ind2); + return ind2 + 1; // F[ind2] is ')' } // Compiles element -int FunctionParser::CompileElement(const char* F, int ind) +int FunctionParser::CompileElement(const char *F, int ind) { + sws(F, ind); + char c = F[ind]; + + if (c == '(') { + ind = CompileExpression(F, ind + 1); sws(F, ind); - char c = F[ind]; + return ind + 1; // F[ind] is ')' + } + + if (isdigit(c) || c == '.' /*|| c=='-'*/) // Number + { + const char *startPtr = &F[ind]; + char *endPtr; + double val = strtod(startPtr, &endPtr); + AddImmediate(val); + AddCompiledByte(cImmed); + incStackPtr(); + return ind + (endPtr - startPtr); + } + + if (isalpha(c) || c == '_') // Function, variable or constant + { + const FuncDefinition *func = FindFunction(F + ind); + if (func) // is function + { + int ind2 = ind + func->nameLength; + sws(F, ind2); // F[ind2] is '(' + if (strcmp(func->name, "if") == 0) // "if" is a special case + { + return CompileIf(F, ind2 + 1); + } - if(c == '(') - { - ind = CompileExpression(F, ind+1); - sws(F, ind); - return ind+1; // F[ind] is ')' +#ifndef DISABLE_EVAL + unsigned requiredParams = + strcmp(func->name, "eval") == 0 ? data->Variables.size() : func->params; +#else + unsigned requiredParams = func->params; +#endif + ind2 = CompileFunctionParams(F, ind2 + 1, requiredParams); + AddFunctionOpcode(func->opcode); + return ind2; // F[ind2-1] is ')' } - if(isdigit(c) || c=='.' /*|| c=='-'*/) // Number + Data::VarMap_t::const_iterator vIter = FindVariable(F + ind, data->Variables); + if (vIter != data->Variables.end()) // is variable { - const char* startPtr = &F[ind]; - char* endPtr; - double val = strtod(startPtr, &endPtr); - AddImmediate(val); - AddCompiledByte(cImmed); - incStackPtr(); - return ind+(endPtr-startPtr); + AddCompiledByte(vIter->second); + incStackPtr(); + return ind + vIter->first.size(); } - if(isalpha(c) || c == '_') // Function, variable or constant + Data::ConstMap_t::const_iterator cIter = FindConstant(F + ind); + if (cIter != data->Constants.end()) // is constant { - const FuncDefinition* func = FindFunction(F+ind); - if(func) // is function - { - int ind2 = ind + func->nameLength; - sws(F, ind2); // F[ind2] is '(' - if(strcmp(func->name, "if") == 0) // "if" is a special case - { - return CompileIf(F, ind2+1); - } - -#ifndef DISABLE_EVAL - unsigned requiredParams = - strcmp(func->name, "eval") == 0 ? - data->Variables.size() : func->params; -#else - unsigned requiredParams = func->params; -#endif - ind2 = CompileFunctionParams(F, ind2+1, requiredParams); - AddFunctionOpcode(func->opcode); - return ind2; // F[ind2-1] is ')' - } - - Data::VarMap_t::const_iterator vIter = - FindVariable(F+ind, data->Variables); - if(vIter != data->Variables.end()) // is variable - { - AddCompiledByte(vIter->second); - incStackPtr(); - return ind + vIter->first.size(); - } - - Data::ConstMap_t::const_iterator cIter = FindConstant(F+ind); - if(cIter != data->Constants.end()) // is constant - { - AddImmediate(cIter->second); - AddCompiledByte(cImmed); - incStackPtr(); - return ind + cIter->first.size(); - } + AddImmediate(cIter->second); + AddCompiledByte(cImmed); + incStackPtr(); + return ind + cIter->first.size(); + } - Data::VarMap_t::const_iterator fIter = - FindVariable(F+ind, data->FuncPtrNames); - if(fIter != data->FuncPtrNames.end()) // is user-defined func pointer - { - unsigned index = fIter->second; + Data::VarMap_t::const_iterator fIter = FindVariable(F + ind, data->FuncPtrNames); + if (fIter != data->FuncPtrNames.end()) // is user-defined func pointer + { + unsigned index = fIter->second; - int ind2 = ind + fIter->first.length(); - sws(F, ind2); // F[ind2] is '(' + int ind2 = ind + fIter->first.length(); + sws(F, ind2); // F[ind2] is '(' - ind2 = CompileFunctionParams(F, ind2+1, - data->FuncPtrs[index].params); + ind2 = CompileFunctionParams(F, ind2 + 1, data->FuncPtrs[index].params); - AddCompiledByte(cFCall); - AddCompiledByte(index); - return ind2; - } + AddCompiledByte(cFCall); + AddCompiledByte(index); + return ind2; + } - Data::VarMap_t::const_iterator pIter = - FindVariable(F+ind, data->FuncParserNames); - if(pIter != data->FuncParserNames.end()) // is user-defined func parser - { - unsigned index = pIter->second; + Data::VarMap_t::const_iterator pIter = FindVariable(F + ind, data->FuncParserNames); + if (pIter != data->FuncParserNames.end()) // is user-defined func parser + { + unsigned index = pIter->second; - int ind2 = ind + pIter->first.length(); - sws(F, ind2); // F[ind2] is '(' + int ind2 = ind + pIter->first.length(); + sws(F, ind2); // F[ind2] is '(' - ind2 = CompileFunctionParams - (F, ind2+1, data->FuncParsers[index]->data->varAmount); + ind2 = CompileFunctionParams(F, ind2 + 1, data->FuncParsers[index]->data->varAmount); - AddCompiledByte(cPCall); - AddCompiledByte(index); - return ind2; - } + AddCompiledByte(cPCall); + AddCompiledByte(index); + return ind2; } + } - parseErrorType = UNEXPECTED_ERROR; - return ind; + parseErrorType = UNEXPECTED_ERROR; + return ind; } // Compiles '^' -int FunctionParser::CompilePow(const char* F, int ind) +int FunctionParser::CompilePow(const char *F, int ind) { - int ind2 = CompileElement(F, ind); - sws(F, ind2); + int ind2 = CompileElement(F, ind); + sws(F, ind2); - while(F[ind2] == '^') - { - ind2 = CompileUnaryMinus(F, ind2+1); - sws(F, ind2); - AddCompiledByte(cPow); - --StackPtr; - } + while (F[ind2] == '^') { + ind2 = CompileUnaryMinus(F, ind2 + 1); + sws(F, ind2); + AddCompiledByte(cPow); + --StackPtr; + } - return ind2; + return ind2; } // Compiles unary '-' -int FunctionParser::CompileUnaryMinus(const char* F, int ind) +int FunctionParser::CompileUnaryMinus(const char *F, int ind) { - sws(F, ind); - if(F[ind] == '-') - { - int ind2 = ind+1; - sws(F, ind2); - ind2 = CompilePow(F, ind2); - sws(F, ind2); - - // if we are negating a constant, negate the constant itself: - if(tempByteCode->back() == cImmed) - tempImmed->back() = -tempImmed->back(); + sws(F, ind); + if (F[ind] == '-') { + int ind2 = ind + 1; + sws(F, ind2); + ind2 = CompilePow(F, ind2); + sws(F, ind2); - // if we are negating a negation, we can remove both: - else if(tempByteCode->back() == cNeg) - tempByteCode->pop_back(); + // if we are negating a constant, negate the constant itself: + if (tempByteCode->back() == cImmed) { + tempImmed->back() = -tempImmed->back(); + } - else - AddCompiledByte(cNeg); + // if we are negating a negation, we can remove both: + else if (tempByteCode->back() == cNeg) { + tempByteCode->pop_back(); + } - return ind2; + else { + AddCompiledByte(cNeg); } - int ind2 = CompilePow(F, ind); - sws(F, ind2); return ind2; + } + + int ind2 = CompilePow(F, ind); + sws(F, ind2); + return ind2; } // Compiles '*', '/' and '%' -int FunctionParser::CompileMult(const char* F, int ind) +int FunctionParser::CompileMult(const char *F, int ind) { - int ind2 = CompileUnaryMinus(F, ind); - sws(F, ind2); - char op; + int ind2 = CompileUnaryMinus(F, ind); + sws(F, ind2); + char op; - while((op = F[ind2]) == '*' || op == '/' || op == '%') - { - ind2 = CompileUnaryMinus(F, ind2+1); - sws(F, ind2); - switch(op) - { - case '*': AddCompiledByte(cMul); break; - case '/': AddCompiledByte(cDiv); break; - case '%': AddCompiledByte(cMod); break; - } - --StackPtr; + while ((op = F[ind2]) == '*' || op == '/' || op == '%') { + ind2 = CompileUnaryMinus(F, ind2 + 1); + sws(F, ind2); + switch (op) { + case '*': + AddCompiledByte(cMul); + break; + case '/': + AddCompiledByte(cDiv); + break; + case '%': + AddCompiledByte(cMod); + break; } + --StackPtr; + } - return ind2; + return ind2; } // Compiles '+' and '-' -int FunctionParser::CompileAddition(const char* F, int ind) +int FunctionParser::CompileAddition(const char *F, int ind) { - int ind2 = CompileMult(F, ind); - sws(F, ind2); - char op; + int ind2 = CompileMult(F, ind); + sws(F, ind2); + char op; - while((op = F[ind2]) == '+' || op == '-') - { - ind2 = CompileMult(F, ind2+1); - sws(F, ind2); - AddCompiledByte(op=='+' ? cAdd : cSub); - --StackPtr; - } + while ((op = F[ind2]) == '+' || op == '-') { + ind2 = CompileMult(F, ind2 + 1); + sws(F, ind2); + AddCompiledByte(op == '+' ? cAdd : cSub); + --StackPtr; + } - return ind2; + return ind2; } // Compiles '=', '<' and '>' -int FunctionParser::CompileComparison(const char* F, int ind) +int FunctionParser::CompileComparison(const char *F, int ind) { - int ind2 = CompileAddition(F, ind); - sws(F, ind2); - char op; + int ind2 = CompileAddition(F, ind); + sws(F, ind2); + char op; - while((op = F[ind2]) == '=' || op == '<' || op == '>') - { - ind2 = CompileAddition(F, ind2+1); - sws(F, ind2); - switch(op) - { - case '=': AddCompiledByte(cEqual); break; - case '<': AddCompiledByte(cLess); break; - case '>': AddCompiledByte(cGreater); break; - } - --StackPtr; + while ((op = F[ind2]) == '=' || op == '<' || op == '>') { + ind2 = CompileAddition(F, ind2 + 1); + sws(F, ind2); + switch (op) { + case '=': + AddCompiledByte(cEqual); + break; + case '<': + AddCompiledByte(cLess); + break; + case '>': + AddCompiledByte(cGreater); + break; } + --StackPtr; + } - return ind2; + return ind2; } // Compiles '&' -int FunctionParser::CompileAnd(const char* F, int ind) +int FunctionParser::CompileAnd(const char *F, int ind) { - int ind2 = CompileComparison(F, ind); - sws(F, ind2); + int ind2 = CompileComparison(F, ind); + sws(F, ind2); - while(F[ind2] == '&') - { - ind2 = CompileComparison(F, ind2+1); - sws(F, ind2); - AddCompiledByte(cAnd); - --StackPtr; - } + while (F[ind2] == '&') { + ind2 = CompileComparison(F, ind2 + 1); + sws(F, ind2); + AddCompiledByte(cAnd); + --StackPtr; + } - return ind2; + return ind2; } // Compiles '|' -int FunctionParser::CompileOr(const char* F, int ind) +int FunctionParser::CompileOr(const char *F, int ind) { - int ind2 = CompileAnd(F, ind); - sws(F, ind2); + int ind2 = CompileAnd(F, ind); + sws(F, ind2); - while(F[ind2] == '|') - { - ind2 = CompileAnd(F, ind2+1); - sws(F, ind2); - AddCompiledByte(cOr); - --StackPtr; - } + while (F[ind2] == '|') { + ind2 = CompileAnd(F, ind2 + 1); + sws(F, ind2); + AddCompiledByte(cOr); + --StackPtr; + } - return ind2; + return ind2; } // Compiles ',' -int FunctionParser::CompileExpression(const char* F, int ind, bool stopAtComma) +int FunctionParser::CompileExpression(const char *F, int ind, bool stopAtComma) { - int ind2 = CompileOr(F, ind); - sws(F, ind2); + int ind2 = CompileOr(F, ind); + sws(F, ind2); - if(stopAtComma) return ind2; + if (stopAtComma) { + return ind2; + } - while(F[ind2] == ',') - { - ind2 = CompileOr(F, ind2+1); - sws(F, ind2); - } + while (F[ind2] == ',') { + ind2 = CompileOr(F, ind2 + 1); + sws(F, ind2); + } - return ind2; + return ind2; } - // Return parse error message // -------------------------- -const char* FunctionParser::ErrorMsg() const +const char *FunctionParser::ErrorMsg() const { - if(parseErrorType != FP_NO_ERROR) return ParseErrorMessage[parseErrorType]; - return 0; + if (parseErrorType != FP_NO_ERROR) { + return ParseErrorMessage[parseErrorType]; + } + return 0; } //--------------------------------------------------------------------------- // Function evaluation //--------------------------------------------------------------------------- //=========================================================================== -namespace -{ - inline int doubleToInt(double d) - { - return d<0 ? -int((-d)+.5) : int(d+.5); - } - - inline double Min(double d1, double d2) - { - return d1d2 ? d1 : d2; - } - - - inline double DegreesToRadians(double degrees) - { - return degrees*(M_PI/180.0); - } - inline double RadiansToDegrees(double radians) - { - return radians*(180.0/M_PI); - } -} - -double FunctionParser::Eval(const double* Vars) -{ - const unsigned* const ByteCode = data->ByteCode; - const double* const Immed = data->Immed; - double* const Stack = data->Stack; - const unsigned ByteCodeSize = data->ByteCodeSize; - unsigned IP, DP=0; - int SP=-1; - - for(IP=0; IP 1) - { evalErrorType=4; return 0; } - Stack[SP] = acos(Stack[SP]); break; +namespace { +inline int doubleToInt(double d) { return d < 0 ? -int((-d) + .5) : int(d + .5); } + +inline double Min(double d1, double d2) { return d1 < d2 ? d1 : d2; } +inline double Max(double d1, double d2) { return d1 > d2 ? d1 : d2; } + +inline double DegreesToRadians(double degrees) { return degrees * (M_PI / 180.0); } +inline double RadiansToDegrees(double radians) { return radians * (180.0 / M_PI); } +} // namespace + +double FunctionParser::Eval(const double *Vars) +{ + const unsigned *const ByteCode = data->ByteCode; + const double *const Immed = data->Immed; + double *const Stack = data->Stack; + const unsigned ByteCodeSize = data->ByteCodeSize; + unsigned IP, DP = 0; + int SP = -1; + + for (IP = 0; IP < ByteCodeSize; ++IP) { + switch (ByteCode[IP]) { + // Functions: + case cAbs: + Stack[SP] = fabs(Stack[SP]); + break; + case cAcos: + if (Stack[SP] < -1 || Stack[SP] > 1) { + evalErrorType = 4; + return 0; + } + Stack[SP] = acos(Stack[SP]); + break; #ifndef NO_ASINH - case cAcosh: Stack[SP] = acosh(Stack[SP]); break; + case cAcosh: + Stack[SP] = acosh(Stack[SP]); + break; #endif - case cAsin: if(Stack[SP] < -1 || Stack[SP] > 1) - { evalErrorType=4; return 0; } - Stack[SP] = asin(Stack[SP]); break; + case cAsin: + if (Stack[SP] < -1 || Stack[SP] > 1) { + evalErrorType = 4; + return 0; + } + Stack[SP] = asin(Stack[SP]); + break; #ifndef NO_ASINH - case cAsinh: Stack[SP] = asinh(Stack[SP]); break; + case cAsinh: + Stack[SP] = asinh(Stack[SP]); + break; #endif - case cAtan: Stack[SP] = atan(Stack[SP]); break; - case cAtan2: Stack[SP-1] = atan2(Stack[SP-1], Stack[SP]); - --SP; break; + case cAtan: + Stack[SP] = atan(Stack[SP]); + break; + case cAtan2: + Stack[SP - 1] = atan2(Stack[SP - 1], Stack[SP]); + --SP; + break; #ifndef NO_ASINH - case cAtanh: Stack[SP] = atanh(Stack[SP]); break; + case cAtanh: + Stack[SP] = atanh(Stack[SP]); + break; #endif - case cCeil: Stack[SP] = ceil(Stack[SP]); break; - case cCos: Stack[SP] = cos(Stack[SP]); break; - case cCosh: Stack[SP] = cosh(Stack[SP]); break; - - case cCot: - { - double t = tan(Stack[SP]); - if(t == 0) { evalErrorType=1; return 0; } - Stack[SP] = 1/t; break; - } - case cCsc: - { - double s = sin(Stack[SP]); - if(s == 0) { evalErrorType=1; return 0; } - Stack[SP] = 1/s; break; - } - + case cCeil: + Stack[SP] = ceil(Stack[SP]); + break; + case cCos: + Stack[SP] = cos(Stack[SP]); + break; + case cCosh: + Stack[SP] = cosh(Stack[SP]); + break; + + case cCot: { + double t = tan(Stack[SP]); + if (t == 0) { + evalErrorType = 1; + return 0; + } + Stack[SP] = 1 / t; + break; + } + case cCsc: { + double s = sin(Stack[SP]); + if (s == 0) { + evalErrorType = 1; + return 0; + } + Stack[SP] = 1 / s; + break; + } #ifndef DISABLE_EVAL - case cEval: - { - data->Stack = new double[data->StackSize]; - double retVal = Eval(&Stack[SP-data->varAmount+1]); - delete[] data->Stack; - data->Stack = Stack; - SP -= data->varAmount-1; - Stack[SP] = retVal; - break; - } + case cEval: { + data->Stack = new double[data->StackSize]; + double retVal = Eval(&Stack[SP - data->varAmount + 1]); + delete[] data->Stack; + data->Stack = Stack; + SP -= data->varAmount - 1; + Stack[SP] = retVal; + break; + } #endif - case cExp: Stack[SP] = exp(Stack[SP]); break; - case cFloor: Stack[SP] = floor(Stack[SP]); break; - - case cIf: - { - unsigned jumpAddr = ByteCode[++IP]; - unsigned immedAddr = ByteCode[++IP]; - if(doubleToInt(Stack[SP]) == 0) - { - IP = jumpAddr; - DP = immedAddr; - } - --SP; break; - } - - case cInt: Stack[SP] = floor(Stack[SP]+.5); break; - case cLog: if(Stack[SP] <= 0) { evalErrorType=3; return 0; } - Stack[SP] = log(Stack[SP]); break; - case cLog10: if(Stack[SP] <= 0) { evalErrorType=3; return 0; } - Stack[SP] = log10(Stack[SP]); break; - case cMax: Stack[SP-1] = Max(Stack[SP-1], Stack[SP]); - --SP; break; - case cMin: Stack[SP-1] = Min(Stack[SP-1], Stack[SP]); - --SP; break; - case cSec: - { - double c = cos(Stack[SP]); - if(c == 0) { evalErrorType=1; return 0; } - Stack[SP] = 1/c; break; - } - case cSin: Stack[SP] = sin(Stack[SP]); break; - case cSinh: Stack[SP] = sinh(Stack[SP]); break; - case cSqrt: if(Stack[SP] < 0) { evalErrorType=2; return 0; } - Stack[SP] = sqrt(Stack[SP]); break; - case cTan: Stack[SP] = tan(Stack[SP]); break; - case cTanh: Stack[SP] = tanh(Stack[SP]); break; - - -// Misc: - case cImmed: Stack[++SP] = Immed[DP++]; break; - case cJump: DP = ByteCode[IP+2]; - IP = ByteCode[IP+1]; - break; - -// Operators: - case cNeg: Stack[SP] = -Stack[SP]; break; - case cAdd: Stack[SP-1] += Stack[SP]; --SP; break; - case cSub: Stack[SP-1] -= Stack[SP]; --SP; break; - case cMul: Stack[SP-1] *= Stack[SP]; --SP; break; - case cDiv: if(Stack[SP] == 0) { evalErrorType=1; return 0; } - Stack[SP-1] /= Stack[SP]; --SP; break; - case cMod: if(Stack[SP] == 0) { evalErrorType=1; return 0; } - Stack[SP-1] = fmod(Stack[SP-1], Stack[SP]); - --SP; break; - case cPow: Stack[SP-1] = pow(Stack[SP-1], Stack[SP]); - --SP; break; - - case cEqual: Stack[SP-1] = (Stack[SP-1] == Stack[SP]); - --SP; break; - case cLess: Stack[SP-1] = (Stack[SP-1] < Stack[SP]); - --SP; break; - case cGreater: Stack[SP-1] = (Stack[SP-1] > Stack[SP]); - --SP; break; - case cAnd: Stack[SP-1] = - (doubleToInt(Stack[SP-1]) && - doubleToInt(Stack[SP])); - --SP; break; - case cOr: Stack[SP-1] = - (doubleToInt(Stack[SP-1]) || - doubleToInt(Stack[SP])); - --SP; break; - -// Degrees-radians conversion: - case cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break; - case cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break; - -// User-defined function calls: - case cFCall: - { - unsigned index = ByteCode[++IP]; - unsigned params = data->FuncPtrs[index].params; - double retVal = - data->FuncPtrs[index].ptr(&Stack[SP-params+1]); - SP -= params-1; - Stack[SP] = retVal; - break; - } - - case cPCall: - { - unsigned index = ByteCode[++IP]; - unsigned params = data->FuncParsers[index]->data->varAmount; - double retVal = - data->FuncParsers[index]->Eval(&Stack[SP-params+1]); - SP -= params-1; - Stack[SP] = retVal; - break; - } - + case cExp: + Stack[SP] = exp(Stack[SP]); + break; + case cFloor: + Stack[SP] = floor(Stack[SP]); + break; + + case cIf: { + unsigned jumpAddr = ByteCode[++IP]; + unsigned immedAddr = ByteCode[++IP]; + if (doubleToInt(Stack[SP]) == 0) { + IP = jumpAddr; + DP = immedAddr; + } + --SP; + break; + } + + case cInt: + Stack[SP] = floor(Stack[SP] + .5); + break; + case cLog: + if (Stack[SP] <= 0) { + evalErrorType = 3; + return 0; + } + Stack[SP] = log(Stack[SP]); + break; + case cLog10: + if (Stack[SP] <= 0) { + evalErrorType = 3; + return 0; + } + Stack[SP] = log10(Stack[SP]); + break; + case cMax: + Stack[SP - 1] = Max(Stack[SP - 1], Stack[SP]); + --SP; + break; + case cMin: + Stack[SP - 1] = Min(Stack[SP - 1], Stack[SP]); + --SP; + break; + case cSec: { + double c = cos(Stack[SP]); + if (c == 0) { + evalErrorType = 1; + return 0; + } + Stack[SP] = 1 / c; + break; + } + case cSin: + Stack[SP] = sin(Stack[SP]); + break; + case cSinh: + Stack[SP] = sinh(Stack[SP]); + break; + case cSqrt: + if (Stack[SP] < 0) { + evalErrorType = 2; + return 0; + } + Stack[SP] = sqrt(Stack[SP]); + break; + case cTan: + Stack[SP] = tan(Stack[SP]); + break; + case cTanh: + Stack[SP] = tanh(Stack[SP]); + break; + + // Misc: + case cImmed: + Stack[++SP] = Immed[DP++]; + break; + case cJump: + DP = ByteCode[IP + 2]; + IP = ByteCode[IP + 1]; + break; + + // Operators: + case cNeg: + Stack[SP] = -Stack[SP]; + break; + case cAdd: + Stack[SP - 1] += Stack[SP]; + --SP; + break; + case cSub: + Stack[SP - 1] -= Stack[SP]; + --SP; + break; + case cMul: + Stack[SP - 1] *= Stack[SP]; + --SP; + break; + case cDiv: + if (Stack[SP] == 0) { + evalErrorType = 1; + return 0; + } + Stack[SP - 1] /= Stack[SP]; + --SP; + break; + case cMod: + if (Stack[SP] == 0) { + evalErrorType = 1; + return 0; + } + Stack[SP - 1] = fmod(Stack[SP - 1], Stack[SP]); + --SP; + break; + case cPow: + Stack[SP - 1] = pow(Stack[SP - 1], Stack[SP]); + --SP; + break; + + case cEqual: + Stack[SP - 1] = (Stack[SP - 1] == Stack[SP]); + --SP; + break; + case cLess: + Stack[SP - 1] = (Stack[SP - 1] < Stack[SP]); + --SP; + break; + case cGreater: + Stack[SP - 1] = (Stack[SP - 1] > Stack[SP]); + --SP; + break; + case cAnd: + Stack[SP - 1] = (doubleToInt(Stack[SP - 1]) && doubleToInt(Stack[SP])); + --SP; + break; + case cOr: + Stack[SP - 1] = (doubleToInt(Stack[SP - 1]) || doubleToInt(Stack[SP])); + --SP; + break; + + // Degrees-radians conversion: + case cDeg: + Stack[SP] = RadiansToDegrees(Stack[SP]); + break; + case cRad: + Stack[SP] = DegreesToRadians(Stack[SP]); + break; + + // User-defined function calls: + case cFCall: { + unsigned index = ByteCode[++IP]; + unsigned params = data->FuncPtrs[index].params; + double retVal = data->FuncPtrs[index].ptr(&Stack[SP - params + 1]); + SP -= params - 1; + Stack[SP] = retVal; + break; + } + + case cPCall: { + unsigned index = ByteCode[++IP]; + unsigned params = data->FuncParsers[index]->data->varAmount; + double retVal = data->FuncParsers[index]->Eval(&Stack[SP - params + 1]); + SP -= params - 1; + Stack[SP] = retVal; + break; + } #ifdef SUPPORT_OPTIMIZER - case cVar: break; // Paranoia. These should never exist - case cDup: Stack[SP+1] = Stack[SP]; ++SP; break; - case cInv: - if(Stack[SP] == 0.0) { evalErrorType=1; return 0; } - Stack[SP] = 1.0/Stack[SP]; - break; + case cVar: + break; // Paranoia. These should never exist + case cDup: + Stack[SP + 1] = Stack[SP]; + ++SP; + break; + case cInv: + if (Stack[SP] == 0.0) { + evalErrorType = 1; + return 0; + } + Stack[SP] = 1.0 / Stack[SP]; + break; #endif -// Variables: - default: - Stack[++SP] = Vars[ByteCode[IP]-VarBegin]; - } + // Variables: + default: + Stack[++SP] = Vars[ByteCode[IP] - VarBegin]; } + } - evalErrorType=0; - return Stack[SP]; + evalErrorType = 0; + return Stack[SP]; } - #ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT -namespace -{ - inline void printHex(std::ostream& dest, unsigned n) - { - dest.width(8); dest.fill('0'); hex(dest); //uppercase(dest); - dest << n; - } -} - -void FunctionParser::PrintByteCode(std::ostream& dest) const -{ - const unsigned* const ByteCode = data->ByteCode; - const double* const Immed = data->Immed; - - for(unsigned IP=0, DP=0; IPByteCodeSize; ++IP) - { - printHex(dest, IP); - dest << ": "; - - unsigned opcode = ByteCode[IP]; - - switch(opcode) - { - case cIf: - dest << "jz\t"; - printHex(dest, ByteCode[IP+1]+1); - dest << endl; - IP += 2; - break; - - case cJump: - dest << "jump\t"; - printHex(dest, ByteCode[IP+1]+1); - dest << endl; - IP += 2; - break; - case cImmed: - dest.precision(10); - dest << "push\t" << Immed[DP++] << endl; - break; - - case cFCall: - { - unsigned index = ByteCode[++IP]; - Data::VarMap_t::const_iterator iter = - data->FuncPtrNames.begin(); - while(iter->second != index) ++iter; - dest << "call\t" << iter->first << endl; - break; - } - - case cPCall: - { - unsigned index = ByteCode[++IP]; - Data::VarMap_t::const_iterator iter = - data->FuncParserNames.begin(); - while(iter->second != index) ++iter; - dest << "call\t" << iter->first << endl; - break; - } - - default: - if(opcode < VarBegin) - { - string n; - switch(opcode) - { - case cNeg: n = "neg"; break; - case cAdd: n = "add"; break; - case cSub: n = "sub"; break; - case cMul: n = "mul"; break; - case cDiv: n = "div"; break; - case cMod: n = "mod"; break; - case cPow: n = "pow"; break; - case cEqual: n = "eq"; break; - case cLess: n = "lt"; break; - case cGreater: n = "gt"; break; - case cAnd: n = "and"; break; - case cOr: n = "or"; break; - case cDeg: n = "deg"; break; - case cRad: n = "rad"; break; +namespace { +inline void printHex(std::ostream &dest, unsigned n) +{ + dest.width(8); + dest.fill('0'); + hex(dest); // uppercase(dest); + dest << n; +} +} // namespace + +void FunctionParser::PrintByteCode(std::ostream &dest) const +{ + const unsigned *const ByteCode = data->ByteCode; + const double *const Immed = data->Immed; + + for (unsigned IP = 0, DP = 0; IP < data->ByteCodeSize; ++IP) { + printHex(dest, IP); + dest << ": "; + + unsigned opcode = ByteCode[IP]; + + switch (opcode) { + case cIf: + dest << "jz\t"; + printHex(dest, ByteCode[IP + 1] + 1); + dest << endl; + IP += 2; + break; + + case cJump: + dest << "jump\t"; + printHex(dest, ByteCode[IP + 1] + 1); + dest << endl; + IP += 2; + break; + case cImmed: + dest.precision(10); + dest << "push\t" << Immed[DP++] << endl; + break; + + case cFCall: { + unsigned index = ByteCode[++IP]; + Data::VarMap_t::const_iterator iter = data->FuncPtrNames.begin(); + while (iter->second != index) { + ++iter; + } + dest << "call\t" << iter->first << endl; + break; + } + + case cPCall: { + unsigned index = ByteCode[++IP]; + Data::VarMap_t::const_iterator iter = data->FuncParserNames.begin(); + while (iter->second != index) { + ++iter; + } + dest << "call\t" << iter->first << endl; + break; + } + + default: + if (opcode < VarBegin) { + string n; + switch (opcode) { + case cNeg: + n = "neg"; + break; + case cAdd: + n = "add"; + break; + case cSub: + n = "sub"; + break; + case cMul: + n = "mul"; + break; + case cDiv: + n = "div"; + break; + case cMod: + n = "mod"; + break; + case cPow: + n = "pow"; + break; + case cEqual: + n = "eq"; + break; + case cLess: + n = "lt"; + break; + case cGreater: + n = "gt"; + break; + case cAnd: + n = "and"; + break; + case cOr: + n = "or"; + break; + case cDeg: + n = "deg"; + break; + case cRad: + n = "rad"; + break; #ifndef DISABLE_EVAL - case cEval: n = "call\t0"; break; + case cEval: + n = "call\t0"; + break; #endif #ifdef SUPPORT_OPTIMIZER - case cVar: n = "(var)"; break; - case cDup: n = "dup"; break; - case cInv: n = "inv"; break; + case cVar: + n = "(var)"; + break; + case cDup: + n = "dup"; + break; + case cInv: + n = "inv"; + break; #endif - default: n = Functions[opcode-cAbs].name; - } - dest << n << endl; - } - else - { - dest << "push\tVar" << opcode-VarBegin << endl; - } + default: + n = Functions[opcode - cAbs].name; } + dest << n << endl; + } + else { + dest << "push\tVar" << opcode - VarBegin << endl; + } } + } } #endif - //======================================================================== // Optimization code was contributed by Bisqwit (http://iki.fi/bisqwit/) //======================================================================== @@ -1590,66 +1745,66 @@ void FunctionParser::PrintByteCode(std::ostream& dest) const #include #include -#define CONSTANT_E 2.71828182845904509080 // exp(1) -#define CONSTANT_PI M_PI // atan2(0,-1) -#define CONSTANT_L10 2.30258509299404590109 // log(10) -#define CONSTANT_L10I 0.43429448190325176116 // 1/log(10) -#define CONSTANT_L10E CONSTANT_L10I // log10(e) -#define CONSTANT_L10EI CONSTANT_L10 // 1/log10(e) -#define CONSTANT_DR (180.0 / M_PI) // 180/pi -#define CONSTANT_RD (M_PI / 180.0) // pi/180 +#define CONSTANT_E 2.71828182845904509080 // exp(1) +#define CONSTANT_PI M_PI // atan2(0,-1) +#define CONSTANT_L10 2.30258509299404590109 // log(10) +#define CONSTANT_L10I 0.43429448190325176116 // 1/log(10) +#define CONSTANT_L10E CONSTANT_L10I // log10(e) +#define CONSTANT_L10EI CONSTANT_L10 // 1/log10(e) +#define CONSTANT_DR (180.0 / M_PI) // 180/pi +#define CONSTANT_RD (M_PI / 180.0) // pi/180 namespace { -class compres -{ - // states: 0=false, 1=true, 2=unknown +class compres { + // states: 0=false, 1=true, 2=unknown public: - compres(bool b) : state(b) {} - compres(char v) : state(v) {} - // is it? - operator bool() const { return state != 0; } - // is it not? - bool operator! () const { return state != 1; } - bool operator==(bool b) const { return (state != 0) != !b; } - bool operator!=(bool b) const { return (state != 0) != b; } + compres(bool b) : state(b) {} + compres(char v) : state(v) {} + // is it? + operator bool() const { return state != 0; } + // is it not? + bool operator!() const { return state != 1; } + bool operator==(bool b) const { return (state != 0) != !b; } + bool operator!=(bool b) const { return (state != 0) != b; } + private: - char state; + char state; }; const compres maybe = (char)2; struct CodeTree; -class SubTree -{ - CodeTree *tree; - bool sign; // Only possible when parent is cAdd or cMul +class SubTree { + CodeTree *tree; + bool sign; // Only possible when parent is cAdd or cMul + + inline void flipsign() { sign = !sign; } - inline void flipsign() { sign = !sign; } public: - SubTree(); - SubTree(double value); - SubTree(const SubTree &b); - SubTree(const CodeTree &b); + SubTree(); + SubTree(double value); + SubTree(const SubTree &b); + SubTree(const CodeTree &b); - ~SubTree(); - const SubTree &operator= (const SubTree &b); - const SubTree &operator= (const CodeTree &b); + ~SubTree(); + const SubTree &operator=(const SubTree &b); + const SubTree &operator=(const CodeTree &b); - bool getsign() const { return sign; } + bool getsign() const { return sign; } - const CodeTree* operator-> () const { return tree; } - const CodeTree& operator* () const { return *tree; } - struct CodeTree* operator-> () { return tree; } - struct CodeTree& operator* () { return *tree; } + const CodeTree *operator->() const { return tree; } + const CodeTree &operator*() const { return *tree; } + struct CodeTree *operator->() { return tree; } + struct CodeTree &operator*() { return *tree; } - bool operator< (const SubTree& b) const; - bool operator== (const SubTree& b) const; - void Negate(); // Note: Parent must be cAdd - void Invert(); // Note: Parent must be cMul + bool operator<(const SubTree &b) const; + bool operator==(const SubTree &b) const; + void Negate(); // Note: Parent must be cAdd + void Invert(); // Note: Parent must be cMul - void CheckConstNeg(); - void CheckConstInv(); + void CheckConstNeg(); + void CheckConstInv(); }; bool IsNegate(const SubTree &p1, const SubTree &p2); @@ -1657,956 +1812,958 @@ bool IsInverse(const SubTree &p1, const SubTree &p2); typedef list paramlist; -struct CodeTreeData -{ - paramlist args; +struct CodeTreeData { + paramlist args; private: - unsigned op; // Operation - double value; // In case of cImmed - unsigned var; // In case of cVar - unsigned funcno; // In case of cFCall, cPCall + unsigned op; // Operation + double value; // In case of cImmed + unsigned var; // In case of cVar + unsigned funcno; // In case of cFCall, cPCall public: - CodeTreeData() : op(cAdd) {} - ~CodeTreeData() {} - - void SetOp(unsigned newop) { op=newop; } - void SetFuncNo(unsigned newno) { funcno=newno; } - unsigned GetFuncNo() const { return funcno; } - - bool IsFunc() const { return op == cFCall || op == cPCall; } - bool IsImmed() const { return op == cImmed; } - bool IsVar() const { return op == cVar; } - inline unsigned GetOp() const { return op; } - inline double GetImmed() const - { - return value; - } - inline unsigned GetVar() const - { - return var; - } + CodeTreeData() : op(cAdd) {} + ~CodeTreeData() {} + + void SetOp(unsigned newop) { op = newop; } + void SetFuncNo(unsigned newno) { funcno = newno; } + unsigned GetFuncNo() const { return funcno; } + + bool IsFunc() const { return op == cFCall || op == cPCall; } + bool IsImmed() const { return op == cImmed; } + bool IsVar() const { return op == cVar; } + inline unsigned GetOp() const { return op; } + inline double GetImmed() const { return value; } + inline unsigned GetVar() const { return var; } + + void AddParam(const SubTree &p) { args.push_back(p); } + void SetVar(unsigned v) + { + args.clear(); + op = cVar; + var = v; + } + void SetImmed(double v) + { + args.clear(); + op = cImmed; + value = orig = v; + inverted = negated = false; + } + void NegateImmed() + { + negated = !negated; + UpdateValue(); + } + void InvertImmed() + { + inverted = !inverted; + UpdateValue(); + } + + bool IsOriginal() const { return !(IsInverted() || IsNegated()); } + bool IsInverted() const { return inverted; } + bool IsNegated() const { return negated; } + bool IsInvertedOriginal() const { return IsInverted() && !IsNegated(); } + bool IsNegatedOriginal() const { return !IsInverted() && IsNegated(); } - void AddParam(const SubTree &p) - { - args.push_back(p); - } - void SetVar(unsigned v) - { - args.clear(); - op = cVar; - var = v; - } - void SetImmed(double v) - { - args.clear(); - op = cImmed; - value = orig = v; - inverted = negated = false; - } - void NegateImmed() - { - negated = !negated; - UpdateValue(); +private: + void UpdateValue() + { + value = orig; + if (IsInverted()) { + value = 1.0 / value; + // FIXME: potential divide by zero. } - void InvertImmed() - { - inverted = !inverted; - UpdateValue(); + if (IsNegated()) { + value = -value; } + } - bool IsOriginal() const { return !(IsInverted() || IsNegated()); } - bool IsInverted() const { return inverted; } - bool IsNegated() const { return negated; } - bool IsInvertedOriginal() const { return IsInverted() && !IsNegated(); } - bool IsNegatedOriginal() const { return !IsInverted() && IsNegated(); } - -private: - void UpdateValue() - { - value = orig; - if(IsInverted()) { value = 1.0 / value; - // FIXME: potential divide by zero. - } - if(IsNegated()) value = -value; - } + double orig; + bool inverted; + bool negated; - double orig; - bool inverted; - bool negated; protected: - // Ensure we don't accidentally copy this - void operator=(const CodeTreeData &b); + // Ensure we don't accidentally copy this + void operator=(const CodeTreeData &b); }; +class CodeTreeDataPtr { + typedef pair p_t; + typedef p_t *pp; + mutable pp p; -class CodeTreeDataPtr -{ - typedef pair p_t; - typedef p_t* pp; - mutable pp p; - - void Alloc() const { ++p->second; } - void Dealloc() const { if(!--p->second) delete p; p = 0; } - - void PrepareForWrite() - { - // We're ready if we're the only owner. - if(p->second == 1) return; + void Alloc() const { ++p->second; } + void Dealloc() const + { + if (!--p->second) { + delete p; + } + p = 0; + } - // Then make a clone. - p_t *newtree = new p_t(p->first, 1); - // Forget the old - Dealloc(); - // Keep the new - p = newtree; + void PrepareForWrite() + { + // We're ready if we're the only owner. + if (p->second == 1) { + return; } + // Then make a clone. + p_t *newtree = new p_t(p->first, 1); + // Forget the old + Dealloc(); + // Keep the new + p = newtree; + } + public: - CodeTreeDataPtr() : p(new p_t) { p->second = 1; } - CodeTreeDataPtr(const CodeTreeDataPtr &b): p(b.p) { Alloc(); } - ~CodeTreeDataPtr() { Dealloc(); } - const CodeTreeDataPtr &operator= (const CodeTreeDataPtr &b) - { - b.Alloc(); - Dealloc(); - p = b.p; - return *this; - } - const CodeTreeData *operator-> () const { return &p->first; } - const CodeTreeData &operator* () const { return p->first; } - CodeTreeData *operator-> () { PrepareForWrite(); return &p->first; } - CodeTreeData &operator* () { PrepareForWrite(); return p->first; } + CodeTreeDataPtr() : p(new p_t) { p->second = 1; } + CodeTreeDataPtr(const CodeTreeDataPtr &b) : p(b.p) { Alloc(); } + ~CodeTreeDataPtr() { Dealloc(); } + const CodeTreeDataPtr &operator=(const CodeTreeDataPtr &b) + { + b.Alloc(); + Dealloc(); + p = b.p; + return *this; + } + const CodeTreeData *operator->() const { return &p->first; } + const CodeTreeData &operator*() const { return p->first; } + CodeTreeData *operator->() + { + PrepareForWrite(); + return &p->first; + } + CodeTreeData &operator*() + { + PrepareForWrite(); + return p->first; + } - void Shock(); + void Shock(); }; +#define CHECKCONSTNEG(item, op) ((op) == cMul) ? (item).CheckConstInv() : (item).CheckConstNeg() -#define CHECKCONSTNEG(item, op) \ - ((op)==cMul) \ - ? (item).CheckConstInv() \ - : (item).CheckConstNeg() - -struct CodeTree -{ - CodeTreeDataPtr data; +struct CodeTree { + CodeTreeDataPtr data; private: - typedef paramlist::iterator pit; - typedef paramlist::const_iterator pcit; + typedef paramlist::iterator pit; + typedef paramlist::const_iterator pcit; - /* - template inline void chk() const - { - } - */ + /* + template inline void chk() const + { + } + */ public: - const pcit GetBegin() const { return data->args.begin(); } - const pcit GetEnd() const { return data->args.end(); } - const pit GetBegin() { return data->args.begin(); } - const pit GetEnd() { return data->args.end(); } - const SubTree& getp0() const { /*chk<1>();*/pcit tmp=GetBegin(); return *tmp; } - const SubTree& getp1() const { /*chk<2>();*/pcit tmp=GetBegin(); ++tmp; return *tmp; } - const SubTree& getp2() const { /*chk<3>();*/pcit tmp=GetBegin(); ++tmp; ++tmp; return *tmp; } - unsigned GetArgCount() const { return data->args.size(); } - void Erase(const pit p) { data->args.erase(p); } - - SubTree& getp0() { /*chk<1>();*/pit tmp=GetBegin(); return *tmp; } - SubTree& getp1() { /*chk<2>();*/pit tmp=GetBegin(); ++tmp; return *tmp; } - SubTree& getp2() { /*chk<3>();*/pit tmp=GetBegin(); ++tmp; ++tmp; return *tmp; } - - // set - void SetImmed(double v) { data->SetImmed(v); } - void SetOp(unsigned op) { data->SetOp(op); } - void SetVar(unsigned v) { data->SetVar(v); } - // get - double GetImmed() const { return data->GetImmed(); } - unsigned GetVar() const { return data->GetVar(); } - unsigned GetOp() const { return data->GetOp(); } - // test - bool IsImmed() const { return data->IsImmed(); } - bool IsVar() const { return data->IsVar(); } - // act - void AddParam(const SubTree &p) { data->AddParam(p); } - void NegateImmed() { data->NegateImmed(); } // don't use when op!=cImmed - void InvertImmed() { data->InvertImmed(); } // don't use when op!=cImmed - - compres NonZero() const { if(!IsImmed()) return maybe; - return GetImmed() != 0.0; } - compres IsPositive() const { if(!IsImmed()) return maybe; - return GetImmed() > 0.0; } + const pcit GetBegin() const { return data->args.begin(); } + const pcit GetEnd() const { return data->args.end(); } + const pit GetBegin() { return data->args.begin(); } + const pit GetEnd() { return data->args.end(); } + const SubTree &getp0() const + { /*chk<1>();*/ + pcit tmp = GetBegin(); + return *tmp; + } + const SubTree &getp1() const + { /*chk<2>();*/ + pcit tmp = GetBegin(); + ++tmp; + return *tmp; + } + const SubTree &getp2() const + { /*chk<3>();*/ + pcit tmp = GetBegin(); + ++tmp; + ++tmp; + return *tmp; + } + unsigned GetArgCount() const { return data->args.size(); } + void Erase(const pit p) { data->args.erase(p); } + + SubTree &getp0() + { /*chk<1>();*/ + pit tmp = GetBegin(); + return *tmp; + } + SubTree &getp1() + { /*chk<2>();*/ + pit tmp = GetBegin(); + ++tmp; + return *tmp; + } + SubTree &getp2() + { /*chk<3>();*/ + pit tmp = GetBegin(); + ++tmp; + ++tmp; + return *tmp; + } + + // set + void SetImmed(double v) { data->SetImmed(v); } + void SetOp(unsigned op) { data->SetOp(op); } + void SetVar(unsigned v) { data->SetVar(v); } + // get + double GetImmed() const { return data->GetImmed(); } + unsigned GetVar() const { return data->GetVar(); } + unsigned GetOp() const { return data->GetOp(); } + // test + bool IsImmed() const { return data->IsImmed(); } + bool IsVar() const { return data->IsVar(); } + // act + void AddParam(const SubTree &p) { data->AddParam(p); } + void NegateImmed() { data->NegateImmed(); } // don't use when op!=cImmed + void InvertImmed() { data->InvertImmed(); } // don't use when op!=cImmed + + compres NonZero() const + { + if (!IsImmed()) { + return maybe; + } + return GetImmed() != 0.0; + } + compres IsPositive() const + { + if (!IsImmed()) { + return maybe; + } + return GetImmed() > 0.0; + } private: - struct ConstList - { - double voidvalue; - list cp; - double value; - unsigned size() const { return cp.size(); } - }; - struct ConstList BuildConstList(); - void KillConst(const ConstList &cl) - { - for(list::const_iterator i=cl.cp.begin(); i!=cl.cp.end(); ++i) - Erase(*i); - } - void FinishConst(const ConstList &cl) - { - if(cl.value != cl.voidvalue && cl.size() > 1) AddParam(cl.value); - if(cl.value == cl.voidvalue || cl.size() > 1) KillConst(cl); - } + struct ConstList { + double voidvalue; + list cp; + double value; + unsigned size() const { return cp.size(); } + }; + struct ConstList BuildConstList(); + void KillConst(const ConstList &cl) + { + for (list::const_iterator i = cl.cp.begin(); i != cl.cp.end(); ++i) { + Erase(*i); + } + } + void FinishConst(const ConstList &cl) + { + if (cl.value != cl.voidvalue && cl.size() > 1) { + AddParam(cl.value); + } + if (cl.value == cl.voidvalue || cl.size() > 1) { + KillConst(cl); + } + } public: - CodeTree() {} - CodeTree(double v) { SetImmed(v); } - - CodeTree(unsigned op, const SubTree &p) - { - SetOp(op); - AddParam(p); - } - CodeTree(unsigned op, const SubTree &p1, const SubTree &p2) - { - SetOp(op); - AddParam(p1); - AddParam(p2); - } - - bool operator== (const CodeTree& b) const; - bool operator< (const CodeTree& b) const; + CodeTree() {} + CodeTree(double v) { SetImmed(v); } + + CodeTree(unsigned op, const SubTree &p) + { + SetOp(op); + AddParam(p); + } + CodeTree(unsigned op, const SubTree &p1, const SubTree &p2) + { + SetOp(op); + AddParam(p1); + AddParam(p2); + } + + bool operator==(const CodeTree &b) const; + bool operator<(const CodeTree &b) const; private: - bool IsSortable() const - { - switch(GetOp()) - { - case cAdd: case cMul: - case cEqual: - case cAnd: case cOr: - case cMax: case cMin: - return true; - default: - return false; - } - } - void SortIfPossible() - { - if(IsSortable()) - { - data->args.sort(); + bool IsSortable() const + { + switch (GetOp()) { + case cAdd: + case cMul: + case cEqual: + case cAnd: + case cOr: + case cMax: + case cMin: + return true; + default: + return false; + } + } + void SortIfPossible() + { + if (IsSortable()) { + data->args.sort(); + } + } + + void ReplaceWithConst(double value) + { + SetImmed(value); + + /* REMEMBER TO CALL CheckConstInv / CheckConstNeg + * FOR PARENT SubTree, OR MAYHEM HAPPENS + */ + } + + void ReplaceWith(const CodeTree &b) + { + // If b is child of *this, mayhem + // happens. So we first make a clone + // and then proceed with copy. + CodeTreeDataPtr tmp = b.data; + tmp.Shock(); + data = tmp; + } + + void ReplaceWith(unsigned op, const SubTree &p) { ReplaceWith(CodeTree(op, p)); } + + void ReplaceWith(unsigned op, const SubTree &p1, const SubTree &p2) + { + ReplaceWith(CodeTree(op, p1, p2)); + } + + void OptimizeConflict() + { + // This optimization does this: x-x = 0, x/x = 1, a+b-a = b. + + if (GetOp() == cAdd || GetOp() == cMul) { + Redo: + pit a, b; + for (a = GetBegin(); a != GetEnd(); ++a) { + for (b = GetBegin(); ++b != GetEnd();) { + const SubTree &p1 = *a; + const SubTree &p2 = *b; + + if (GetOp() == cMul ? IsInverse(p1, p2) : IsNegate(p1, p2)) { + // These parameters complement each others out + Erase(b); + Erase(a); + goto Redo; + } } + } } + OptimizeRedundant(); + } - void ReplaceWithConst(double value) - { - SetImmed(value); + void OptimizeRedundant() + { + // This optimization does this: min()=0, max()=0, add()=0, mul()=1 - /* REMEMBER TO CALL CheckConstInv / CheckConstNeg - * FOR PARENT SubTree, OR MAYHEM HAPPENS - */ + if (!GetArgCount()) { + if (GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax) { + ReplaceWithConst(0); + } + else if (GetOp() == cMul) { + ReplaceWithConst(1); + } + return; } - void ReplaceWith(const CodeTree &b) - { - // If b is child of *this, mayhem - // happens. So we first make a clone - // and then proceed with copy. - CodeTreeDataPtr tmp = b.data; - tmp.Shock(); - data = tmp; - } - - void ReplaceWith(unsigned op, const SubTree &p) - { - ReplaceWith(CodeTree(op, p)); - } + // And this: mul(x) = x, min(x) = x, max(x) = x, add(x) = x - void ReplaceWith(unsigned op, const SubTree &p1, const SubTree &p2) - { - ReplaceWith(CodeTree(op, p1, p2)); - } + if (GetArgCount() == 1) { + if (GetOp() == cMul || GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax) { + if (!getp0().getsign()) { + ReplaceWith(*getp0()); + } + } + } + + OptimizeDoubleNegations(); + } + + void OptimizeDoubleNegations() + { + if (GetOp() == cAdd) { + // Eschew double negations + + // If any of the elements is cMul + // and has a numeric constant, negate + // the constant and negate sign. + + for (pit a = GetBegin(); a != GetEnd(); ++a) { + SubTree &pa = *a; + if (pa.getsign() && pa->GetOp() == cMul) { + CodeTree &p = *pa; + for (pit b = p.GetBegin(); b != p.GetEnd(); ++b) { + SubTree &pb = *b; + if (pb->IsImmed()) { + pb.Negate(); + pa.Negate(); + break; + } + } + } + } + } + + if (GetOp() == cMul) { + // If any of the elements is cPow + // and has a numeric exponent, negate + // the exponent and negate sign. + + for (pit a = GetBegin(); a != GetEnd(); ++a) { + SubTree &pa = *a; + if (pa.getsign() && pa->GetOp() == cPow) { + CodeTree &p = *pa; + if (p.getp1()->IsImmed()) { + // negate ok for pow when op=cImmed + p.getp1().Negate(); + pa.Negate(); + } + } + } + } + } + + void OptimizeConstantMath1() + { + // This optimization does three things: + // - For adding groups: + // Constants are added together. + // - For multiplying groups: + // Constants are multiplied together. + // - For function calls: + // If all parameters are constants, + // the call is replaced with constant value. + + // First, do this: + OptimizeAddMulFlat(); + + switch (GetOp()) { + case cAdd: { + ConstList cl = BuildConstList(); + FinishConst(cl); + break; + } + case cMul: { + ConstList cl = BuildConstList(); + + if (cl.value == 0.0) { + ReplaceWithConst(0.0); + } + else { + FinishConst(cl); + } + + break; + } +#define ConstantUnaryFun(token, fun) \ + case token: { \ + const SubTree &p0 = getp0(); \ + if (p0->IsImmed()) \ + ReplaceWithConst(fun(p0->GetImmed())); \ + break; \ + } +#define ConstantBinaryFun(token, fun) \ + case token: { \ + const SubTree &p0 = getp0(); \ + const SubTree &p1 = getp1(); \ + if (p0->IsImmed() && p1->IsImmed()) \ + ReplaceWithConst(fun(p0->GetImmed(), p1->GetImmed())); \ + break; \ + } + + // FIXME: potential invalid parameters for functions + // can cause exceptions here + + ConstantUnaryFun(cAbs, fabs); + ConstantUnaryFun(cAcos, acos); + ConstantUnaryFun(cAsin, asin); + ConstantUnaryFun(cAtan, atan); + ConstantUnaryFun(cCeil, ceil); + ConstantUnaryFun(cCos, cos); + ConstantUnaryFun(cCosh, cosh); + ConstantUnaryFun(cFloor, floor); + ConstantUnaryFun(cLog, log); + ConstantUnaryFun(cSin, sin); + ConstantUnaryFun(cSinh, sinh); + ConstantUnaryFun(cTan, tan); + ConstantUnaryFun(cTanh, tanh); + ConstantBinaryFun(cAtan2, atan2); + ConstantBinaryFun(cMax, Max); + ConstantBinaryFun(cMin, Min); + ConstantBinaryFun(cMod, fmod); // not a func, but belongs here too + ConstantBinaryFun(cPow, pow); + + case cNeg: + case cSub: + case cDiv: + /* Unreached (nonexistent operator) + * TODO: internal error here? + */ + break; + + case cCot: + case cCsc: + case cSec: + case cDeg: + case cRad: + case cLog10: + case cSqrt: + case cExp: + /* Unreached (nonexistent function) + * TODO: internal error here? + */ + break; + } + + OptimizeConflict(); + } + + void OptimizeAddMulFlat() + { + // This optimization flattens the topography of the tree. + // Examples: + // x + (y+z) = x+y+z + // x * (y/z) = x*y/z + // x / (y/z) = x/y*z + + if (GetOp() == cAdd || GetOp() == cMul) { + // If children are same type as parent add them here + for (pit b, a = GetBegin(); a != GetEnd(); a = b) { + const SubTree &pa = *a; + b = a; + ++b; + if (pa->GetOp() != GetOp()) { + continue; + } - void OptimizeConflict() - { - // This optimization does this: x-x = 0, x/x = 1, a+b-a = b. + // Child is same type + for (pcit c = pa->GetBegin(); c != pa->GetEnd(); ++c) { + const SubTree &pb = *c; + if (pa.getsign()) { + // +a -(+b +c) + // means b and c will be negated - if(GetOp() == cAdd || GetOp() == cMul) - { - Redo: - pit a, b; - for(a=GetBegin(); a!=GetEnd(); ++a) - { - for(b=GetBegin(); ++b != GetEnd(); ) - { - const SubTree &p1 = *a; - const SubTree &p2 = *b; - - if(GetOp() == cMul ? IsInverse(p1,p2) - : IsNegate(p1,p2)) - { - // These parameters complement each others out - Erase(b); - Erase(a); - goto Redo; - } - } + SubTree tmp = pb; + if (GetOp() == cMul) { + tmp.Invert(); } + else { + tmp.Negate(); + } + AddParam(tmp); + } + else { + AddParam(pb); + } } - OptimizeRedundant(); + Erase(a); + + // Note: OptimizeConstantMath1() would be a good thing to call next. + } } + } - void OptimizeRedundant() - { - // This optimization does this: min()=0, max()=0, add()=0, mul()=1 + void OptimizeLinearCombine() + { + // This optimization does the following: + // + // x*x*x*x -> x^4 + // x+x+x+x -> x*4 + // x*x -> x^2 + // x/z/z -> + // - if(!GetArgCount()) - { - if(GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax) - ReplaceWithConst(0); - else if(GetOp() == cMul) - ReplaceWithConst(1); - return; - } + // Remove conflicts first, so we don't have to worry about signs. + OptimizeConflict(); - // And this: mul(x) = x, min(x) = x, max(x) = x, add(x) = x + bool didchanges = false; + if (GetOp() == cAdd || GetOp() == cMul) { + Redo: + for (pit a = GetBegin(); a != GetEnd(); ++a) { + const SubTree &pa = *a; - if(GetArgCount() == 1) - { - if(GetOp() == cMul || GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax) - if(!getp0().getsign()) - ReplaceWith(*getp0()); + list poslist; + + for (pit b = a; ++b != GetEnd();) { + const SubTree &pb = *b; + if (*pa == *pb) { + poslist.push_back(b); + } } - OptimizeDoubleNegations(); - } + unsigned min = 2; + if (poslist.size() >= min) { + SubTree arvo = pa; + bool negate = arvo.getsign(); - void OptimizeDoubleNegations() - { - if(GetOp() == cAdd) - { - // Eschew double negations - - // If any of the elements is cMul - // and has a numeric constant, negate - // the constant and negate sign. - - for(pit a=GetBegin(); a!=GetEnd(); ++a) - { - SubTree &pa = *a; - if(pa.getsign() - && pa->GetOp() == cMul) - { - CodeTree &p = *pa; - for(pit b=p.GetBegin(); - b!=p.GetEnd(); ++b) - { - SubTree &pb = *b; - if(pb->IsImmed()) - { - pb.Negate(); - pa.Negate(); - break; - } - } - } - } - } + double factor = poslist.size() + 1; - if(GetOp() == cMul) - { - // If any of the elements is cPow - // and has a numeric exponent, negate - // the exponent and negate sign. - - for(pit a=GetBegin(); a!=GetEnd(); ++a) - { - SubTree &pa = *a; - if(pa.getsign() && pa->GetOp() == cPow) - { - CodeTree &p = *pa; - if(p.getp1()->IsImmed()) - { - // negate ok for pow when op=cImmed - p.getp1().Negate(); - pa.Negate(); - } - } - } + if (negate) { + arvo.Negate(); + factor = -factor; + } + + CodeTree tmp(GetOp() == cAdd ? cMul : cPow, arvo, factor); + + list::const_iterator j; + for (j = poslist.begin(); j != poslist.end(); ++j) { + Erase(*j); + } + poslist.clear(); + + *a = tmp; + didchanges = true; + goto Redo; } + } } + if (didchanges) { + // As a result, there might be need for this: + OptimizeAddMulFlat(); + // And this: + OptimizeRedundant(); + } + } - void OptimizeConstantMath1() - { - // This optimization does three things: - // - For adding groups: - // Constants are added together. - // - For multiplying groups: - // Constants are multiplied together. - // - For function calls: - // If all parameters are constants, - // the call is replaced with constant value. - - // First, do this: - OptimizeAddMulFlat(); - - switch(GetOp()) - { - case cAdd: - { - ConstList cl = BuildConstList(); - FinishConst(cl); - break; - } - case cMul: - { - ConstList cl = BuildConstList(); + void OptimizeLogarithm() + { + /* + This is basic logarithm math: + pow(X,Y)/log(Y) = X + log(X)/log(Y) = logY(X) + log(X^Y) = log(X)*Y + log(X*Y) = log(X)+log(Y) + exp(log(X)*Y) = X^Y + + This function does these optimizations: + pow(const_E, log(x)) = x + pow(const_E, log(x)*y) = x^y + pow(10, log(x)*const_L10I*y) = x^y + pow(z, log(x)/log(z)*y) = x^y + + And this: + log(x^z) = z * log(x) + Which automatically causes these too: + log(pow(const_E, x)) = x + log(pow(y, x)) = x * log(y) + log(pow(pow(const_E, y), x)) = x*y + + And it does this too: + log(x) + log(y) + log(z) = log(x * y * z) + log(x * exp(y)) = log(x) + y - if(cl.value == 0.0) ReplaceWithConst(0.0); - else FinishConst(cl); + */ - break; - } - #define ConstantUnaryFun(token, fun) \ - case token: { const SubTree &p0 = getp0(); \ - if(p0->IsImmed()) ReplaceWithConst(fun(p0->GetImmed())); \ - break; } - #define ConstantBinaryFun(token, fun) \ - case token: { const SubTree &p0 = getp0(); \ - const SubTree &p1 = getp1(); \ - if(p0->IsImmed() && \ - p1->IsImmed()) ReplaceWithConst(fun(p0->GetImmed(), p1->GetImmed())); \ - break; } - - // FIXME: potential invalid parameters for functions - // can cause exceptions here - - ConstantUnaryFun(cAbs, fabs); - ConstantUnaryFun(cAcos, acos); - ConstantUnaryFun(cAsin, asin); - ConstantUnaryFun(cAtan, atan); - ConstantUnaryFun(cCeil, ceil); - ConstantUnaryFun(cCos, cos); - ConstantUnaryFun(cCosh, cosh); - ConstantUnaryFun(cFloor, floor); - ConstantUnaryFun(cLog, log); - ConstantUnaryFun(cSin, sin); - ConstantUnaryFun(cSinh, sinh); - ConstantUnaryFun(cTan, tan); - ConstantUnaryFun(cTanh, tanh); - ConstantBinaryFun(cAtan2, atan2); - ConstantBinaryFun(cMax, Max); - ConstantBinaryFun(cMin, Min); - ConstantBinaryFun(cMod, fmod); // not a func, but belongs here too - ConstantBinaryFun(cPow, pow); - - case cNeg: - case cSub: - case cDiv: - /* Unreached (nonexistent operator) - * TODO: internal error here? - */ - break; - - case cCot: - case cCsc: - case cSec: - case cDeg: - case cRad: - case cLog10: - case cSqrt: - case cExp: - /* Unreached (nonexistent function) - * TODO: internal error here? - */ - break; - } + // Must be already in exponential form. - OptimizeConflict(); - } + // Optimize exponents before doing something. + OptimizeExponents(); - void OptimizeAddMulFlat() - { - // This optimization flattens the topography of the tree. - // Examples: - // x + (y+z) = x+y+z - // x * (y/z) = x*y/z - // x / (y/z) = x/y*z + if (GetOp() == cLog) { + // We should have one parameter for log() function. + // If we don't, we're screwed. - if(GetOp() == cAdd || GetOp() == cMul) - { - // If children are same type as parent add them here - for(pit b, a=GetBegin(); a!=GetEnd(); a=b) - { - const SubTree &pa = *a; b=a; ++b; - if(pa->GetOp() != GetOp()) continue; - - // Child is same type - for(pcit c=pa->GetBegin(); - c!=pa->GetEnd(); - ++c) - { - const SubTree &pb = *c; - if(pa.getsign()) - { - // +a -(+b +c) - // means b and c will be negated - - SubTree tmp = pb; - if(GetOp() == cMul) - tmp.Invert(); - else - tmp.Negate(); - AddParam(tmp); - } - else - AddParam(pb); - } - Erase(a); - - // Note: OptimizeConstantMath1() would be a good thing to call next. - } - } - } + const SubTree &p = getp0(); - void OptimizeLinearCombine() - { - // This optimization does the following: - // - // x*x*x*x -> x^4 - // x+x+x+x -> x*4 - // x*x -> x^2 - // x/z/z -> - // + if (p->GetOp() == cPow) { + // Found log(x^y) + SubTree p0 = p->getp0(); // x + SubTree p1 = p->getp1(); // y - // Remove conflicts first, so we don't have to worry about signs. - OptimizeConflict(); + // Build the new logarithm. + CodeTree tmp(GetOp(), p0); // log(x) - bool didchanges = false; - if(GetOp() == cAdd || GetOp() == cMul) - { - Redo: - for(pit a=GetBegin(); a!=GetEnd(); ++a) - { - const SubTree &pa = *a; - - list poslist; - - for(pit b=a; ++b!=GetEnd(); ) - { - const SubTree &pb = *b; - if(*pa == *pb) - poslist.push_back(b); - } - - unsigned min = 2; - if(poslist.size() >= min) - { - SubTree arvo = pa; - bool negate = arvo.getsign(); - - double factor = poslist.size() + 1; - - if(negate) - { - arvo.Negate(); - factor = -factor; - } - - CodeTree tmp(GetOp()==cAdd ? cMul : cPow, - arvo, - factor); - - list::const_iterator j; - for(j=poslist.begin(); j!=poslist.end(); ++j) - Erase(*j); - poslist.clear(); - - *a = tmp; - didchanges = true; - goto Redo; - } - } - } - if(didchanges) - { - // As a result, there might be need for this: - OptimizeAddMulFlat(); - // And this: - OptimizeRedundant(); - } - } + // Become log(x) * y + ReplaceWith(cMul, tmp, p1); + } + else if (p->GetOp() == cMul) { + // Redefine &p nonconst + SubTree &p = getp0(); - void OptimizeLogarithm() - { - /* - This is basic logarithm math: - pow(X,Y)/log(Y) = X - log(X)/log(Y) = logY(X) - log(X^Y) = log(X)*Y - log(X*Y) = log(X)+log(Y) - exp(log(X)*Y) = X^Y - - This function does these optimizations: - pow(const_E, log(x)) = x - pow(const_E, log(x)*y) = x^y - pow(10, log(x)*const_L10I*y) = x^y - pow(z, log(x)/log(z)*y) = x^y - - And this: - log(x^z) = z * log(x) - Which automatically causes these too: - log(pow(const_E, x)) = x - log(pow(y, x)) = x * log(y) - log(pow(pow(const_E, y), x)) = x*y - - And it does this too: - log(x) + log(y) + log(z) = log(x * y * z) - log(x * exp(y)) = log(x) + y - - */ - - // Must be already in exponential form. - - // Optimize exponents before doing something. - OptimizeExponents(); - - if(GetOp() == cLog) - { - // We should have one parameter for log() function. - // If we don't, we're screwed. + p->OptimizeAddMulFlat(); + p->OptimizeExponents(); + CHECKCONSTNEG(p, p->GetOp()); - const SubTree &p = getp0(); + list adds; - if(p->GetOp() == cPow) - { - // Found log(x^y) - SubTree p0 = p->getp0(); // x - SubTree p1 = p->getp1(); // y + for (pit b, a = p->GetBegin(); a != p->GetEnd(); a = b) { + SubTree &pa = *a; + b = a; + ++b; + if (pa->GetOp() == cPow && pa->getp0()->IsImmed() && + pa->getp0()->GetImmed() == CONSTANT_E) { + adds.push_back(pa->getp1()); + p->Erase(a); + continue; + } + } + if (adds.size()) { + CodeTree tmp(cAdd, *this); - // Build the new logarithm. - CodeTree tmp(GetOp(), p0); // log(x) + list::const_iterator i; + for (i = adds.begin(); i != adds.end(); ++i) { + tmp.AddParam(*i); + } - // Become log(x) * y - ReplaceWith(cMul, tmp, p1); - } - else if(p->GetOp() == cMul) - { - // Redefine &p nonconst - SubTree &p = getp0(); - - p->OptimizeAddMulFlat(); - p->OptimizeExponents(); - CHECKCONSTNEG(p, p->GetOp()); - - list adds; - - for(pit b, a = p->GetBegin(); - a != p->GetEnd(); a=b) - { - SubTree &pa = *a; b=a; ++b; - if(pa->GetOp() == cPow - && pa->getp0()->IsImmed() - && pa->getp0()->GetImmed() == CONSTANT_E) - { - adds.push_back(pa->getp1()); - p->Erase(a); - continue; - } - } - if(adds.size()) - { - CodeTree tmp(cAdd, *this); - - list::const_iterator i; - for(i=adds.begin(); i!=adds.end(); ++i) - tmp.AddParam(*i); - - ReplaceWith(tmp); - } - } + ReplaceWith(tmp); } - if(GetOp() == cAdd) - { - // Check which ones are logs. - list poslist; - - for(pit a=GetBegin(); a!=GetEnd(); ++a) - { - const SubTree &pa = *a; - if(pa->GetOp() == cLog) - poslist.push_back(a); - } + } + } + if (GetOp() == cAdd) { + // Check which ones are logs. + list poslist; - if(poslist.size() >= 2) - { - CodeTree tmp(cMul, 1.0); // eek - - list::const_iterator j; - for(j=poslist.begin(); j!=poslist.end(); ++j) - { - const SubTree &pb = **j; - // Take all of its children - for(pcit b=pb->GetBegin(); - b!=pb->GetEnd(); - ++b) - { - SubTree tmp2 = *b; - if(pb.getsign()) tmp2.Negate(); - tmp.AddParam(tmp2); - } - Erase(*j); - } - poslist.clear(); - - AddParam(CodeTree(cLog, tmp)); + for (pit a = GetBegin(); a != GetEnd(); ++a) { + const SubTree &pa = *a; + if (pa->GetOp() == cLog) { + poslist.push_back(a); + } + } + + if (poslist.size() >= 2) { + CodeTree tmp(cMul, 1.0); // eek + + list::const_iterator j; + for (j = poslist.begin(); j != poslist.end(); ++j) { + const SubTree &pb = **j; + // Take all of its children + for (pcit b = pb->GetBegin(); b != pb->GetEnd(); ++b) { + SubTree tmp2 = *b; + if (pb.getsign()) { + tmp2.Negate(); } - // Done, hopefully + tmp.AddParam(tmp2); + } + Erase(*j); } - if(GetOp() == cPow) - { - const SubTree &p0 = getp0(); - SubTree &p1 = getp1(); - - if(p0->IsImmed() && p0->GetImmed() == CONSTANT_E - && p1->GetOp() == cLog) - { - // pow(const_E, log(x)) = x - ReplaceWith(*(p1->getp0())); + poslist.clear(); + + AddParam(CodeTree(cLog, tmp)); + } + // Done, hopefully + } + if (GetOp() == cPow) { + const SubTree &p0 = getp0(); + SubTree &p1 = getp1(); + + if (p0->IsImmed() && p0->GetImmed() == CONSTANT_E && p1->GetOp() == cLog) { + // pow(const_E, log(x)) = x + ReplaceWith(*(p1->getp0())); + } + else if (p1->GetOp() == cMul) { + // bool didsomething = true; + + pit poslogpos /*= NULL*/; + bool foundposlog = false; + pit neglogpos /*= NULL*/; + bool foundneglog = false; + + ConstList cl = p1->BuildConstList(); + + for (pit a = p1->GetBegin(); a != p1->GetEnd(); ++a) { + const SubTree &pa = *a; + if (pa->GetOp() == cLog) { + if (!pa.getsign()) { + foundposlog = true; + poslogpos = a; } - else if(p1->GetOp() == cMul) - { - //bool didsomething = true; - - pit poslogpos /*= NULL*/; bool foundposlog = false; - pit neglogpos /*= NULL*/; bool foundneglog = false; - - ConstList cl = p1->BuildConstList(); - - for(pit a=p1->GetBegin(); a!=p1->GetEnd(); ++a) - { - const SubTree &pa = *a; - if(pa->GetOp() == cLog) - { - if(!pa.getsign()) - { - foundposlog = true; - poslogpos = a; - } - else if(*p0 == *(pa->getp0())) - { - foundneglog = true; - neglogpos = a; - } - } - } - - if(p0->IsImmed() - && p0->GetImmed() == 10.0 - && cl.value == CONSTANT_L10I - && foundposlog) - { - SubTree base = (*poslogpos)->getp0(); - p1->KillConst(cl); - p1->Erase(poslogpos); - p1->OptimizeRedundant(); - SubTree mul = p1; - - ReplaceWith(cPow, base, mul); - - // FIXME: what optimizations should be done now? - return; - } - - // Put back the constant - FinishConst(cl); - - if(p0->IsImmed() - && p0->GetImmed() == CONSTANT_E - && foundposlog) - { - SubTree base = (*poslogpos)->getp0(); - p1->Erase(poslogpos); - - p1->OptimizeRedundant(); - SubTree mul = p1; - - ReplaceWith(cPow, base, mul); - - // FIXME: what optimizations should be done now? - return; - } - - if(foundposlog - && foundneglog - && *((*neglogpos)->getp0()) == *p0) - { - SubTree base = (*poslogpos)->getp0(); - p1->Erase(poslogpos); - p1->Erase(neglogpos); - - p1->OptimizeRedundant(); - SubTree mul = p1; - - ReplaceWith(cPow, base, mul); - - // FIXME: what optimizations should be done now? - return; - } + else if (*p0 == *(pa->getp0())) { + foundneglog = true; + neglogpos = a; } + } } - } - void OptimizeFunctionCalls() - { - /* Goals: sin(asin(x)) = x - * cos(acos(x)) = x - * tan(atan(x)) = x - * NOTE: - * Do NOT do these: - * asin(sin(x)) - * acos(cos(x)) - * atan(tan(x)) - * Because someone might want to wrap the angle. - */ - // FIXME: TODO - } - - void OptimizePowMulAdd() - { - // x^3 * x -> x^4 - // x*3 + x -> x*4 - // FIXME: Do those + if (p0->IsImmed() && p0->GetImmed() == 10.0 && cl.value == CONSTANT_L10I && foundposlog) { + SubTree base = (*poslogpos)->getp0(); + p1->KillConst(cl); + p1->Erase(poslogpos); + p1->OptimizeRedundant(); + SubTree mul = p1; - // x^1 -> x - if(GetOp() == cPow) - { - const SubTree &base = getp0(); - const SubTree &exponent = getp1(); - - if(exponent->IsImmed()) - { - if(exponent->GetImmed() == 1.0) - ReplaceWith(*base); - else if(exponent->GetImmed() == 0.0 - && base->NonZero()) - ReplaceWithConst(1.0); - } + ReplaceWith(cPow, base, mul); + + // FIXME: what optimizations should be done now? + return; } - } - void OptimizeExponents() - { - /* Goals: - * (x^y)^z -> x^(y*z) - * x^y * x^z -> x^(y+z) - */ - // First move to exponential form. - OptimizeLinearCombine(); + // Put back the constant + FinishConst(cl); - bool didchanges = false; + if (p0->IsImmed() && p0->GetImmed() == CONSTANT_E && foundposlog) { + SubTree base = (*poslogpos)->getp0(); + p1->Erase(poslogpos); - Redo: - if(GetOp() == cPow) - { - // (x^y)^z -> x^(y*z) + p1->OptimizeRedundant(); + SubTree mul = p1; - const SubTree &p0 = getp0(); - const SubTree &p1 = getp1(); - if(p0->GetOp() == cPow) - { - CodeTree tmp(cMul, p0->getp1(), p1); - tmp.Optimize(); + ReplaceWith(cPow, base, mul); - ReplaceWith(cPow, p0->getp0(), tmp); + // FIXME: what optimizations should be done now? + return; + } - didchanges = true; - goto Redo; - } + if (foundposlog && foundneglog && *((*neglogpos)->getp0()) == *p0) { + SubTree base = (*poslogpos)->getp0(); + p1->Erase(poslogpos); + p1->Erase(neglogpos); + + p1->OptimizeRedundant(); + SubTree mul = p1; + + ReplaceWith(cPow, base, mul); + + // FIXME: what optimizations should be done now? + return; } - if(GetOp() == cMul) - { - // x^y * x^z -> x^(y+z) + } + } + } + + void OptimizeFunctionCalls() + { + /* Goals: sin(asin(x)) = x + * cos(acos(x)) = x + * tan(atan(x)) = x + * NOTE: + * Do NOT do these: + * asin(sin(x)) + * acos(cos(x)) + * atan(tan(x)) + * Because someone might want to wrap the angle. + */ + // FIXME: TODO + } + + void OptimizePowMulAdd() + { + // x^3 * x -> x^4 + // x*3 + x -> x*4 + // FIXME: Do those + + // x^1 -> x + if (GetOp() == cPow) { + const SubTree &base = getp0(); + const SubTree &exponent = getp1(); + + if (exponent->IsImmed()) { + if (exponent->GetImmed() == 1.0) { + ReplaceWith(*base); + } + else if (exponent->GetImmed() == 0.0 && base->NonZero()) { + ReplaceWithConst(1.0); + } + } + } + } - for(pit a=GetBegin(); a!=GetEnd(); ++a) - { - const SubTree &pa = *a; + void OptimizeExponents() + { + /* Goals: + * (x^y)^z -> x^(y*z) + * x^y * x^z -> x^(y+z) + */ + // First move to exponential form. + OptimizeLinearCombine(); - if(pa->GetOp() != cPow) continue; + bool didchanges = false; - list poslist; + Redo: + if (GetOp() == cPow) { + // (x^y)^z -> x^(y*z) - for(pit b=a; ++b != GetEnd(); ) - { - const SubTree &pb = *b; - if(pb->GetOp() == cPow - && *(pa->getp0()) - == *(pb->getp0())) - { - poslist.push_back(b); - } - } + const SubTree &p0 = getp0(); + const SubTree &p1 = getp1(); + if (p0->GetOp() == cPow) { + CodeTree tmp(cMul, p0->getp1(), p1); + tmp.Optimize(); - if(poslist.size() >= 1) - { - poslist.push_back(a); + ReplaceWith(cPow, p0->getp0(), tmp); - CodeTree base = *(pa->getp0()); + didchanges = true; + goto Redo; + } + } + if (GetOp() == cMul) { + // x^y * x^z -> x^(y+z) - CodeTree exponent(cAdd, 0.0); //eek + for (pit a = GetBegin(); a != GetEnd(); ++a) { + const SubTree &pa = *a; - // Collect all exponents to cAdd - list::const_iterator i; - for(i=poslist.begin(); i!=poslist.end(); ++i) - { - const SubTree &pb = **i; + if (pa->GetOp() != cPow) { + continue; + } - SubTree tmp2 = pb->getp1(); - if(pb.getsign()) tmp2.Invert(); + list poslist; - exponent.AddParam(tmp2); - } + for (pit b = a; ++b != GetEnd();) { + const SubTree &pb = *b; + if (pb->GetOp() == cPow && *(pa->getp0()) == *(pb->getp0())) { + poslist.push_back(b); + } + } - exponent.Optimize(); + if (poslist.size() >= 1) { + poslist.push_back(a); - CodeTree result(cPow, base, exponent); + CodeTree base = *(pa->getp0()); - for(i=poslist.begin(); i!=poslist.end(); ++i) - Erase(*i); - poslist.clear(); + CodeTree exponent(cAdd, 0.0); // eek - AddParam(result); // We're cMul, remember + // Collect all exponents to cAdd + list::const_iterator i; + for (i = poslist.begin(); i != poslist.end(); ++i) { + const SubTree &pb = **i; - didchanges = true; - goto Redo; - } + SubTree tmp2 = pb->getp1(); + if (pb.getsign()) { + tmp2.Invert(); } - } - OptimizePowMulAdd(); + exponent.AddParam(tmp2); + } - if(didchanges) - { - // As a result, there might be need for this: - OptimizeConflict(); + exponent.Optimize(); + + CodeTree result(cPow, base, exponent); + + for (i = poslist.begin(); i != poslist.end(); ++i) { + Erase(*i); + } + poslist.clear(); + + AddParam(result); // We're cMul, remember + + didchanges = true; + goto Redo; } + } } - void OptimizeLinearExplode() - { - // x^2 -> x*x - // But only if x is just a simple thing + OptimizePowMulAdd(); - // Won't work on anything else. - if(GetOp() != cPow) return; + if (didchanges) { + // As a result, there might be need for this: + OptimizeConflict(); + } + } + + void OptimizeLinearExplode() + { + // x^2 -> x*x + // But only if x is just a simple thing - // TODO TODO TODO + // Won't work on anything else. + if (GetOp() != cPow) { + return; } - void OptimizePascal() - { -#if 0 // Too big, too specific, etc + // TODO TODO TODO + } + + void OptimizePascal() + { +#if 0 // Too big, too specific, etc // Won't work on anything else. if(GetOp() != cAdd) return; @@ -2626,729 +2783,710 @@ struct CodeTree // x x * x y * + y y * + // -> x y + dup * x y * - #endif - } + } public: - - void Optimize(); - - void Assemble(vector &byteCode, - vector &immed) const; - - void FinalOptimize() - { - // First optimize each parameter. - for(pit a=GetBegin(); a!=GetEnd(); ++a) - (*a)->FinalOptimize(); - - /* These things are to be done: - * - * x * CONSTANT_DR -> cDeg(x) - * x * CONSTANT_RD -> cRad(x) - * pow(x, 0.5) -> sqrt(x) - * log(x) * CONSTANT_L10I -> log10(x) - * pow(CONSTANT_E, x) -> exp(x) - * inv(sin(x)) -> csc(x) - * inv(cos(x)) -> sec(x) - * inv(tan(x)) -> cot(x) - */ - - - if(GetOp() == cPow) - { - const SubTree &p0 = getp0(); - const SubTree &p1 = getp1(); - if(p0->GetOp() == cImmed - && p0->GetImmed() == CONSTANT_E) - { - ReplaceWith(cExp, p1); - } - else if(p1->GetOp() == cImmed - && p1->GetImmed() == 0.5) - { - ReplaceWith(cSqrt, p0); - } + void Optimize(); + + void Assemble(vector &byteCode, vector &immed) const; + + void FinalOptimize() + { + // First optimize each parameter. + for (pit a = GetBegin(); a != GetEnd(); ++a) { + (*a)->FinalOptimize(); + } + + /* These things are to be done: + * + * x * CONSTANT_DR -> cDeg(x) + * x * CONSTANT_RD -> cRad(x) + * pow(x, 0.5) -> sqrt(x) + * log(x) * CONSTANT_L10I -> log10(x) + * pow(CONSTANT_E, x) -> exp(x) + * inv(sin(x)) -> csc(x) + * inv(cos(x)) -> sec(x) + * inv(tan(x)) -> cot(x) + */ + + if (GetOp() == cPow) { + const SubTree &p0 = getp0(); + const SubTree &p1 = getp1(); + if (p0->GetOp() == cImmed && p0->GetImmed() == CONSTANT_E) { + ReplaceWith(cExp, p1); + } + else if (p1->GetOp() == cImmed && p1->GetImmed() == 0.5) { + ReplaceWith(cSqrt, p0); + } + } + if (GetOp() == cMul) { + if (GetArgCount() == 1 && getp0().getsign()) { + /***/ if (getp0()->GetOp() == cSin) { + ReplaceWith(cCsc, getp0()->getp0()); } - if(GetOp() == cMul) - { - if(GetArgCount() == 1 && getp0().getsign()) - { - /***/if(getp0()->GetOp() == cSin)ReplaceWith(cCsc, getp0()->getp0()); - else if(getp0()->GetOp() == cCos)ReplaceWith(cSec, getp0()->getp0()); - else if(getp0()->GetOp() == cTan)ReplaceWith(cCot, getp0()->getp0()); - } + else if (getp0()->GetOp() == cCos) { + ReplaceWith(cSec, getp0()->getp0()); } - // Separate "if", because op may have just changed - if(GetOp() == cMul) - { - CodeTree *found_log = 0; + else if (getp0()->GetOp() == cTan) { + ReplaceWith(cCot, getp0()->getp0()); + } + } + } + // Separate "if", because op may have just changed + if (GetOp() == cMul) { + CodeTree *found_log = 0; - ConstList cl = BuildConstList(); + ConstList cl = BuildConstList(); - for(pit a=GetBegin(); a!=GetEnd(); ++a) - { - SubTree &pa = *a; - if(pa->GetOp() == cLog && !pa.getsign()) - found_log = &*pa; - } - if(cl.value == CONSTANT_L10I && found_log) - { - // Change the log() to log10() - found_log->SetOp(cLog10); - // And forget the constant - KillConst(cl); - } - else if(cl.value == CONSTANT_DR) - { - OptimizeRedundant(); - ReplaceWith(cDeg, *this); - } - else if(cl.value == CONSTANT_RD) - { - OptimizeRedundant(); - ReplaceWith(cRad, *this); - } - else FinishConst(cl); + for (pit a = GetBegin(); a != GetEnd(); ++a) { + SubTree &pa = *a; + if (pa->GetOp() == cLog && !pa.getsign()) { + found_log = &*pa; } - - SortIfPossible(); + } + if (cl.value == CONSTANT_L10I && found_log) { + // Change the log() to log10() + found_log->SetOp(cLog10); + // And forget the constant + KillConst(cl); + } + else if (cl.value == CONSTANT_DR) { + OptimizeRedundant(); + ReplaceWith(cDeg, *this); + } + else if (cl.value == CONSTANT_RD) { + OptimizeRedundant(); + ReplaceWith(cRad, *this); + } + else { + FinishConst(cl); + } } + + SortIfPossible(); + } }; void CodeTreeDataPtr::Shock() { - /* - PrepareForWrite(); - paramlist &p2 = (*this)->args; - for(paramlist::iterator i=p2.begin(); i!=p2.end(); ++i) - { - (*i)->data.Shock(); - } - */ + /* + PrepareForWrite(); + paramlist &p2 = (*this)->args; + for(paramlist::iterator i=p2.begin(); i!=p2.end(); ++i) + { + (*i)->data.Shock(); + } + */ } CodeTree::ConstList CodeTree::BuildConstList() { - ConstList result; - result.value = - result.voidvalue = GetOp()==cMul ? 1.0 : 0.0; + ConstList result; + result.value = result.voidvalue = GetOp() == cMul ? 1.0 : 0.0; - list &cp = result.cp; - for(pit b, a=GetBegin(); a!=GetEnd(); a=b) - { - SubTree &pa = *a; b=a; ++b; - if(!pa->IsImmed()) continue; - - double thisvalue = pa->GetImmed(); - if(thisvalue == result.voidvalue) - { - // This value is no good, forget it - Erase(a); - continue; - } - if(GetOp() == cMul) - result.value *= thisvalue; - else - result.value += thisvalue; - cp.push_back(a); + list &cp = result.cp; + for (pit b, a = GetBegin(); a != GetEnd(); a = b) { + SubTree &pa = *a; + b = a; + ++b; + if (!pa->IsImmed()) { + continue; } - if(GetOp() == cMul) - { - /* - Jos joku niista arvoista on -1 eika se ole ainoa arvo, - niin joku muu niista arvoista negatoidaan. - */ - for(bool done=false; cp.size() > 1 && !done; ) - { - done = true; - for(list::iterator b,a=cp.begin(); a!=cp.end(); a=b) - { - b=a; ++b; - if((**a)->GetImmed() == -1.0) - { - Erase(*a); - cp.erase(a); - - // take randomly something - (**cp.begin())->data->NegateImmed(); - if(cp.size() < 2)break; - done = false; - } - } - } - } - return result; -} - -void CodeTree::Assemble - (vector &byteCode, - vector &immed) const -{ - #define AddCmd(op) byteCode.push_back((op)) - #define AddConst(v) do { \ - byteCode.push_back(cImmed); \ - immed.push_back((v)); \ - } while(0) - if(IsVar()) - { - AddCmd(GetVar()); - return; + double thisvalue = pa->GetImmed(); + if (thisvalue == result.voidvalue) { + // This value is no good, forget it + Erase(a); + continue; } - if(IsImmed()) - { - AddConst(GetImmed()); - return; + if (GetOp() == cMul) { + result.value *= thisvalue; } - - switch(GetOp()) - { - case cAdd: - case cMul: - { - unsigned opcount = 0; - for(pcit a=GetBegin(); a!=GetEnd(); ++a) - { - const SubTree &pa = *a; - - if(opcount < 2) ++opcount; - - bool pnega = pa.getsign(); - - bool done = false; - if(pa->IsImmed()) - { - if(GetOp() == cMul - && pa->data->IsInverted() - && (pnega || opcount==2) - ) - { - CodeTree tmp = *pa; - tmp.data->InvertImmed(); - tmp.Assemble(byteCode, immed); - pnega = !pnega; - done = true; - } - else if(GetOp() == cAdd - && (pa->data->IsNegatedOriginal() - // || pa->GetImmed() < 0 - ) - && (pnega || opcount==2) - ) - { - CodeTree tmp = *pa; - tmp.data->NegateImmed(); - tmp.Assemble(byteCode, immed); - pnega = !pnega; - done = true; - } - } - if(!done) - pa->Assemble(byteCode, immed); - - if(opcount == 2) - { - unsigned tmpop = GetOp(); - if(pnega) // negate - { - tmpop = (tmpop == cMul) ? cDiv : cSub; - } - AddCmd(tmpop); - } - else if(pnega) - { - if(GetOp() == cMul) AddCmd(cInv); - else AddCmd(cNeg); - } - } + else { + result.value += thisvalue; + } + cp.push_back(a); + } + if (GetOp() == cMul) { + /* + Jos joku niista arvoista on -1 eika se ole ainoa arvo, + niin joku muu niista arvoista negatoidaan. + */ + for (bool done = false; cp.size() > 1 && !done;) { + done = true; + for (list::iterator b, a = cp.begin(); a != cp.end(); a = b) { + b = a; + ++b; + if ((**a)->GetImmed() == -1.0) { + Erase(*a); + cp.erase(a); + + // take randomly something + (**cp.begin())->data->NegateImmed(); + if (cp.size() < 2) { break; + } + done = false; } - case cIf: - { - // If the parameter amount is != 3, we're screwed. - getp0()->Assemble(byteCode, immed); - - unsigned ofs = byteCode.size(); - AddCmd(cIf); - AddCmd(0); // code index - AddCmd(0); // immed index - - getp1()->Assemble(byteCode, immed); - - byteCode[ofs+1] = byteCode.size()+2; - byteCode[ofs+2] = immed.size(); - - ofs = byteCode.size(); - AddCmd(cJump); - AddCmd(0); // code index - AddCmd(0); // immed index - - getp2()->Assemble(byteCode, immed); - - byteCode[ofs+1] = byteCode.size()-1; - byteCode[ofs+2] = immed.size(); - - break; + } + } + } + return result; +} + +void CodeTree::Assemble(vector &byteCode, vector &immed) const +{ +#define AddCmd(op) byteCode.push_back((op)) +#define AddConst(v) \ + do { \ + byteCode.push_back(cImmed); \ + immed.push_back((v)); \ + } while (0) + + if (IsVar()) { + AddCmd(GetVar()); + return; + } + if (IsImmed()) { + AddConst(GetImmed()); + return; + } + + switch (GetOp()) { + case cAdd: + case cMul: { + unsigned opcount = 0; + for (pcit a = GetBegin(); a != GetEnd(); ++a) { + const SubTree &pa = *a; + + if (opcount < 2) { + ++opcount; + } + + bool pnega = pa.getsign(); + + bool done = false; + if (pa->IsImmed()) { + if (GetOp() == cMul && pa->data->IsInverted() && (pnega || opcount == 2)) { + CodeTree tmp = *pa; + tmp.data->InvertImmed(); + tmp.Assemble(byteCode, immed); + pnega = !pnega; + done = true; } - case cFCall: - { - // If the parameter count is invalid, we're screwed. - for(pcit a=GetBegin(); a!=GetEnd(); ++a) - { - const SubTree &pa = *a; - pa->Assemble(byteCode, immed); - } - AddCmd(GetOp()); - AddCmd(data->GetFuncNo()); - break; + else if (GetOp() == cAdd && + (pa->data->IsNegatedOriginal() + // || pa->GetImmed() < 0 + ) && + (pnega || opcount == 2)) { + CodeTree tmp = *pa; + tmp.data->NegateImmed(); + tmp.Assemble(byteCode, immed); + pnega = !pnega; + done = true; } - case cPCall: + } + if (!done) { + pa->Assemble(byteCode, immed); + } + + if (opcount == 2) { + unsigned tmpop = GetOp(); + if (pnega) // negate { - // If the parameter count is invalid, we're screwed. - for(pcit a=GetBegin(); a!=GetEnd(); ++a) - { - const SubTree &pa = *a; - pa->Assemble(byteCode, immed); - } - AddCmd(GetOp()); - AddCmd(data->GetFuncNo()); - break; + tmpop = (tmpop == cMul) ? cDiv : cSub; } - default: - { - // If the parameter count is invalid, we're screwed. - for(pcit a=GetBegin(); a!=GetEnd(); ++a) - { - const SubTree &pa = *a; - pa->Assemble(byteCode, immed); - } - AddCmd(GetOp()); - break; + AddCmd(tmpop); + } + else if (pnega) { + if (GetOp() == cMul) { + AddCmd(cInv); } - } + else { + AddCmd(cNeg); + } + } + } + break; + } + case cIf: { + // If the parameter amount is != 3, we're screwed. + getp0()->Assemble(byteCode, immed); + + unsigned ofs = byteCode.size(); + AddCmd(cIf); + AddCmd(0); // code index + AddCmd(0); // immed index + + getp1()->Assemble(byteCode, immed); + + byteCode[ofs + 1] = byteCode.size() + 2; + byteCode[ofs + 2] = immed.size(); + + ofs = byteCode.size(); + AddCmd(cJump); + AddCmd(0); // code index + AddCmd(0); // immed index + + getp2()->Assemble(byteCode, immed); + + byteCode[ofs + 1] = byteCode.size() - 1; + byteCode[ofs + 2] = immed.size(); + + break; + } + case cFCall: { + // If the parameter count is invalid, we're screwed. + for (pcit a = GetBegin(); a != GetEnd(); ++a) { + const SubTree &pa = *a; + pa->Assemble(byteCode, immed); + } + AddCmd(GetOp()); + AddCmd(data->GetFuncNo()); + break; + } + case cPCall: { + // If the parameter count is invalid, we're screwed. + for (pcit a = GetBegin(); a != GetEnd(); ++a) { + const SubTree &pa = *a; + pa->Assemble(byteCode, immed); + } + AddCmd(GetOp()); + AddCmd(data->GetFuncNo()); + break; + } + default: { + // If the parameter count is invalid, we're screwed. + for (pcit a = GetBegin(); a != GetEnd(); ++a) { + const SubTree &pa = *a; + pa->Assemble(byteCode, immed); + } + AddCmd(GetOp()); + break; + } + } } void CodeTree::Optimize() { - // Phase: - // Phase 0: Do local optimizations. - // Phase 1: Optimize each. - // Phase 2: Do local optimizations again. - - for(unsigned phase=0; phase<=2; ++phase) - { - if(phase == 1) - { - // Optimize each parameter. - for(pit a=GetBegin(); a!=GetEnd(); ++a) - { - (*a)->Optimize(); - CHECKCONSTNEG(*a, GetOp()); - } - continue; - } - if(phase == 0 || phase == 2) - { - // Do local optimizations. - - OptimizeConstantMath1(); - OptimizeLogarithm(); - OptimizeFunctionCalls(); - OptimizeExponents(); - OptimizeLinearExplode(); - OptimizePascal(); - - /* Optimization paths: - - doublenegations= - redundant= * doublenegations - conflict= * redundant - addmulflat= - constantmath1= addmulflat * conflict - linearcombine= conflict * addmulflat(1) redundant(1) - powmuladd= - exponents= linearcombine * powmuladd conflict(1) - logarithm= exponents * - functioncalls= IDLE - linearexplode= IDLE - pascal= IDLE - - * = actions here - (1) = only if made changes - */ - } + // Phase: + // Phase 0: Do local optimizations. + // Phase 1: Optimize each. + // Phase 2: Do local optimizations again. + + for (unsigned phase = 0; phase <= 2; ++phase) { + if (phase == 1) { + // Optimize each parameter. + for (pit a = GetBegin(); a != GetEnd(); ++a) { + (*a)->Optimize(); + CHECKCONSTNEG(*a, GetOp()); + } + continue; + } + if (phase == 0 || phase == 2) { + // Do local optimizations. + + OptimizeConstantMath1(); + OptimizeLogarithm(); + OptimizeFunctionCalls(); + OptimizeExponents(); + OptimizeLinearExplode(); + OptimizePascal(); + + /* Optimization paths: + + doublenegations= + redundant= * doublenegations + conflict= * redundant + addmulflat= + constantmath1= addmulflat * conflict + linearcombine= conflict * addmulflat(1) redundant(1) + powmuladd= + exponents= linearcombine * powmuladd conflict(1) + logarithm= exponents * + functioncalls= IDLE + linearexplode= IDLE + pascal= IDLE + + * = actions here + (1) = only if made changes + */ + } + } +} + +bool CodeTree::operator==(const CodeTree &b) const +{ + if (GetOp() != b.GetOp()) { + return false; + } + if (IsImmed()) { + if (GetImmed() != b.GetImmed()) { + return false; } + } + if (IsVar()) { + if (GetVar() != b.GetVar()) { + return false; + } + } + if (data->IsFunc()) { + if (data->GetFuncNo() != b.data->GetFuncNo()) { + return false; + } + } + return data->args == b.data->args; } - -bool CodeTree::operator== (const CodeTree& b) const -{ - if(GetOp() != b.GetOp()) return false; - if(IsImmed()) if(GetImmed() != b.GetImmed()) return false; - if(IsVar()) if(GetVar() != b.GetVar()) return false; - if(data->IsFunc()) - if(data->GetFuncNo() != b.data->GetFuncNo()) return false; - return data->args == b.data->args; -} - -bool CodeTree::operator< (const CodeTree& b) const +bool CodeTree::operator<(const CodeTree &b) const { - if(GetArgCount() != b.GetArgCount()) - return GetArgCount() > b.GetArgCount(); - - if(GetOp() != b.GetOp()) - { - // sort immeds last - if(IsImmed() != b.IsImmed()) return IsImmed() < b.IsImmed(); + if (GetArgCount() != b.GetArgCount()) { + return GetArgCount() > b.GetArgCount(); + } - return GetOp() < b.GetOp(); + if (GetOp() != b.GetOp()) { + // sort immeds last + if (IsImmed() != b.IsImmed()) { + return IsImmed() < b.IsImmed(); } - if(IsImmed()) - { - if(GetImmed() != b.GetImmed()) return GetImmed() < b.GetImmed(); - } - if(IsVar() && GetVar() != b.GetVar()) - { - return GetVar() < b.GetVar(); - } - if(data->IsFunc() && data->GetFuncNo() != b.data->GetFuncNo()) - { - return data->GetFuncNo() < b.data->GetFuncNo(); + return GetOp() < b.GetOp(); + } + + if (IsImmed()) { + if (GetImmed() != b.GetImmed()) { + return GetImmed() < b.GetImmed(); } + } + if (IsVar() && GetVar() != b.GetVar()) { + return GetVar() < b.GetVar(); + } + if (data->IsFunc() && data->GetFuncNo() != b.data->GetFuncNo()) { + return data->GetFuncNo() < b.data->GetFuncNo(); + } - pcit i = GetBegin(), j = b.GetBegin(); - for(; i != GetEnd(); ++i, ++j) - { - const SubTree &pa = *i, &pb = *j; + pcit i = GetBegin(), j = b.GetBegin(); + for (; i != GetEnd(); ++i, ++j) { + const SubTree &pa = *i, &pb = *j; - if(!(pa == pb)) - return pa < pb; + if (!(pa == pb)) { + return pa < pb; } - return false; + } + return false; } - bool IsNegate(const SubTree &p1, const SubTree &p2) /*const */ { - if(p1->IsImmed() && p2->IsImmed()) - { - return p1->GetImmed() == -p2->GetImmed(); - } - if(p1.getsign() == p2.getsign()) return false; - return *p1 == *p2; + if (p1->IsImmed() && p2->IsImmed()) { + return p1->GetImmed() == -p2->GetImmed(); + } + if (p1.getsign() == p2.getsign()) { + return false; + } + return *p1 == *p2; } bool IsInverse(const SubTree &p1, const SubTree &p2) /*const*/ { - if(p1->IsImmed() && p2->IsImmed()) - { - // FIXME: potential divide by zero. - return p1->GetImmed() == 1.0 / p2->GetImmed(); - } - if(p1.getsign() == p2.getsign()) return false; - return *p1 == *p2; + if (p1->IsImmed() && p2->IsImmed()) { + // FIXME: potential divide by zero. + return p1->GetImmed() == 1.0 / p2->GetImmed(); + } + if (p1.getsign() == p2.getsign()) { + return false; + } + return *p1 == *p2; } -SubTree::SubTree() : tree(new CodeTree), sign(false) -{ -} +SubTree::SubTree() : tree(new CodeTree), sign(false) {} -SubTree::SubTree(const SubTree &b) : tree(new CodeTree(*b.tree)), sign(b.sign) -{ -} +SubTree::SubTree(const SubTree &b) : tree(new CodeTree(*b.tree)), sign(b.sign) {} -#define SubTreeDecl(p1, p2) \ - SubTree::SubTree p1 : tree(new CodeTree p2), sign(false) { } +#define SubTreeDecl(p1, p2) \ + SubTree::SubTree p1 : tree(new CodeTree p2), sign(false) {} -SubTreeDecl( (const CodeTree &b), (b) ) -SubTreeDecl( (double value), (value) ) +SubTreeDecl((const CodeTree &b), (b)) SubTreeDecl((double value), (value)) #undef SubTreeDecl -SubTree::~SubTree() + SubTree::~SubTree() { - delete tree; tree=0; + delete tree; + tree = 0; } -const SubTree &SubTree::operator= (const SubTree &b) +const SubTree &SubTree::operator=(const SubTree &b) { - sign = b.sign; - CodeTree *oldtree = tree; - tree = new CodeTree(*b.tree); - delete oldtree; - return *this; + sign = b.sign; + CodeTree *oldtree = tree; + tree = new CodeTree(*b.tree); + delete oldtree; + return *this; } -const SubTree &SubTree::operator= (const CodeTree &b) +const SubTree &SubTree::operator=(const CodeTree &b) { - sign = false; - CodeTree *oldtree = tree; - tree = new CodeTree(b); - delete oldtree; - return *this; + sign = false; + CodeTree *oldtree = tree; + tree = new CodeTree(b); + delete oldtree; + return *this; } -bool SubTree::operator< (const SubTree& b) const +bool SubTree::operator<(const SubTree &b) const { - if(getsign() != b.getsign()) return getsign() < b.getsign(); - return *tree < *b.tree; -} -bool SubTree::operator== (const SubTree& b) const -{ - return sign == b.sign && *tree == *b.tree; + if (getsign() != b.getsign()) { + return getsign() < b.getsign(); + } + return *tree < *b.tree; } +bool SubTree::operator==(const SubTree &b) const { return sign == b.sign && *tree == *b.tree; } void SubTree::Negate() // Note: Parent must be cAdd { - flipsign(); - CheckConstNeg(); + flipsign(); + CheckConstNeg(); } void SubTree::CheckConstNeg() { - if(tree->IsImmed() && getsign()) - { - tree->NegateImmed(); - sign = false; - } + if (tree->IsImmed() && getsign()) { + tree->NegateImmed(); + sign = false; + } } void SubTree::Invert() // Note: Parent must be cMul { - flipsign(); - CheckConstInv(); + flipsign(); + CheckConstInv(); } void SubTree::CheckConstInv() { - if(tree->IsImmed() && getsign()) - { - tree->InvertImmed(); - sign = false; - } + if (tree->IsImmed() && getsign()) { + tree->InvertImmed(); + sign = false; + } } -}//namespace +} // namespace void FunctionParser::MakeTree(void *r) const { - // Dirty hack. Should be fixed. - CodeTree* result = static_cast(r); - - vector stack(1); - - #define GROW(n) do { \ - stacktop += n; \ - if(stack.size() <= stacktop) stack.resize(stacktop+1); \ - } while(0) - - #define EAT(n, opcode) do { \ - unsigned newstacktop = stacktop-n; \ - stack[stacktop].SetOp((opcode)); \ - for(unsigned a=0, b=(n); a labels; - - const unsigned* const ByteCode = data->ByteCode; - const unsigned ByteCodeSize = data->ByteCodeSize; - const double* const Immed = data->Immed; - - for(unsigned IP=0, DP=0; ; ++IP) - { - while(labels.size() > 0 - && *labels.begin() == IP) - { - // The "else" of an "if" ends here - EAT(3, cIf); - labels.erase(labels.begin()); + // Dirty hack. Should be fixed. + CodeTree *result = static_cast(r); + + vector stack(1); + +#define GROW(n) \ + do { \ + stacktop += n; \ + if (stack.size() <= stacktop) \ + stack.resize(stacktop + 1); \ + } while (0) + +#define EAT(n, opcode) \ + do { \ + unsigned newstacktop = stacktop - n; \ + stack[stacktop].SetOp((opcode)); \ + for (unsigned a = 0, b = (n); a < b; ++a) \ + stack[stacktop].AddParam(stack[newstacktop + a]); \ + stack.erase(stack.begin() + newstacktop, stack.begin() + stacktop); \ + stacktop = newstacktop; \ + GROW(1); \ + } while (0) + +#define ADDCONST(n) \ + do { \ + stack[stacktop].SetImmed((n)); \ + GROW(1); \ + } while (0) + + unsigned stacktop = 0; + + list labels; + + const unsigned *const ByteCode = data->ByteCode; + const unsigned ByteCodeSize = data->ByteCodeSize; + const double *const Immed = data->Immed; + + for (unsigned IP = 0, DP = 0;; ++IP) { + while (labels.size() > 0 && *labels.begin() == IP) { + // The "else" of an "if" ends here + EAT(3, cIf); + labels.erase(labels.begin()); + } + + if (IP >= ByteCodeSize) { + break; + } + + unsigned opcode = ByteCode[IP]; + + if (opcode == cIf) { + IP += 2; + } + else if (opcode == cJump) { + labels.push_front(ByteCode[IP + 1] + 1); + IP += 2; + } + else if (opcode == cImmed) { + ADDCONST(Immed[DP++]); + } + else if (opcode < VarBegin) { + switch (opcode) { + // Unary operators + case cNeg: { + EAT(1, cAdd); // Unary minus is negative adding. + stack[stacktop - 1].getp0().Negate(); + break; + } + // Binary operators + case cSub: { + EAT(2, cAdd); // Minus is negative adding + stack[stacktop - 1].getp1().Negate(); + break; + } + case cDiv: { + EAT(2, cMul); // Divide is inverse multiply + stack[stacktop - 1].getp1().Invert(); + break; + } + + // ADD ALL TWO PARAMETER NON-FUNCTIONS HERE + case cAdd: + case cMul: + case cMod: + case cPow: + case cEqual: + case cLess: + case cGreater: + case cAnd: + case cOr: + EAT(2, opcode); + break; + + case cFCall: { + unsigned index = ByteCode[++IP]; + unsigned params = data->FuncPtrs[index].params; + EAT(params, opcode); + stack[stacktop - 1].data->SetFuncNo(index); + break; + } + case cPCall: { + unsigned index = ByteCode[++IP]; + unsigned params = data->FuncParsers[index]->data->varAmount; + EAT(params, opcode); + stack[stacktop - 1].data->SetFuncNo(index); + break; + } + + // Converted to cMul on fly + case cDeg: + ADDCONST(CONSTANT_DR); + EAT(2, cMul); + break; + + // Converted to cMul on fly + case cRad: + ADDCONST(CONSTANT_RD); + EAT(2, cMul); + break; + + // Functions + default: { + const FuncDefinition &func = Functions[opcode - cAbs]; + + unsigned paramcount = func.params; +#ifndef DISABLE_EVAL + if (opcode == cEval) { + paramcount = data->varAmount; } - - if(IP >= ByteCodeSize) - { - break; +#endif + if (opcode == cSqrt) { + // Converted on fly: sqrt(x) = x^0.5 + opcode = cPow; + paramcount = 2; + ADDCONST(0.5); } - - unsigned opcode = ByteCode[IP]; - - if(opcode == cIf) - { - IP += 2; + if (opcode == cExp) { + // Converted on fly: exp(x) = CONSTANT_E^x + + opcode = cPow; + paramcount = 2; + // reverse the parameters... kludgey + stack[stacktop] = stack[stacktop - 1]; + stack[stacktop - 1].SetImmed(CONSTANT_E); + GROW(1); } - else if(opcode == cJump) - { - labels.push_front(ByteCode[IP+1]+1); - IP += 2; + bool do_inv = false; + if (opcode == cCot) { + do_inv = true; + opcode = cTan; } - else if(opcode == cImmed) - { - ADDCONST(Immed[DP++]); + if (opcode == cCsc) { + do_inv = true; + opcode = cSin; } - else if(opcode < VarBegin) - { - switch(opcode) - { - // Unary operators - case cNeg: - { - EAT(1, cAdd); // Unary minus is negative adding. - stack[stacktop-1].getp0().Negate(); - break; - } - // Binary operators - case cSub: - { - EAT(2, cAdd); // Minus is negative adding - stack[stacktop-1].getp1().Negate(); - break; - } - case cDiv: - { - EAT(2, cMul); // Divide is inverse multiply - stack[stacktop-1].getp1().Invert(); - break; - } - - // ADD ALL TWO PARAMETER NON-FUNCTIONS HERE - case cAdd: case cMul: - case cMod: case cPow: - case cEqual: case cLess: case cGreater: - case cAnd: case cOr: - EAT(2, opcode); - break; - - case cFCall: - { - unsigned index = ByteCode[++IP]; - unsigned params = data->FuncPtrs[index].params; - EAT(params, opcode); - stack[stacktop-1].data->SetFuncNo(index); - break; - } - case cPCall: - { - unsigned index = ByteCode[++IP]; - unsigned params = - data->FuncParsers[index]->data->varAmount; - EAT(params, opcode); - stack[stacktop-1].data->SetFuncNo(index); - break; - } - - // Converted to cMul on fly - case cDeg: - ADDCONST(CONSTANT_DR); - EAT(2, cMul); - break; - - // Converted to cMul on fly - case cRad: - ADDCONST(CONSTANT_RD); - EAT(2, cMul); - break; - - // Functions - default: - { - const FuncDefinition& func = Functions[opcode-cAbs]; - - unsigned paramcount = func.params; -#ifndef DISABLE_EVAL - if(opcode == cEval) paramcount = data->varAmount; -#endif - if(opcode == cSqrt) - { - // Converted on fly: sqrt(x) = x^0.5 - opcode = cPow; - paramcount = 2; - ADDCONST(0.5); - } - if(opcode == cExp) - { - // Converted on fly: exp(x) = CONSTANT_E^x - - opcode = cPow; - paramcount = 2; - // reverse the parameters... kludgey - stack[stacktop] = stack[stacktop-1]; - stack[stacktop-1].SetImmed(CONSTANT_E); - GROW(1); - } - bool do_inv = false; - if(opcode == cCot) { do_inv = true; opcode = cTan; } - if(opcode == cCsc) { do_inv = true; opcode = cSin; } - if(opcode == cSec) { do_inv = true; opcode = cCos; } - - bool do_log10 = false; - if(opcode == cLog10) - { - // Converted on fly: log10(x) = log(x) * CONSTANT_L10I - opcode = cLog; - do_log10 = true; - } - EAT(paramcount, opcode); - if(do_log10) - { - ADDCONST(CONSTANT_L10I); - EAT(2, cMul); - } - if(do_inv) - { - // Unary cMul, inverted. No need for "1.0" - EAT(1, cMul); - stack[stacktop-1].getp0().Invert(); - } - break; - } - } + if (opcode == cSec) { + do_inv = true; + opcode = cCos; } - else - { - stack[stacktop].SetVar(opcode); - GROW(1); + + bool do_log10 = false; + if (opcode == cLog10) { + // Converted on fly: log10(x) = log(x) * CONSTANT_L10I + opcode = cLog; + do_log10 = true; + } + EAT(paramcount, opcode); + if (do_log10) { + ADDCONST(CONSTANT_L10I); + EAT(2, cMul); + } + if (do_inv) { + // Unary cMul, inverted. No need for "1.0" + EAT(1, cMul); + stack[stacktop - 1].getp0().Invert(); } + break; + } + } } - - if(!stacktop) - { - // ERROR: Stack does not have any values! - return; + else { + stack[stacktop].SetVar(opcode); + GROW(1); } + } - --stacktop; // Ignore the last element, it is always nop (cAdd). + if (!stacktop) { + // ERROR: Stack does not have any values! + return; + } - if(stacktop > 0) - { - // ERROR: Stack has too many values! - return; - } + --stacktop; // Ignore the last element, it is always nop (cAdd). + + if (stacktop > 0) { + // ERROR: Stack has too many values! + return; + } - // Okay, the tree is now stack[0] - *result = stack[0]; + // Okay, the tree is now stack[0] + *result = stack[0]; } void FunctionParser::Optimize() { - copyOnWrite(); + copyOnWrite(); - CodeTree tree; - MakeTree(&tree); + CodeTree tree; + MakeTree(&tree); - // Do all sorts of optimizations - tree.Optimize(); - // Last changes before assembly - tree.FinalOptimize(); + // Do all sorts of optimizations + tree.Optimize(); + // Last changes before assembly + tree.FinalOptimize(); - // Now rebuild from the tree. + // Now rebuild from the tree. - vector byteCode; - vector immed; + vector byteCode; + vector immed; #if 0 byteCode.resize(Comp.ByteCodeSize); @@ -3357,34 +3495,36 @@ void FunctionParser::Optimize() immed.resize(Comp.ImmedSize); for(unsigned a=0; aByteCode; data->ByteCode = 0; - if((data->ByteCodeSize = byteCode.size()) > 0) - { - data->ByteCode = new unsigned[data->ByteCodeSize]; - for(unsigned a=0; aByteCode[a] = byteCode[a]; + delete[] data->ByteCode; + data->ByteCode = 0; + if ((data->ByteCodeSize = byteCode.size()) > 0) { + data->ByteCode = new unsigned[data->ByteCodeSize]; + for (unsigned a = 0; a < byteCode.size(); ++a) { + data->ByteCode[a] = byteCode[a]; } + } - delete[] data->Immed; data->Immed = 0; - if((data->ImmedSize = immed.size()) > 0) - { - data->Immed = new double[data->ImmedSize]; - for(unsigned a=0; aImmed[a] = immed[a]; + delete[] data->Immed; + data->Immed = 0; + if ((data->ImmedSize = immed.size()) > 0) { + data->Immed = new double[data->ImmedSize]; + for (unsigned a = 0; a < immed.size(); ++a) { + data->Immed[a] = immed[a]; } + } } - #else /* !SUPPORT_OPTIMIZER */ /* keep the linker happy */ void FunctionParser::MakeTree(void *) const {} void FunctionParser::Optimize() { - // Do nothing if no optimizations are supported. + // Do nothing if no optimizations are supported. } #endif diff --git a/src/labenski/src/fparser.hh b/src/labenski/src/fparser.hh index e777f55c4..5ba148f8d 100644 --- a/src/labenski/src/fparser.hh +++ b/src/labenski/src/fparser.hh @@ -22,141 +22,137 @@ #include #endif -class FunctionParser -{ +class FunctionParser { public: - enum ParseErrorType - { - SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH, - EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS, - ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC, - FP_NO_ERROR - }; + enum ParseErrorType { + SYNTAX_ERROR = 0, + MISM_PARENTH, + MISSING_PARENTH, + EMPTY_PARENTH, + EXPECT_OPERATOR, + OUT_OF_MEMORY, + UNEXPECTED_ERROR, + INVALID_VARS, + ILL_PARAMS_AMOUNT, + PREMATURE_EOS, + EXPECT_PARENTH_FUNC, + FP_NO_ERROR + }; - int Parse(const std::string& Function, const std::string& Vars, - bool useDegrees = false); - const char* ErrorMsg() const; - inline ParseErrorType GetParseErrorType() const { return parseErrorType; } + int Parse(const std::string &Function, const std::string &Vars, bool useDegrees = false); + const char *ErrorMsg() const; + inline ParseErrorType GetParseErrorType() const { return parseErrorType; } - double Eval(const double* Vars); - inline int EvalError() const { return evalErrorType; } + double Eval(const double *Vars); + inline int EvalError() const { return evalErrorType; } - bool AddConstant(const std::string& name, double value); + bool AddConstant(const std::string &name, double value); - typedef double (*FunctionPtr)(const double*); + typedef double (*FunctionPtr)(const double *); - bool AddFunction(const std::string& name, - FunctionPtr, unsigned paramsAmount); - bool AddFunction(const std::string& name, FunctionParser&); + bool AddFunction(const std::string &name, FunctionPtr, unsigned paramsAmount); + bool AddFunction(const std::string &name, FunctionParser &); - void Optimize(); + void Optimize(); - int GetNumberVariables() const { return data->varAmount; } - bool GetUseDegrees() const { return data->useDegreeConversion; } + int GetNumberVariables() const { return data->varAmount; } + bool GetUseDegrees() const { return data->useDegreeConversion; } - FunctionParser(); - ~FunctionParser(); + FunctionParser(); + ~FunctionParser(); - // Copy constructor and assignment operator (implemented using the - // copy-on-write technique for efficiency): - FunctionParser(const FunctionParser&); - FunctionParser& operator=(const FunctionParser&); + // Copy constructor and assignment operator (implemented using the + // copy-on-write technique for efficiency): + FunctionParser(const FunctionParser &); + FunctionParser &operator=(const FunctionParser &); #ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT - // For debugging purposes only: - void PrintByteCode(std::ostream& dest) const; + // For debugging purposes only: + void PrintByteCode(std::ostream &dest) const; #endif - - -//======================================================================== + //======================================================================== private: -//======================================================================== - - -// Private data: -// ------------ - ParseErrorType parseErrorType; - int evalErrorType; + //======================================================================== - struct Data - { - unsigned referenceCounter; + // Private data: + // ------------ + ParseErrorType parseErrorType; + int evalErrorType; - int varAmount; - bool useDegreeConversion; + struct Data { + unsigned referenceCounter; - typedef std::map VarMap_t; - VarMap_t Variables; + int varAmount; + bool useDegreeConversion; - typedef std::map ConstMap_t; - ConstMap_t Constants; + typedef std::map VarMap_t; + VarMap_t Variables; - VarMap_t FuncPtrNames; - struct FuncPtrData - { - FunctionPtr ptr; unsigned params; - FuncPtrData(FunctionPtr p, unsigned par): ptr(p), params(par) {} - }; - std::vector FuncPtrs; + typedef std::map ConstMap_t; + ConstMap_t Constants; - VarMap_t FuncParserNames; - std::vector FuncParsers; - - unsigned* ByteCode; - unsigned ByteCodeSize; - double* Immed; - unsigned ImmedSize; - double* Stack; - unsigned StackSize; - - Data(); - ~Data(); - Data(const Data&); - - Data& operator=(const Data&); // not implemented on purpose + VarMap_t FuncPtrNames; + struct FuncPtrData { + FunctionPtr ptr; + unsigned params; + FuncPtrData(FunctionPtr p, unsigned par) : ptr(p), params(par) {} }; - - Data* data; - - // Temp data needed in Compile(): - unsigned StackPtr; - std::vector* tempByteCode; - std::vector* tempImmed; - - -// Private methods: -// --------------- - inline void copyOnWrite(); - - - bool checkRecursiveLinking(const FunctionParser*) const; - - bool isValidName(const std::string&) const; - Data::VarMap_t::const_iterator FindVariable(const char*, - const Data::VarMap_t&) const; - Data::ConstMap_t::const_iterator FindConstant(const char*) const; - int CheckSyntax(const char*); - bool Compile(const char*); - bool IsVariable(int); - void AddCompiledByte(unsigned); - void AddImmediate(double); - void AddFunctionOpcode(unsigned); - inline void incStackPtr(); - int CompileIf(const char*, int); - int CompileFunctionParams(const char*, int, unsigned); - int CompileElement(const char*, int); - int CompilePow(const char*, int); - int CompileUnaryMinus(const char*, int); - int CompileMult(const char*, int); - int CompileAddition(const char*, int); - int CompileComparison(const char*, int); - int CompileAnd(const char*, int); - int CompileOr(const char*, int); - int CompileExpression(const char*, int, bool=false); - - - void MakeTree(void*) const; + std::vector FuncPtrs; + + VarMap_t FuncParserNames; + std::vector FuncParsers; + + unsigned *ByteCode; + unsigned ByteCodeSize; + double *Immed; + unsigned ImmedSize; + double *Stack; + unsigned StackSize; + + Data(); + ~Data(); + Data(const Data &); + + Data &operator=(const Data &); // not implemented on purpose + }; + + Data *data; + + // Temp data needed in Compile(): + unsigned StackPtr; + std::vector *tempByteCode; + std::vector *tempImmed; + + // Private methods: + // --------------- + inline void copyOnWrite(); + + bool checkRecursiveLinking(const FunctionParser *) const; + + bool isValidName(const std::string &) const; + Data::VarMap_t::const_iterator FindVariable(const char *, const Data::VarMap_t &) const; + Data::ConstMap_t::const_iterator FindConstant(const char *) const; + int CheckSyntax(const char *); + bool Compile(const char *); + bool IsVariable(int); + void AddCompiledByte(unsigned); + void AddImmediate(double); + void AddFunctionOpcode(unsigned); + inline void incStackPtr(); + int CompileIf(const char *, int); + int CompileFunctionParams(const char *, int, unsigned); + int CompileElement(const char *, int); + int CompilePow(const char *, int); + int CompileUnaryMinus(const char *, int); + int CompileMult(const char *, int); + int CompileAddition(const char *, int); + int CompileComparison(const char *, int); + int CompileAnd(const char *, int); + int CompileOr(const char *, int); + int CompileExpression(const char *, int, bool = false); + + void MakeTree(void *) const; }; #endif diff --git a/src/labenski/src/genergdi.cpp b/src/labenski/src/genergdi.cpp index ae74c64b0..2718d7d4a 100644 --- a/src/labenski/src/genergdi.cpp +++ b/src/labenski/src/genergdi.cpp @@ -12,15 +12,15 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #include "wx/wxthings/genergdi.h" #include "wx/tokenzr.h" const wxGenericColour wxNullGenericColour; -const wxGenericPen wxNullGenericPen; -const wxGenericBrush wxNullGenericBrush; +const wxGenericPen wxNullGenericPen; +const wxGenericBrush wxNullGenericBrush; #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArrayGenericColour) WX_DEFINE_OBJARRAY(wxArrayGenericPen) @@ -31,167 +31,163 @@ WX_DEFINE_OBJARRAY(wxArrayGenericBrush) //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxGenericColour, wxObject) -class wxGenericColourRefData : public wxObjectRefData -{ +class wxGenericColourRefData : public wxObjectRefData { public: - explicit wxGenericColourRefData(unsigned char r = 0, unsigned char g = 0, - unsigned char b = 0, unsigned char a = 255) - : wxObjectRefData(), m_r(r), m_g(g), m_b(b), m_a(a) {} - - wxGenericColourRefData( const wxGenericColourRefData& data ) - : wxObjectRefData(), m_r(data.m_r), m_g(data.m_g), m_b(data.m_b), m_a(data.m_a) {} - - unsigned char m_r, m_g, m_b, m_a; + explicit wxGenericColourRefData(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, + unsigned char a = 255) + : wxObjectRefData(), m_r(r), m_g(g), m_b(b), m_a(a) + { + } + + wxGenericColourRefData(const wxGenericColourRefData &data) + : wxObjectRefData(), m_r(data.m_r), m_g(data.m_g), m_b(data.m_b), m_a(data.m_a) + { + } + + unsigned char m_r, m_g, m_b, m_a; }; -#define M_GCOLOURDATA ((wxGenericColourRefData*)m_refData) +#define M_GCOLOURDATA ((wxGenericColourRefData *)m_refData) //---------------------------------------------------------------------------- -wxObjectRefData *wxGenericColour::CreateRefData() const -{ - return new wxGenericColourRefData; -} +wxObjectRefData *wxGenericColour::CreateRefData() const { return new wxGenericColourRefData; } wxObjectRefData *wxGenericColour::CloneRefData(const wxObjectRefData *data) const { - return new wxGenericColourRefData(*(const wxGenericColourRefData *)data); + return new wxGenericColourRefData(*(const wxGenericColourRefData *)data); } -void wxGenericColour::Create( const wxGenericColour& c ) -{ - Ref(c); -} -void wxGenericColour::Create( const wxColour& c) +void wxGenericColour::Create(const wxGenericColour &c) { Ref(c); } +void wxGenericColour::Create(const wxColour &c) { - UnRef(); - m_refData = new wxGenericColourRefData; - Set(c); + UnRef(); + m_refData = new wxGenericColourRefData; + Set(c); } -void wxGenericColour::Create( unsigned char red, unsigned char green, - unsigned char blue, unsigned char alpha ) +void wxGenericColour::Create(unsigned char red, unsigned char green, unsigned char blue, + unsigned char alpha) { - UnRef(); - m_refData = new wxGenericColourRefData(red, green, blue, alpha); + UnRef(); + m_refData = new wxGenericColourRefData(red, green, blue, alpha); } -void wxGenericColour::CreateABGR( unsigned long colABGR ) +void wxGenericColour::CreateABGR(unsigned long colABGR) { - UnRef(); - m_refData = new wxGenericColourRefData; - SetABGR(colABGR); + UnRef(); + m_refData = new wxGenericColourRefData; + SetABGR(colABGR); } -void wxGenericColour::CreateARGB( unsigned long colARGB ) +void wxGenericColour::CreateARGB(unsigned long colARGB) { - UnRef(); - m_refData = new wxGenericColourRefData; - SetARGB(colARGB); + UnRef(); + m_refData = new wxGenericColourRefData; + SetARGB(colARGB); } -void wxGenericColour::Create( const wxString& colourName ) +void wxGenericColour::Create(const wxString &colourName) { - UnRef(); - m_refData = new wxGenericColourRefData; - Set(colourName); + UnRef(); + m_refData = new wxGenericColourRefData; + Set(colourName); } -void wxGenericColour::Set( const wxGenericColour &c ) +void wxGenericColour::Set(const wxGenericColour &c) { - wxCHECK_RET(Ok() && c.Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_r = c.GetRed(); - M_GCOLOURDATA->m_g = c.GetGreen(); - M_GCOLOURDATA->m_b = c.GetBlue(); - M_GCOLOURDATA->m_a = c.GetAlpha(); + wxCHECK_RET(Ok() && c.Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_r = c.GetRed(); + M_GCOLOURDATA->m_g = c.GetGreen(); + M_GCOLOURDATA->m_b = c.GetBlue(); + M_GCOLOURDATA->m_a = c.GetAlpha(); } -void wxGenericColour::Set( const wxColour& c ) +void wxGenericColour::Set(const wxColour &c) { - wxCHECK_RET(Ok() && c.Ok(), wxT("Invalid colour")); - M_GCOLOURDATA->m_r = c.Red(); - M_GCOLOURDATA->m_g = c.Green(); - M_GCOLOURDATA->m_b = c.Blue(); + wxCHECK_RET(Ok() && c.Ok(), wxT("Invalid colour")); + M_GCOLOURDATA->m_r = c.Red(); + M_GCOLOURDATA->m_g = c.Green(); + M_GCOLOURDATA->m_b = c.Blue(); } -void wxGenericColour::Set( unsigned char red, unsigned char green, - unsigned char blue, unsigned char alpha ) +void wxGenericColour::Set(unsigned char red, unsigned char green, unsigned char blue, + unsigned char alpha) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_r = red; - M_GCOLOURDATA->m_g = green; - M_GCOLOURDATA->m_b = blue; - M_GCOLOURDATA->m_a = alpha; + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_r = red; + M_GCOLOURDATA->m_g = green; + M_GCOLOURDATA->m_b = blue; + M_GCOLOURDATA->m_a = alpha; } -void wxGenericColour::SetABGR( unsigned long colABGR ) +void wxGenericColour::SetABGR(unsigned long colABGR) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_r = (unsigned char)(0xFF& colABGR); - M_GCOLOURDATA->m_g = (unsigned char)(0xFF&(colABGR >> 8)); - M_GCOLOURDATA->m_b = (unsigned char)(0xFF&(colABGR >> 16)); - M_GCOLOURDATA->m_a = (unsigned char)(0xFF&(colABGR >> 24)); + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_r = (unsigned char)(0xFF & colABGR); + M_GCOLOURDATA->m_g = (unsigned char)(0xFF & (colABGR >> 8)); + M_GCOLOURDATA->m_b = (unsigned char)(0xFF & (colABGR >> 16)); + M_GCOLOURDATA->m_a = (unsigned char)(0xFF & (colABGR >> 24)); } -void wxGenericColour::SetARGB( unsigned long colARGB ) +void wxGenericColour::SetARGB(unsigned long colARGB) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_b = (unsigned char)(0xFF& colARGB); - M_GCOLOURDATA->m_g = (unsigned char)(0xFF&(colARGB >> 8)); - M_GCOLOURDATA->m_r = (unsigned char)(0xFF&(colARGB >> 16)); - M_GCOLOURDATA->m_a = (unsigned char)(0xFF&(colARGB >> 24)); + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_b = (unsigned char)(0xFF & colARGB); + M_GCOLOURDATA->m_g = (unsigned char)(0xFF & (colARGB >> 8)); + M_GCOLOURDATA->m_r = (unsigned char)(0xFF & (colARGB >> 16)); + M_GCOLOURDATA->m_a = (unsigned char)(0xFF & (colARGB >> 24)); } -void wxGenericColour::Set( const wxString& colourName ) +void wxGenericColour::Set(const wxString &colourName) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - Set(wxColour(colourName)); + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + Set(wxColour(colourName)); } -void wxGenericColour::SetRed( unsigned char r ) +void wxGenericColour::SetRed(unsigned char r) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_r = r; + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_r = r; } -void wxGenericColour::SetGreen( unsigned char g ) +void wxGenericColour::SetGreen(unsigned char g) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_g = g; + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_g = g; } -void wxGenericColour::SetBlue( unsigned char b ) +void wxGenericColour::SetBlue(unsigned char b) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_b = b; + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_b = b; } -void wxGenericColour::SetAlpha( unsigned char a ) +void wxGenericColour::SetAlpha(unsigned char a) { - wxCHECK_RET(Ok(), wxT("Invalid generic colour")); - M_GCOLOURDATA->m_a = a; + wxCHECK_RET(Ok(), wxT("Invalid generic colour")); + M_GCOLOURDATA->m_a = a; } unsigned char wxGenericColour::GetRed() const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); - return M_GCOLOURDATA->m_r; + wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); + return M_GCOLOURDATA->m_r; } unsigned char wxGenericColour::GetGreen() const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); - return M_GCOLOURDATA->m_g; + wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); + return M_GCOLOURDATA->m_g; } unsigned char wxGenericColour::GetBlue() const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); - return M_GCOLOURDATA->m_b; + wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); + return M_GCOLOURDATA->m_b; } unsigned char wxGenericColour::GetAlpha() const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); - return M_GCOLOURDATA->m_a; + wxCHECK_MSG(Ok(), 0, wxT("Invalid generic colour")); + return M_GCOLOURDATA->m_a; } -bool wxGenericColour::IsSameAs( const wxGenericColour& c ) const +bool wxGenericColour::IsSameAs(const wxGenericColour &c) const { - wxCHECK_MSG(Ok() && c.Ok(), false, wxT("Invalid generic colour")); - wxGenericColourRefData *cData = (wxGenericColourRefData*)c.GetRefData(); - return (M_GCOLOURDATA->m_r == cData->m_r) && (M_GCOLOURDATA->m_g == cData->m_g) && - (M_GCOLOURDATA->m_b == cData->m_b) && (M_GCOLOURDATA->m_a == cData->m_a); + wxCHECK_MSG(Ok() && c.Ok(), false, wxT("Invalid generic colour")); + wxGenericColourRefData *cData = (wxGenericColourRefData *)c.GetRefData(); + return (M_GCOLOURDATA->m_r == cData->m_r) && (M_GCOLOURDATA->m_g == cData->m_g) && + (M_GCOLOURDATA->m_b == cData->m_b) && (M_GCOLOURDATA->m_a == cData->m_a); } -bool wxGenericColour::IsSameAs( const wxColour& c ) const +bool wxGenericColour::IsSameAs(const wxColour &c) const { - wxCHECK_MSG(Ok() && c.Ok(), false, wxT("Invalid colour")); - return (M_GCOLOURDATA->m_r == c.Red()) && - (M_GCOLOURDATA->m_g == c.Green()) && - (M_GCOLOURDATA->m_b == c.Blue()); + wxCHECK_MSG(Ok() && c.Ok(), false, wxT("Invalid colour")); + return (M_GCOLOURDATA->m_r == c.Red()) && (M_GCOLOURDATA->m_g == c.Green()) && + (M_GCOLOURDATA->m_b == c.Blue()); } // This code is assumed to be public domain, originally from Paul Bourke, July 1996 @@ -199,34 +195,34 @@ bool wxGenericColour::IsSameAs( const wxColour& c ) const wxGenericColour wxGenericColour::GetHotColdColour(double v) const { - wxGenericColour c(255, 255, 255); - const double vmin = 0.0, vmax = 255.0, dv = vmax - vmin; - - if (v < vmin) v = vmin; - if (v > vmax) v = vmax; - - if (v < (vmin + 0.25 * dv)) - { - c.SetRed(0); - c.SetGreen(int(vmax*(4.0 * (v - vmin) / dv) + 0.5)); - } - else if (v < (vmin + 0.5 * dv)) - { - c.SetRed(0); - c.SetBlue(int(vmax*(1.0 + 4.0 * (vmin + 0.25 * dv - v) / dv) + 0.5)); - } - else if (v < (vmin + 0.75 * dv)) - { - c.SetRed(int(vmax*(4.0 * (v - vmin - 0.5 * dv) / dv) + 0.5)); - c.SetBlue(0); - } - else - { - c.SetGreen(int(vmax*(1.0 + 4.0 * (vmin + 0.75 * dv - v) / dv) + 0.5)); - c.SetBlue(0); - } - - return c; + wxGenericColour c(255, 255, 255); + const double vmin = 0.0, vmax = 255.0, dv = vmax - vmin; + + if (v < vmin) { + v = vmin; + } + if (v > vmax) { + v = vmax; + } + + if (v < (vmin + 0.25 * dv)) { + c.SetRed(0); + c.SetGreen(int(vmax * (4.0 * (v - vmin) / dv) + 0.5)); + } + else if (v < (vmin + 0.5 * dv)) { + c.SetRed(0); + c.SetBlue(int(vmax * (1.0 + 4.0 * (vmin + 0.25 * dv - v) / dv) + 0.5)); + } + else if (v < (vmin + 0.75 * dv)) { + c.SetRed(int(vmax * (4.0 * (v - vmin - 0.5 * dv) / dv) + 0.5)); + c.SetBlue(0); + } + else { + c.SetGreen(int(vmax * (1.0 + 4.0 * (vmin + 0.75 * dv - v) / dv) + 0.5)); + c.SetBlue(0); + } + + return c; } /* wxString wxGenericColour::WriteString(const wxString& format) const @@ -254,245 +250,241 @@ bool wxGenericColour::ReadString(const wxString& str, const wxString& format) //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxGenericPen, wxObject) -class wxGenericPenRefData : public wxObjectRefData -{ +class wxGenericPenRefData : public wxObjectRefData { public: - explicit wxGenericPenRefData(int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, - wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND) - : wxObjectRefData(), m_width(width), m_style(style), - m_cap(cap), m_join(join), - m_dash_count(0), m_dash(NULL) {} - - wxGenericPenRefData(const wxGenericPenRefData& data) : wxObjectRefData(), - m_colour(data.m_colour), m_width(data.m_width), m_style(data.m_style), - m_cap(data.m_cap), m_join(data.m_join), - m_dash_count(data.m_dash_count), m_dash(NULL) - { - if (data.m_dash) - { - m_dash = (wxDash*)malloc(m_dash_count*sizeof(wxDash)); - memcpy(m_dash, data.m_dash, m_dash_count*sizeof(wxDash)); - } + explicit wxGenericPenRefData(int width = 1, wxPenStyle style = wxPENSTYLE_SOLID, + wxPenCap cap = wxCAP_ROUND, wxPenJoin join = wxJOIN_ROUND) + : wxObjectRefData(), m_width(width), m_style(style), m_cap(cap), m_join(join), m_dash_count(0), + m_dash(NULL) + { + } + + wxGenericPenRefData(const wxGenericPenRefData &data) + : wxObjectRefData(), m_colour(data.m_colour), m_width(data.m_width), m_style(data.m_style), + m_cap(data.m_cap), m_join(data.m_join), m_dash_count(data.m_dash_count), m_dash(NULL) + { + if (data.m_dash) { + m_dash = (wxDash *)malloc(m_dash_count * sizeof(wxDash)); + memcpy(m_dash, data.m_dash, m_dash_count * sizeof(wxDash)); } + } - ~wxGenericPenRefData() { if (m_dash) free(m_dash); } + ~wxGenericPenRefData() + { + if (m_dash) { + free(m_dash); + } + } - wxGenericColour m_colour; - int m_width; - wxPenStyle m_style; - wxPenCap m_cap; - wxPenJoin m_join; + wxGenericColour m_colour; + int m_width; + wxPenStyle m_style; + wxPenCap m_cap; + wxPenJoin m_join; - int m_dash_count; // don't arbitrarily adjust these! - wxDash *m_dash; + int m_dash_count; // don't arbitrarily adjust these! + wxDash *m_dash; }; -#define M_GPENDATA ((wxGenericPenRefData*)m_refData) +#define M_GPENDATA ((wxGenericPenRefData *)m_refData) //---------------------------------------------------------------------------- -wxObjectRefData *wxGenericPen::CreateRefData() const -{ - return new wxGenericPenRefData; -} +wxObjectRefData *wxGenericPen::CreateRefData() const { return new wxGenericPenRefData; } wxObjectRefData *wxGenericPen::CloneRefData(const wxObjectRefData *data) const { - return new wxGenericPenRefData(*(const wxGenericPenRefData *)data); + return new wxGenericPenRefData(*(const wxGenericPenRefData *)data); } -void wxGenericPen::Create( const wxGenericPen &pen ) +void wxGenericPen::Create(const wxGenericPen &pen) { Ref(pen); } +void wxGenericPen::Create(const wxPen &pen) { - Ref(pen); + UnRef(); + m_refData = new wxGenericPenRefData; + Set(pen); } -void wxGenericPen::Create( const wxPen &pen ) +void wxGenericPen::Create(const wxGenericColour &colour, int width, wxPenStyle style, wxPenCap cap, + wxPenJoin join) { - UnRef(); - m_refData = new wxGenericPenRefData; - Set(pen); + UnRef(); + m_refData = new wxGenericPenRefData(width, style, cap, join); + M_GPENDATA->m_colour = colour; } -void wxGenericPen::Create(const wxGenericColour &colour, int width, wxPenStyle style, - wxPenCap cap, wxPenJoin join ) +void wxGenericPen::Create(const wxColour &colour, int width, wxPenStyle style, wxPenCap cap, + wxPenJoin join) { - UnRef(); - m_refData = new wxGenericPenRefData(width, style, cap, join); - M_GPENDATA->m_colour = colour; -} -void wxGenericPen::Create(const wxColour &colour, int width, wxPenStyle style, - wxPenCap cap, wxPenJoin join ) -{ - Create(wxGenericColour(colour), width, style, cap, join); + Create(wxGenericColour(colour), width, style, cap, join); } -void wxGenericPen::Set( const wxGenericPen& pen ) +void wxGenericPen::Set(const wxGenericPen &pen) { - wxCHECK_RET(Ok() && pen.Ok(), wxT("Invalid generic pen")); - SetColour(pen.GetColour()); - M_GPENDATA->m_width = pen.GetWidth(); - M_GPENDATA->m_style = pen.GetStyle(); - M_GPENDATA->m_cap = pen.GetCap(); - M_GPENDATA->m_join = pen.GetJoin(); + wxCHECK_RET(Ok() && pen.Ok(), wxT("Invalid generic pen")); + SetColour(pen.GetColour()); + M_GPENDATA->m_width = pen.GetWidth(); + M_GPENDATA->m_style = pen.GetStyle(); + M_GPENDATA->m_cap = pen.GetCap(); + M_GPENDATA->m_join = pen.GetJoin(); - wxDash* dash; - int n_dashes = pen.GetDashes(&dash); - SetDashes(n_dashes, dash); + wxDash *dash; + int n_dashes = pen.GetDashes(&dash); + SetDashes(n_dashes, dash); } -void wxGenericPen::Set( const wxPen &pen ) +void wxGenericPen::Set(const wxPen &pen) { - wxCHECK_RET(Ok() && pen.Ok(), wxT("Invalid generic pen")); - SetColour(pen.GetColour()); - M_GPENDATA->m_width = pen.GetWidth(); - M_GPENDATA->m_style = pen.GetStyle(); - M_GPENDATA->m_cap = pen.GetCap(); - M_GPENDATA->m_join = pen.GetJoin(); + wxCHECK_RET(Ok() && pen.Ok(), wxT("Invalid generic pen")); + SetColour(pen.GetColour()); + M_GPENDATA->m_width = pen.GetWidth(); + M_GPENDATA->m_style = pen.GetStyle(); + M_GPENDATA->m_cap = pen.GetCap(); + M_GPENDATA->m_join = pen.GetJoin(); - wxDash* dash; - int n_dashes = pen.GetDashes(&dash); - SetDashes(n_dashes, dash); + wxDash *dash; + int n_dashes = pen.GetDashes(&dash); + SetDashes(n_dashes, dash); - // or SetDashes(pen.GetDashCount(), pen.GetDash()); not in msw 2.4 -} -void wxGenericPen::SetColour( const wxGenericColour &colour ) -{ - wxCHECK_RET(Ok() && colour.Ok(), wxT("Invalid generic pen or colour")); - M_GPENDATA->m_colour = colour; + // or SetDashes(pen.GetDashCount(), pen.GetDash()); not in msw 2.4 } -void wxGenericPen::SetColour( const wxColour &colour ) +void wxGenericPen::SetColour(const wxGenericColour &colour) { - SetColour(wxGenericColour(colour)); + wxCHECK_RET(Ok() && colour.Ok(), wxT("Invalid generic pen or colour")); + M_GPENDATA->m_colour = colour; } -void wxGenericPen::SetColour( int red, int green, int blue, int alpha ) +void wxGenericPen::SetColour(const wxColour &colour) { SetColour(wxGenericColour(colour)); } +void wxGenericPen::SetColour(int red, int green, int blue, int alpha) { - SetColour(wxGenericColour(red, green, blue, alpha)); + SetColour(wxGenericColour(red, green, blue, alpha)); } -void wxGenericPen::SetCap( wxPenCap capStyle ) +void wxGenericPen::SetCap(wxPenCap capStyle) { - wxCHECK_RET(Ok(), wxT("Invalid generic pen")); - M_GPENDATA->m_cap = capStyle; + wxCHECK_RET(Ok(), wxT("Invalid generic pen")); + M_GPENDATA->m_cap = capStyle; } -void wxGenericPen::SetJoin( wxPenJoin joinStyle ) +void wxGenericPen::SetJoin(wxPenJoin joinStyle) { - wxCHECK_RET(Ok(), wxT("Invalid generic pen")); - M_GPENDATA->m_join = joinStyle; + wxCHECK_RET(Ok(), wxT("Invalid generic pen")); + M_GPENDATA->m_join = joinStyle; } -void wxGenericPen::SetStyle( wxPenStyle style ) +void wxGenericPen::SetStyle(wxPenStyle style) { - wxCHECK_RET(Ok(), wxT("Invalid generic pen")); - M_GPENDATA->m_style = style; + wxCHECK_RET(Ok(), wxT("Invalid generic pen")); + M_GPENDATA->m_style = style; } -void wxGenericPen::SetWidth( int width ) +void wxGenericPen::SetWidth(int width) { - wxCHECK_RET(Ok(), wxT("Invalid generic pen")); - M_GPENDATA->m_width = width; + wxCHECK_RET(Ok(), wxT("Invalid generic pen")); + M_GPENDATA->m_width = width; } -void wxGenericPen::SetDashes( int number_of_dashes, const wxDash *dash ) +void wxGenericPen::SetDashes(int number_of_dashes, const wxDash *dash) { - wxCHECK_RET(Ok(), wxT("Invalid generic pen")); - wxCHECK_RET(((number_of_dashes == 0) && !dash) || - ((number_of_dashes > 0) && dash), wxT("Invalid dashes for pen")); + wxCHECK_RET(Ok(), wxT("Invalid generic pen")); + wxCHECK_RET(((number_of_dashes == 0) && !dash) || ((number_of_dashes > 0) && dash), + wxT("Invalid dashes for pen")); - // internal double check to see if somebody's messed with this - //wxCHECK_RET(((M_GPENDATA->m_dash_count == 0) && !M_GPENDATA->m_dash) || - // ((M_GPENDATA->m_dash_count != 0) && M_GPENDATA->m_dash), wxT("Invalid internal dashes for pen")); + // internal double check to see if somebody's messed with this + // wxCHECK_RET(((M_GPENDATA->m_dash_count == 0) && !M_GPENDATA->m_dash) || + // ((M_GPENDATA->m_dash_count != 0) && M_GPENDATA->m_dash), wxT("Invalid internal + // dashes for pen")); - if (M_GPENDATA->m_dash) - { - free(M_GPENDATA->m_dash); - M_GPENDATA->m_dash = NULL; - M_GPENDATA->m_dash_count = 0; - } + if (M_GPENDATA->m_dash) { + free(M_GPENDATA->m_dash); + M_GPENDATA->m_dash = NULL; + M_GPENDATA->m_dash_count = 0; + } - if (!dash) - return; + if (!dash) { + return; + } - M_GPENDATA->m_dash_count = number_of_dashes; - M_GPENDATA->m_dash = (wxDash*)malloc(number_of_dashes*sizeof(wxDash)); - memcpy(M_GPENDATA->m_dash, dash, number_of_dashes*sizeof(wxDash)); + M_GPENDATA->m_dash_count = number_of_dashes; + M_GPENDATA->m_dash = (wxDash *)malloc(number_of_dashes * sizeof(wxDash)); + memcpy(M_GPENDATA->m_dash, dash, number_of_dashes * sizeof(wxDash)); } wxPen wxGenericPen::GetPen() const { - wxCHECK_MSG(Ok(), wxNullPen, wxT("Invalid generic pen")); - wxPen pen(M_GPENDATA->m_colour.GetColour(), M_GPENDATA->m_width, M_GPENDATA->m_style); - pen.SetCap(M_GPENDATA->m_cap); - pen.SetJoin(M_GPENDATA->m_join); - if (M_GPENDATA->m_dash_count > 0) - pen.SetDashes(M_GPENDATA->m_dash_count, M_GPENDATA->m_dash); + wxCHECK_MSG(Ok(), wxNullPen, wxT("Invalid generic pen")); + wxPen pen(M_GPENDATA->m_colour.GetColour(), M_GPENDATA->m_width, M_GPENDATA->m_style); + pen.SetCap(M_GPENDATA->m_cap); + pen.SetJoin(M_GPENDATA->m_join); + if (M_GPENDATA->m_dash_count > 0) { + pen.SetDashes(M_GPENDATA->m_dash_count, M_GPENDATA->m_dash); + } - return pen; + return pen; } wxGenericColour wxGenericPen::GetGenericColour() const { - wxCHECK_MSG(Ok(), wxNullGenericColour, wxT("Invalid generic pen")); - return M_GPENDATA->m_colour; + wxCHECK_MSG(Ok(), wxNullGenericColour, wxT("Invalid generic pen")); + return M_GPENDATA->m_colour; } wxColour wxGenericPen::GetColour() const { - wxCHECK_MSG(Ok(), wxNullColour, wxT("Invalid generic pen")); - return M_GPENDATA->m_colour.GetColour(); + wxCHECK_MSG(Ok(), wxNullColour, wxT("Invalid generic pen")); + return M_GPENDATA->m_colour.GetColour(); } int wxGenericPen::GetWidth() const { - wxCHECK_MSG(Ok(), 1, wxT("Invalid generic pen")); - return M_GPENDATA->m_width; + wxCHECK_MSG(Ok(), 1, wxT("Invalid generic pen")); + return M_GPENDATA->m_width; } wxPenStyle wxGenericPen::GetStyle() const { - wxCHECK_MSG(Ok(), wxPENSTYLE_SOLID, wxT("Invalid generic pen")); - return M_GPENDATA->m_style; + wxCHECK_MSG(Ok(), wxPENSTYLE_SOLID, wxT("Invalid generic pen")); + return M_GPENDATA->m_style; } wxPenCap wxGenericPen::GetCap() const { - wxCHECK_MSG(Ok(), wxCAP_ROUND, wxT("Invalid generic pen")); - return M_GPENDATA->m_cap; + wxCHECK_MSG(Ok(), wxCAP_ROUND, wxT("Invalid generic pen")); + return M_GPENDATA->m_cap; } wxPenJoin wxGenericPen::GetJoin() const { - wxCHECK_MSG(Ok(), wxJOIN_ROUND, wxT("Invalid generic pen")); - return M_GPENDATA->m_join; + wxCHECK_MSG(Ok(), wxJOIN_ROUND, wxT("Invalid generic pen")); + return M_GPENDATA->m_join; } int wxGenericPen::GetDashes(wxDash **ptr) const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid generic pen")); - *ptr = (wxDash*)M_GPENDATA->m_dash; - return M_GPENDATA->m_dash_count; + wxCHECK_MSG(Ok(), 0, wxT("Invalid generic pen")); + *ptr = (wxDash *)M_GPENDATA->m_dash; + return M_GPENDATA->m_dash_count; } int wxGenericPen::GetDashCount() const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid generic pen")); - return M_GPENDATA->m_dash_count; + wxCHECK_MSG(Ok(), 0, wxT("Invalid generic pen")); + return M_GPENDATA->m_dash_count; } -wxDash* wxGenericPen::GetDash() const +wxDash *wxGenericPen::GetDash() const { - wxCHECK_MSG(Ok(), NULL, wxT("Invalid generic pen")); - return M_GPENDATA->m_dash; + wxCHECK_MSG(Ok(), NULL, wxT("Invalid generic pen")); + return M_GPENDATA->m_dash; } bool wxGenericPen::IsSameAs(const wxGenericPen &pen) const { - wxCHECK_MSG(Ok() && pen.Ok(), false, wxT("Invalid generic pen")); - wxGenericPenRefData *pData = (wxGenericPenRefData*)pen.GetRefData(); + wxCHECK_MSG(Ok() && pen.Ok(), false, wxT("Invalid generic pen")); + wxGenericPenRefData *pData = (wxGenericPenRefData *)pen.GetRefData(); - if ((M_GPENDATA->m_colour != pData->m_colour) || (M_GPENDATA->m_width != pData->m_width) || - (M_GPENDATA->m_style != pData->m_style) || (M_GPENDATA->m_cap != pData->m_cap) || - (M_GPENDATA->m_join != pData->m_join) || (M_GPENDATA->m_dash_count != pen.GetDashCount())) - return false; + if ((M_GPENDATA->m_colour != pData->m_colour) || (M_GPENDATA->m_width != pData->m_width) || + (M_GPENDATA->m_style != pData->m_style) || (M_GPENDATA->m_cap != pData->m_cap) || + (M_GPENDATA->m_join != pData->m_join) || (M_GPENDATA->m_dash_count != pen.GetDashCount())) { + return false; + } - if (M_GPENDATA->m_dash_count > 0) - return memcmp(M_GPENDATA->m_dash, pen.GetDash(), M_GPENDATA->m_dash_count*sizeof(wxDash)) == 0; + if (M_GPENDATA->m_dash_count > 0) { + return memcmp(M_GPENDATA->m_dash, pen.GetDash(), M_GPENDATA->m_dash_count * sizeof(wxDash)) == + 0; + } - return true; + return true; } bool wxGenericPen::IsSameAs(const wxPen &pen) const { - wxCHECK_MSG(Ok() && pen.Ok(), false, wxT("Invalid generic pen")); - wxGenericPen gp(pen); - gp.GetGenericColour().SetAlpha(M_GPENDATA->m_colour.GetAlpha()); - return IsSameAs(gp); + wxCHECK_MSG(Ok() && pen.Ok(), false, wxT("Invalid generic pen")); + wxGenericPen gp(pen); + gp.GetGenericColour().SetAlpha(M_GPENDATA->m_colour.GetAlpha()); + return IsSameAs(gp); } - - - /* wxString wxGenericPen::WriteString() const { @@ -553,7 +545,6 @@ bool wxGenericPen::ReadString(const wxString& str) } */ - #include "wx/bitmap.h" //---------------------------------------------------------------------------- @@ -561,156 +552,152 @@ bool wxGenericPen::ReadString(const wxString& str) //---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxGenericBrush, wxObject) -class wxGenericBrushRefData : public wxObjectRefData -{ +class wxGenericBrushRefData : public wxObjectRefData { public: - wxGenericBrushRefData(const wxGenericColour& c = wxNullGenericColour, - wxBrushStyle style = wxBRUSHSTYLE_SOLID) : wxObjectRefData(), - m_colour(c), m_style(style) {} - - wxGenericBrushRefData(const wxGenericBrushRefData& data) : wxObjectRefData(), - m_colour(data.m_colour), m_style(data.m_style), m_stipple(data.m_stipple) {} - - ~wxGenericBrushRefData() { } - - wxGenericColour m_colour; - wxBrushStyle m_style; - wxBitmap m_stipple; + wxGenericBrushRefData(const wxGenericColour &c = wxNullGenericColour, + wxBrushStyle style = wxBRUSHSTYLE_SOLID) + : wxObjectRefData(), m_colour(c), m_style(style) + { + } + + wxGenericBrushRefData(const wxGenericBrushRefData &data) + : wxObjectRefData(), m_colour(data.m_colour), m_style(data.m_style), m_stipple(data.m_stipple) + { + } + + ~wxGenericBrushRefData() {} + + wxGenericColour m_colour; + wxBrushStyle m_style; + wxBitmap m_stipple; }; -#define M_GBRUSHDATA ((wxGenericBrushRefData*)m_refData) +#define M_GBRUSHDATA ((wxGenericBrushRefData *)m_refData) //---------------------------------------------------------------------------- -wxObjectRefData *wxGenericBrush::CreateRefData() const -{ - return new wxGenericBrushRefData; -} +wxObjectRefData *wxGenericBrush::CreateRefData() const { return new wxGenericBrushRefData; } wxObjectRefData *wxGenericBrush::CloneRefData(const wxObjectRefData *data) const { - return new wxGenericBrushRefData(*(const wxGenericBrushRefData *)data); + return new wxGenericBrushRefData(*(const wxGenericBrushRefData *)data); } -void wxGenericBrush::Create( const wxGenericBrush &brush ) +void wxGenericBrush::Create(const wxGenericBrush &brush) { Ref(brush); } +void wxGenericBrush::Create(const wxBrush &brush) { - Ref(brush); -} -void wxGenericBrush::Create( const wxBrush &brush ) -{ - UnRef(); - m_refData = new wxGenericBrushRefData; - Set(brush); + UnRef(); + m_refData = new wxGenericBrushRefData; + Set(brush); } void wxGenericBrush::Create(const wxGenericColour &colour, wxBrushStyle style) { - UnRef(); - m_refData = new wxGenericBrushRefData(colour, style); + UnRef(); + m_refData = new wxGenericBrushRefData(colour, style); } void wxGenericBrush::Create(const wxColour &colour, wxBrushStyle style) { - Create(wxGenericColour(colour), style); + Create(wxGenericColour(colour), style); } -void wxGenericBrush::Create( const wxBitmap &stipple ) +void wxGenericBrush::Create(const wxBitmap &stipple) { - UnRef(); - wxCHECK_RET(stipple.Ok(), wxT("Invalid bitmap in wxGenericBrush::Create")); + UnRef(); + wxCHECK_RET(stipple.Ok(), wxT("Invalid bitmap in wxGenericBrush::Create")); - wxBrushStyle style = stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE : wxBRUSHSTYLE_STIPPLE; - m_refData = new wxGenericBrushRefData(wxNullGenericColour, style); - M_GBRUSHDATA->m_stipple = stipple; + wxBrushStyle style = stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE : wxBRUSHSTYLE_STIPPLE; + m_refData = new wxGenericBrushRefData(wxNullGenericColour, style); + M_GBRUSHDATA->m_stipple = stipple; } -void wxGenericBrush::Set( const wxGenericBrush& brush ) +void wxGenericBrush::Set(const wxGenericBrush &brush) { - wxCHECK_RET(Ok() && brush.Ok(), wxT("Invalid generic brush")); - SetColour(brush.GetColour()); - M_GBRUSHDATA->m_style = brush.GetStyle(); - wxBitmap* stipple = brush.GetStipple(); - if (stipple && stipple->Ok()) - M_GBRUSHDATA->m_stipple = *stipple; + wxCHECK_RET(Ok() && brush.Ok(), wxT("Invalid generic brush")); + SetColour(brush.GetColour()); + M_GBRUSHDATA->m_style = brush.GetStyle(); + wxBitmap *stipple = brush.GetStipple(); + if (stipple && stipple->Ok()) { + M_GBRUSHDATA->m_stipple = *stipple; + } } -void wxGenericBrush::Set( const wxBrush &brush ) +void wxGenericBrush::Set(const wxBrush &brush) { - wxCHECK_RET(Ok() && brush.Ok(), wxT("Invalid generic brush")); - SetColour(brush.GetColour()); - M_GBRUSHDATA->m_style = brush.GetStyle(); - wxBitmap* stipple = brush.GetStipple(); - if (stipple && stipple->Ok()) - M_GBRUSHDATA->m_stipple = *stipple; + wxCHECK_RET(Ok() && brush.Ok(), wxT("Invalid generic brush")); + SetColour(brush.GetColour()); + M_GBRUSHDATA->m_style = brush.GetStyle(); + wxBitmap *stipple = brush.GetStipple(); + if (stipple && stipple->Ok()) { + M_GBRUSHDATA->m_stipple = *stipple; + } } -void wxGenericBrush::SetColour( const wxGenericColour &colour ) +void wxGenericBrush::SetColour(const wxGenericColour &colour) { - wxCHECK_RET(Ok() && colour.Ok(), wxT("Invalid generic brush or colour")); - M_GBRUSHDATA->m_colour = colour; + wxCHECK_RET(Ok() && colour.Ok(), wxT("Invalid generic brush or colour")); + M_GBRUSHDATA->m_colour = colour; } -void wxGenericBrush::SetColour( const wxColour &colour ) +void wxGenericBrush::SetColour(const wxColour &colour) { SetColour(wxGenericColour(colour)); } +void wxGenericBrush::SetColour(int red, int green, int blue, int alpha) { - SetColour(wxGenericColour(colour)); + SetColour(wxGenericColour(red, green, blue, alpha)); } -void wxGenericBrush::SetColour( int red, int green, int blue, int alpha ) +void wxGenericBrush::SetStyle(wxBrushStyle style) { - SetColour(wxGenericColour(red, green, blue, alpha)); + wxCHECK_RET(Ok(), wxT("Invalid generic brush")); + M_GBRUSHDATA->m_style = style; } -void wxGenericBrush::SetStyle( wxBrushStyle style ) +void wxGenericBrush::SetStipple(const wxBitmap &stipple) { - wxCHECK_RET(Ok(), wxT("Invalid generic brush")); - M_GBRUSHDATA->m_style = style; -} -void wxGenericBrush::SetStipple(const wxBitmap& stipple) -{ - wxCHECK_RET(Ok(), wxT("Invalid generic brush")); - M_GBRUSHDATA->m_stipple = stipple; - M_GBRUSHDATA->m_style = stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE : wxBRUSHSTYLE_STIPPLE; - + wxCHECK_RET(Ok(), wxT("Invalid generic brush")); + M_GBRUSHDATA->m_stipple = stipple; + M_GBRUSHDATA->m_style = + stipple.GetMask() ? wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE : wxBRUSHSTYLE_STIPPLE; } wxBrush wxGenericBrush::GetBrush() const { - wxCHECK_MSG(Ok(), wxNullBrush, wxT("Invalid generic brush")); - if (M_GBRUSHDATA->m_stipple.Ok()) - return wxBrush(M_GBRUSHDATA->m_stipple); + wxCHECK_MSG(Ok(), wxNullBrush, wxT("Invalid generic brush")); + if (M_GBRUSHDATA->m_stipple.Ok()) { + return wxBrush(M_GBRUSHDATA->m_stipple); + } - return wxBrush(M_GBRUSHDATA->m_colour.GetColour(), M_GBRUSHDATA->m_style); + return wxBrush(M_GBRUSHDATA->m_colour.GetColour(), M_GBRUSHDATA->m_style); } wxGenericColour wxGenericBrush::GetGenericColour() const { - wxCHECK_MSG(Ok(), wxNullGenericColour, wxT("Invalid generic brush")); - return M_GBRUSHDATA->m_colour; + wxCHECK_MSG(Ok(), wxNullGenericColour, wxT("Invalid generic brush")); + return M_GBRUSHDATA->m_colour; } wxColour wxGenericBrush::GetColour() const { - wxCHECK_MSG(Ok(), wxNullColour, wxT("Invalid generic brush")); - return M_GBRUSHDATA->m_colour.GetColour(); + wxCHECK_MSG(Ok(), wxNullColour, wxT("Invalid generic brush")); + return M_GBRUSHDATA->m_colour.GetColour(); } wxBrushStyle wxGenericBrush::GetStyle() const { - wxCHECK_MSG(Ok(), wxBRUSHSTYLE_SOLID, wxT("Invalid generic brush")); - return M_GBRUSHDATA->m_style; + wxCHECK_MSG(Ok(), wxBRUSHSTYLE_SOLID, wxT("Invalid generic brush")); + return M_GBRUSHDATA->m_style; } -wxBitmap* wxGenericBrush::GetStipple() const +wxBitmap *wxGenericBrush::GetStipple() const { - wxCHECK_MSG(Ok(), NULL, wxT("Invalid generic brush")); - return &M_GBRUSHDATA->m_stipple; + wxCHECK_MSG(Ok(), NULL, wxT("Invalid generic brush")); + return &M_GBRUSHDATA->m_stipple; } -bool wxGenericBrush::IsSameAs(const wxGenericBrush& brush) const +bool wxGenericBrush::IsSameAs(const wxGenericBrush &brush) const { - wxCHECK_MSG(Ok() && brush.Ok(), 1, wxT("Invalid generic brush")); - wxGenericBrushRefData *bData = (wxGenericBrushRefData*)brush.GetRefData(); -#if wxCHECK_VERSION(2,7,0) - // FIXME: Hack for wx2.7; how do we test wxBitmap for equality now? - return (M_GBRUSHDATA->m_colour == bData->m_colour) && - (M_GBRUSHDATA->m_style == bData->m_style); + wxCHECK_MSG(Ok() && brush.Ok(), 1, wxT("Invalid generic brush")); + wxGenericBrushRefData *bData = (wxGenericBrushRefData *)brush.GetRefData(); +#if wxCHECK_VERSION(2, 7, 0) + // FIXME: Hack for wx2.7; how do we test wxBitmap for equality now? + return (M_GBRUSHDATA->m_colour == bData->m_colour) && (M_GBRUSHDATA->m_style == bData->m_style); #else - return (M_GBRUSHDATA->m_colour == bData->m_colour) && - (M_GBRUSHDATA->m_style == bData->m_style) && - (M_GBRUSHDATA->m_stipple == bData->m_stipple); + return (M_GBRUSHDATA->m_colour == bData->m_colour) && + (M_GBRUSHDATA->m_style == bData->m_style) && + (M_GBRUSHDATA->m_stipple == bData->m_stipple); #endif } -bool wxGenericBrush::IsSameAs(const wxBrush& brush) const +bool wxGenericBrush::IsSameAs(const wxBrush &brush) const { - wxCHECK_MSG(Ok() && brush.Ok(), 1, wxT("Invalid generic brush")); - wxGenericBrush gB(brush); - gB.GetGenericColour().SetAlpha(M_GBRUSHDATA->m_colour.GetAlpha()); - return IsSameAs(gB); + wxCHECK_MSG(Ok() && brush.Ok(), 1, wxT("Invalid generic brush")); + wxGenericBrush gB(brush); + gB.GetGenericColour().SetAlpha(M_GBRUSHDATA->m_colour.GetAlpha()); + return IsSameAs(gB); } diff --git a/src/labenski/src/geometry.cpp b/src/labenski/src/geometry.cpp index bdb19bb57..af08605de 100644 --- a/src/labenski/src/geometry.cpp +++ b/src/labenski/src/geometry.cpp @@ -10,108 +10,89 @@ #include #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #include "wx/wxthings/geometry.h" /* 2.4 : How do I generate a circle through three points? -Let the three given points be a, b, c. Use _0 and _1 to represent x and y coordinates. The coordinates of the center p=(p_0,p_1) of the circle determined by a, b, and c are: -A = b_0 - a_0; B = b_1 - a_1; C = c_0 - a_0; D = c_1 - a_1; -E = A*(a_0 + b_0) + B*(a_1 + b_1); F = C*(a_0 + c_0) + D*(a_1 + c_1); -G = 2.0*(A*(c_1 - b_1)-B*(c_0 - b_0)); -p_0 = (D*E - B*F) / G; p_1 = (A*F - C*E) / G; -If G is zero then the three points are collinear and no finite-radius circle through them exists. Otherwise, the radius of the circle is: -r^2 = (a_0 - p_0)^2 + (a_1 - p_1)^2 -[O' Rourke (C)] p. 201. Simplified by Jim Ward. +Let the three given points be a, b, c. Use _0 and _1 to represent x and y coordinates. The +coordinates of the center p=(p_0,p_1) of the circle determined by a, b, and c are: A = b_0 - a_0; B += b_1 - a_1; C = c_0 - a_0; D = c_1 - a_1; E = A*(a_0 + b_0) + B*(a_1 + b_1); F = C*(a_0 + c_0) + +D*(a_1 + c_1); G = 2.0*(A*(c_1 - b_1)-B*(c_0 - b_0)); p_0 = (D*E - B*F) / G; p_1 = (A*F - C*E) / G; +If G is zero then the three points are collinear and no finite-radius circle through them exists. +Otherwise, the radius of the circle is: r^2 = (a_0 - p_0)^2 + (a_1 - p_1)^2 [O' Rourke (C)] p. 201. +Simplified by Jim Ward. */ -wxCircleDouble::wxCircleDouble(const wxPoint2DDouble &p1, - const wxPoint2DDouble &p2, +wxCircleDouble::wxCircleDouble(const wxPoint2DDouble &p1, const wxPoint2DDouble &p2, const wxPoint2DDouble &p3) { - wxDouble A = p2.m_x - p1.m_x, - B = p2.m_y - p1.m_y, - C = p3.m_x - p1.m_x, - D = p3.m_y - p1.m_y; + wxDouble A = p2.m_x - p1.m_x, B = p2.m_y - p1.m_y, C = p3.m_x - p1.m_x, D = p3.m_y - p1.m_y; - wxDouble E = A*(p1.m_x + p2.m_x) + B*(p1.m_y + p2.m_y), - F = C*(p1.m_x + p3.m_x) + D*(p1.m_y + p3.m_y), - G = 2.0*(A*(p3.m_y - p2.m_y)-B*(p3.m_x - p2.m_x)); + wxDouble E = A * (p1.m_x + p2.m_x) + B * (p1.m_y + p2.m_y), + F = C * (p1.m_x + p3.m_x) + D * (p1.m_y + p3.m_y), + G = 2.0 * (A * (p3.m_y - p2.m_y) - B * (p3.m_x - p2.m_x)); - if (G == 0) - { - m_x = m_y = m_r = 0; - return; - } + if (G == 0) { + m_x = m_y = m_r = 0; + return; + } - m_x = (D*E - B*F) / G, - m_y = (A*F - C*E) / G; - m_r = sqrt( (p1.m_x - m_x)*(p1.m_x - m_x) + (p1.m_y - m_y)*(p1.m_y - m_y) ); + m_x = (D * E - B * F) / G, m_y = (A * F - C * E) / G; + m_r = sqrt((p1.m_x - m_x) * (p1.m_x - m_x) + (p1.m_y - m_y) * (p1.m_y - m_y)); } -int wxCircleDouble::IntersectLine( const wxRay2DDouble &line, - wxPoint2DDouble *pt1, - wxPoint2DDouble *pt2 ) const +int wxCircleDouble::IntersectLine(const wxRay2DDouble &line, wxPoint2DDouble *pt1, + wxPoint2DDouble *pt2) const { - //if (line.GetDistanceToPoint(m_origin) > m_r) return 0; - - wxDouble l1_x = m_x-m_r, l1_y = line.GetYFromX(l1_x); - wxDouble l2_x = m_x+m_r, l2_y = line.GetYFromX(l2_x); + // if (line.GetDistanceToPoint(m_origin) > m_r) return 0; - // quick check to see it it intersects at all - //wxDouble top = m_origin.m_y-m_r, bot = m_origin.m_y+m_r; - //if (((l1_y < top)&&(l2_y < top))||((l1_y > bot)&&(l2_y > bot))) return 0; + wxDouble l1_x = m_x - m_r, l1_y = line.GetYFromX(l1_x); + wxDouble l2_x = m_x + m_r, l2_y = line.GetYFromX(l2_x); - wxDouble l2_l1_x = l2_x - l1_x, l2_l1_y = l2_y - l1_y; + // quick check to see it it intersects at all + // wxDouble top = m_origin.m_y-m_r, bot = m_origin.m_y+m_r; + // if (((l1_y < top)&&(l2_y < top))||((l1_y > bot)&&(l2_y > bot))) return 0; - wxDouble a = l2_l1_x*l2_l1_x + l2_l1_y*l2_l1_y; - wxDouble b = 2.0 * (l2_l1_x * (l1_x - m_x) + l2_l1_y * (l1_y - m_y) ); + wxDouble l2_l1_x = l2_x - l1_x, l2_l1_y = l2_y - l1_y; - wxDouble c = m_x*m_x + m_y*m_y + l1_x*l1_x + l1_y*l1_y - 2.0*(m_x*l1_x + m_y*l1_y) - m_r*m_r; - wxDouble det = b*b - 4.0*a*c; + wxDouble a = l2_l1_x * l2_l1_x + l2_l1_y * l2_l1_y; + wxDouble b = 2.0 * (l2_l1_x * (l1_x - m_x) + l2_l1_y * (l1_y - m_y)); - if ( det < 0 ) - { - return 0; - } - else if ( det == 0 ) - { - if (pt1) - { - wxDouble u = -b/(2.0*a); - pt1->m_x = l2_x + u*l2_l1_x; - pt1->m_y = l2_y + u*l2_l1_y; - } - return 1; - } - // else det > 0 so 2 points intersect - wxDouble e = sqrt(det); + wxDouble c = m_x * m_x + m_y * m_y + l1_x * l1_x + l1_y * l1_y - + 2.0 * (m_x * l1_x + m_y * l1_y) - m_r * m_r; + wxDouble det = b * b - 4.0 * a * c; - if (pt1) - { - wxDouble u1 = (-b - e)/( 2.0*a ); - pt1->m_x = l1_x + u1*l2_l1_x; - pt1->m_y = l1_y + u1*l2_l1_y; + if (det < 0) { + return 0; + } + else if (det == 0) { + if (pt1) { + wxDouble u = -b / (2.0 * a); + pt1->m_x = l2_x + u * l2_l1_x; + pt1->m_y = l2_y + u * l2_l1_y; } - if (pt2) - { - wxDouble u2 = (-b + e)/( 2.0*a ); - pt2->m_x = l1_x + u2*l2_l1_x; - pt2->m_y = l1_y + u2*l2_l1_y; - } - - return 2; + return 1; + } + // else det > 0 so 2 points intersect + wxDouble e = sqrt(det); + + if (pt1) { + wxDouble u1 = (-b - e) / (2.0 * a); + pt1->m_x = l1_x + u1 * l2_l1_x; + pt1->m_y = l1_y + u1 * l2_l1_y; + } + if (pt2) { + wxDouble u2 = (-b + e) / (2.0 * a); + pt2->m_x = l1_x + u2 * l2_l1_x; + pt2->m_y = l1_y + u2 * l2_l1_y; + } + + return 2; } - - - - - - - /* int wxEllipseInt::IntersectLine( const wxLine2DInt &line, wxPoint2DInt &pt1, diff --git a/src/labenski/src/lm_lsqr.cpp b/src/labenski/src/lm_lsqr.cpp index a4067dd20..337ef2f35 100644 --- a/src/labenski/src/lm_lsqr.cpp +++ b/src/labenski/src/lm_lsqr.cpp @@ -12,12 +12,12 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/dynarray.h" - #include "wx/log.h" +#include "wx/dynarray.h" +#include "wx/log.h" #endif // WX_PRECOMP #include "wx/math.h" @@ -34,1776 +34,1812 @@ static LM_LeastSquareProgressHandler_ s_lm_leastsquarehandler = nullptr; -void SetLM_LeastSquareProgressHandler( LM_LeastSquareProgressHandler_ handler ) +void SetLM_LeastSquareProgressHandler(LM_LeastSquareProgressHandler_ handler) { - s_lm_leastsquarehandler = handler; + s_lm_leastsquarehandler = handler; } static int s_nprint = 0; -void SetLM_LeastSquareProgressHandlerTicks( int iterations ) +void SetLM_LeastSquareProgressHandlerTicks(int iterations) { - wxCHECK_RET( (iterations>=0), wxT("invalid iteration step size")); - s_nprint = iterations; + wxCHECK_RET((iterations >= 0), wxT("invalid iteration step size")); + s_nprint = iterations; } /************************lmmisc.c*************************/ -inline double dmax1(double a, double b) { return ( a >= b ) ? a : b; } -inline double dmin1(double a, double b) { return ( a <= b ) ? a : b; } +inline double dmax1(double a, double b) { return (a >= b) ? a : b; } +inline double dmin1(double a, double b) { return (a <= b) ? a : b; } -inline int min0(int a, int b) { return ( a <= b ) ? a : b; } -inline int mod( int k, int m ) { return ( k % m ); } +inline int min0(int a, int b) { return (a <= b) ? a : b; } +inline int mod(int k, int m) { return (k % m); } -void pmat( int m, int n, double y[] ) +void pmat(int m, int n, double y[]) { - int i, j, k = 0; - - for( i=0; i 1) && (plotData.GetCount() >= plotFunc.GetNumberVariables() - 1), false, wxT("invalid dimensions")); - - m_plotData = new wxPlotData(plotData); - m_plotFunc = new wxPlotFunction(plotFunc); - - double *x_data = m_plotData->GetXData(); - double *y_data = m_plotData->GetYData(); - int data_count = m_plotData->GetCount(); - for (int i=0; i 1) && + (plotData.GetCount() >= plotFunc.GetNumberVariables() - 1), + false, wxT("invalid dimensions")); + + m_plotData = new wxPlotData(plotData); + m_plotFunc = new wxPlotFunction(plotFunc); + + double *x_data = m_plotData->GetXData(); + double *y_data = m_plotData->GetYData(); + int data_count = m_plotData->GetCount(); + for (int i = 0; i < data_count; i++, x_data++, y_data++) { + if (!wxFinite(*x_data) && !wxFinite(*y_data)) { + Destroy(); + m_resultMsg.Printf(wxT("Unable to fit data since some values are NaN")); + return false; } + } - memset(m_x, 0, m_n * sizeof(double)); + m_n = plotFunc.GetNumberVariables() - 1; + m_m = plotData.GetCount(); - m_ok = true; - return true; -} + m_ldfjac = m_m; -int LM_LeastSquare::Fit(const double *x0, int init_count) -{ - wxCHECK_MSG(Ok() && !IsFitting(), 0, wxT("invalid functions")); + m_vars = (double *)malloc((m_n + 1) * sizeof(double)); + m_x = (double *)malloc(m_n * sizeof(double)); + m_fvec = (double *)malloc(m_m * sizeof(double)); + m_diag = (double *)malloc(m_n * sizeof(double)); + m_fjac = (double *)malloc(m_m * m_n * sizeof(double)); + m_qtf = (double *)malloc(m_n * sizeof(double)); + m_ipvt = (int *)malloc(m_n * sizeof(int)); + m_maxfev = 200 * (m_n + 1); - m_nan = 0; - m_info = -1; - m_fnorm = 0; - m_nfev = 0; + if (!(m_plotData && m_plotFunc && m_vars && m_x && m_fvec && m_diag && m_fjac && m_qtf && + m_ipvt)) { + Destroy(); + wxFAIL_MSG(wxT("can't allocate memory")); + return false; + } - int i; + memset(m_x, 0, m_n * sizeof(double)); - if (x0 && (init_count > 0)) - { - wxCHECK_MSG(init_count <= m_n, 0, wxT("Invalid initializer count")); + m_ok = true; + return true; +} - // initialize the variables - for (i=0; i 0)) { + wxCHECK_MSG(init_count <= m_n, 0, wxT("Invalid initializer count")); + + // initialize the variables + for (i = 0; i < init_count; i++) { + if (!wxFinite(x0[i])) { + m_x[i] = m_init_value; + wxLogWarning(wxT("Initial value is NaN in LM_LeastSquare::Fit")); + } + else { + m_x[i] = x0[i]; + } + } - // initialize the rest, if any - for (i=init_count; i=0)&&(n= 0) && (n < m_n), 0.0, wxT("Invalid variable index")); + return m_x[n]; } /* -* fcn is the name of the user-supplied subroutine which -* calculates the functions. fcn must be declared -* in an external statement in the user calling -* program, and should be written as follows. -* -* subroutine fcn(m,n,x,fvec,iflag) -* integer m,n,iflag -* double precision x(n),fvec(m) -* ---------- -* calculate the functions at x and -* return this vector in fvec. -* ---------- -* return -* end -* -* the value of iflag should not be changed by fcn unless -* the user wants to terminate execution of lmdif1. -* in this case set iflag to a negative integer. -* -* m is a positive integer input variable set to the number -* of functions. -* -* n is a positive integer input variable set to the number -* of variables. n must not exceed m. -* -* x is an array of length n. on input x must contain -* an initial estimate of the solution vector. on output x -* contains the final estimate of the solution vector. -* -* fvec is an output array of length m which contains -* the functions evaluated at the output x. -* -* -* argonne national laboratory. minpack project. march 1980. -* burton s. garbow, kenneth e. hillstrom, jorge j. more -* -* ********** -*/ + * fcn is the name of the user-supplied subroutine which + * calculates the functions. fcn must be declared + * in an external statement in the user calling + * program, and should be written as follows. + * + * subroutine fcn(m,n,x,fvec,iflag) + * integer m,n,iflag + * double precision x(n),fvec(m) + * ---------- + * calculate the functions at x and + * return this vector in fvec. + * ---------- + * return + * end + * + * the value of iflag should not be changed by fcn unless + * the user wants to terminate execution of lmdif1. + * in this case set iflag to a negative integer. + * + * m is a positive integer input variable set to the number + * of functions. + * + * n is a positive integer input variable set to the number + * of variables. n must not exceed m. + * + * x is an array of length n. on input x must contain + * an initial estimate of the solution vector. on output x + * contains the final estimate of the solution vector. + * + * fvec is an output array of length m which contains + * the functions evaluated at the output x. + * + * + * argonne national laboratory. minpack project. march 1980. + * burton s. garbow, kenneth e. hillstrom, jorge j. more + * + * ********** + */ void LM_LeastSquare::fcn(int m, int n, double x[], double fvec[], int *iflag) { wxCHECK_RET(m_plotData && m_plotFunc, wxT("invalid functions")); - if (*iflag == 0) - { - if (m_abort_fitting) - *iflag = -1; - else if (s_lm_leastsquarehandler) - { - // exit if handler returns false - if (!((*s_lm_leastsquarehandler)(m_plotFunc->GetFunctionString(), m_nfev, m_maxfev))) - *iflag = -1; - } - - return; + if (*iflag == 0) { + if (m_abort_fitting) { + *iflag = -1; + } + else if (s_lm_leastsquarehandler) { + // exit if handler returns false + if (!((*s_lm_leastsquarehandler)(m_plotFunc->GetFunctionString(), m_nfev, m_maxfev))) { + *iflag = -1; + } } - double *x_data = m_plotData->GetXData(); - double *y_data = m_plotData->GetYData(); - double f = 0; - memcpy(m_vars, x, n*sizeof(double)); - - for (int i=0; iGetValue(m_vars); - if (!wxFinite(f)) - { - m_nan++; - fvec[i] = 0; - continue; - } + return; + } + + double *x_data = m_plotData->GetXData(); + double *y_data = m_plotData->GetYData(); + double f = 0; + memcpy(m_vars, x, n * sizeof(double)); - fvec[i] = (*y_data) - f; + for (int i = 0; i < m; i++, x_data++, y_data++) { + /* // this is checked in Create now + if (!wxFinite(*x_data) && !wxFinite(*y_data)) + { + m_nan++; + fvec[i] = 0; + continue; + } + */ + m_vars[n] = *x_data; + + f = m_plotFunc->GetValue(m_vars); + if (!wxFinite(f)) { + m_nan++; + fvec[i] = 0; + continue; } + + fvec[i] = (*y_data) - f; + } } /*********************** lmdif.c ****************************/ #define BUG 0 /* -* ********** -* -* subroutine lmdif -* -* the purpose of lmdif is to minimize the sum of the squares of -* m nonlinear functions in n variables by a modification of -* the levenberg-marquardt algorithm. the user must provide a -* subroutine which calculates the functions. the jacobian is -* then calculated by a forward-difference approximation. -* -* the subroutine statement is -* -* subroutine lmdif(fcn,m,n,x,fvec,ftol,xtol,gtol,maxfev,epsfcn, -* diag,mode,factor,nprint,info,nfev,fjac, -* ldfjac,ipvt,qtf,wa1,wa2,wa3,wa4) -* -* where -* -* fcn is the name of the user-supplied subroutine which -* calculates the functions. fcn must be declared -* in an external statement in the user calling -* program, and should be written as follows. -* -* subroutine fcn(m,n,x,fvec,iflag) -* integer m,n,iflag -* double precision x(n),fvec(m) -* ---------- -* calculate the functions at x and -* return this vector in fvec. -* ---------- -* return -* end -* -* the value of iflag should not be changed by fcn unless -* the user wants to terminate execution of lmdif. -* in this case set iflag to a negative integer. -* -* m is a positive integer input variable set to the number -* of functions. -* -* n is a positive integer input variable set to the number -* of variables. n must not exceed m. -* -* x is an array of length n. on input x must contain -* an initial estimate of the solution vector. on output x -* contains the final estimate of the solution vector. -* -* fvec is an output array of length m which contains -* the functions evaluated at the output x. -* -* ftol is a nonnegative input variable. termination -* occurs when both the actual and predicted relative -* reductions in the sum of squares are at most ftol. -* therefore, ftol measures the relative error desired -* in the sum of squares. -* -* xtol is a nonnegative input variable. termination -* occurs when the relative error between two consecutive -* iterates is at most xtol. therefore, xtol measures the -* relative error desired in the approximate solution. -* -* gtol is a nonnegative input variable. termination -* occurs when the cosine of the angle between fvec and -* any column of the jacobian is at most gtol in absolute -* value. therefore, gtol measures the orthogonality -* desired between the function vector and the columns -* of the jacobian. -* -* maxfev is a positive integer input variable. termination -* occurs when the number of calls to fcn is at least -* maxfev by the end of an iteration. -* -* epsfcn is an input variable used in determining a suitable -* step length for the forward-difference approximation. this -* approximation assumes that the relative errors in the -* functions are of the order of epsfcn. if epsfcn is less -* than the machine precision, it is assumed that the relative -* errors in the functions are of the order of the machine -* precision. -* -* diag is an array of length n. if mode = 1 (see -* below), diag is internally set. if mode = 2, diag -* must contain positive entries that serve as -* multiplicative scale factors for the variables. -* -* mode is an integer input variable. if mode = 1, the -* variables will be scaled internally. if mode = 2, -* the scaling is specified by the input diag. other -* values of mode are equivalent to mode = 1. -* -* factor is a positive input variable used in determining the -* initial step bound. this bound is set to the product of -* factor and the euclidean norm of diag*x if nonzero, or else -* to factor itself. in most cases factor should lie in the -* interval (.1,100.). 100. is a generally recommended value. -* -* nprint is an integer input variable that enables controlled -* printing of iterates if it is positive. in this case, -* fcn is called with iflag = 0 at the beginning of the first -* iteration and every nprint iterations thereafter and -* immediately prior to return, with x and fvec available -* for printing. if nprint is not positive, no special calls -* of fcn with iflag = 0 are made. -* -* info is an integer output variable. if the user has -* terminated execution, info is set to the (negative) -* value of iflag. see description of fcn. otherwise, -* info is set as follows. -* -* info = 0 improper input parameters. -* -* info = 1 both actual and predicted relative reductions -* in the sum of squares are at most ftol. -* -* info = 2 relative error between two consecutive iterates -* is at most xtol. -* -* info = 3 conditions for info = 1 and info = 2 both hold. -* -* info = 4 the cosine of the angle between fvec and any -* column of the jacobian is at most gtol in -* absolute value. -* -* info = 5 number of calls to fcn has reached or -* exceeded maxfev. -* -* info = 6 ftol is too small. no further reduction in -* the sum of squares is possible. -* -* info = 7 xtol is too small. no further improvement in -* the approximate solution x is possible. -* -* info = 8 gtol is too small. fvec is orthogonal to the -* columns of the jacobian to machine precision. -* -* nfev is an integer output variable set to the number of -* calls to fcn. -* -* fjac is an output m by n array. the upper n by n submatrix -* of fjac contains an upper triangular matrix r with -* diagonal elements of nonincreasing magnitude such that -* -* t t t -* p *(jac *jac)*p = r *r, -* -* where p is a permutation matrix and jac is the final -* calculated jacobian. column j of p is column ipvt(j) -* (see below) of the identity matrix. the lower trapezoidal -* part of fjac contains information generated during -* the computation of r. -* -* ldfjac is a positive integer input variable not less than m -* which specifies the leading dimension of the array fjac. -* -* ipvt is an integer output array of length n. ipvt -* defines a permutation matrix p such that jac*p = q*r, -* where jac is the final calculated jacobian, q is -* orthogonal (not stored), and r is upper triangular -* with diagonal elements of nonincreasing magnitude. -* column j of p is column ipvt(j) of the identity matrix. -* -* qtf is an output array of length n which contains -* the first n elements of the vector (q transpose)*fvec. -* -* wa1, wa2, and wa3 are work arrays of length n. -* -* wa4 is a work array of length m. -* -* subprograms called -* -* user-supplied ...... fcn -* -* minpack-supplied ... dpmpar,enorm,fdjac2,lmpar,qrfac -* -* fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod -* -* argonne national laboratory. minpack project. march 1980. -* burton s. garbow, kenneth e. hillstrom, jorge j. more -* -* ********** -*/ - -void LM_LeastSquare::lmdif( int m, int n, double x[], double fvec[], - double ftol, double xtol, double gtol, int maxfev, - double epsfcn, double diag[], int mode, - double factor, int nprint, int *info, int *nfev, - double fjac[], int ldfjac, int ipvt[], double qtf[], - double wa1[], double wa2[], double wa3[], double wa4[]) + * ********** + * + * subroutine lmdif + * + * the purpose of lmdif is to minimize the sum of the squares of + * m nonlinear functions in n variables by a modification of + * the levenberg-marquardt algorithm. the user must provide a + * subroutine which calculates the functions. the jacobian is + * then calculated by a forward-difference approximation. + * + * the subroutine statement is + * + * subroutine lmdif(fcn,m,n,x,fvec,ftol,xtol,gtol,maxfev,epsfcn, + * diag,mode,factor,nprint,info,nfev,fjac, + * ldfjac,ipvt,qtf,wa1,wa2,wa3,wa4) + * + * where + * + * fcn is the name of the user-supplied subroutine which + * calculates the functions. fcn must be declared + * in an external statement in the user calling + * program, and should be written as follows. + * + * subroutine fcn(m,n,x,fvec,iflag) + * integer m,n,iflag + * double precision x(n),fvec(m) + * ---------- + * calculate the functions at x and + * return this vector in fvec. + * ---------- + * return + * end + * + * the value of iflag should not be changed by fcn unless + * the user wants to terminate execution of lmdif. + * in this case set iflag to a negative integer. + * + * m is a positive integer input variable set to the number + * of functions. + * + * n is a positive integer input variable set to the number + * of variables. n must not exceed m. + * + * x is an array of length n. on input x must contain + * an initial estimate of the solution vector. on output x + * contains the final estimate of the solution vector. + * + * fvec is an output array of length m which contains + * the functions evaluated at the output x. + * + * ftol is a nonnegative input variable. termination + * occurs when both the actual and predicted relative + * reductions in the sum of squares are at most ftol. + * therefore, ftol measures the relative error desired + * in the sum of squares. + * + * xtol is a nonnegative input variable. termination + * occurs when the relative error between two consecutive + * iterates is at most xtol. therefore, xtol measures the + * relative error desired in the approximate solution. + * + * gtol is a nonnegative input variable. termination + * occurs when the cosine of the angle between fvec and + * any column of the jacobian is at most gtol in absolute + * value. therefore, gtol measures the orthogonality + * desired between the function vector and the columns + * of the jacobian. + * + * maxfev is a positive integer input variable. termination + * occurs when the number of calls to fcn is at least + * maxfev by the end of an iteration. + * + * epsfcn is an input variable used in determining a suitable + * step length for the forward-difference approximation. this + * approximation assumes that the relative errors in the + * functions are of the order of epsfcn. if epsfcn is less + * than the machine precision, it is assumed that the relative + * errors in the functions are of the order of the machine + * precision. + * + * diag is an array of length n. if mode = 1 (see + * below), diag is internally set. if mode = 2, diag + * must contain positive entries that serve as + * multiplicative scale factors for the variables. + * + * mode is an integer input variable. if mode = 1, the + * variables will be scaled internally. if mode = 2, + * the scaling is specified by the input diag. other + * values of mode are equivalent to mode = 1. + * + * factor is a positive input variable used in determining the + * initial step bound. this bound is set to the product of + * factor and the euclidean norm of diag*x if nonzero, or else + * to factor itself. in most cases factor should lie in the + * interval (.1,100.). 100. is a generally recommended value. + * + * nprint is an integer input variable that enables controlled + * printing of iterates if it is positive. in this case, + * fcn is called with iflag = 0 at the beginning of the first + * iteration and every nprint iterations thereafter and + * immediately prior to return, with x and fvec available + * for printing. if nprint is not positive, no special calls + * of fcn with iflag = 0 are made. + * + * info is an integer output variable. if the user has + * terminated execution, info is set to the (negative) + * value of iflag. see description of fcn. otherwise, + * info is set as follows. + * + * info = 0 improper input parameters. + * + * info = 1 both actual and predicted relative reductions + * in the sum of squares are at most ftol. + * + * info = 2 relative error between two consecutive iterates + * is at most xtol. + * + * info = 3 conditions for info = 1 and info = 2 both hold. + * + * info = 4 the cosine of the angle between fvec and any + * column of the jacobian is at most gtol in + * absolute value. + * + * info = 5 number of calls to fcn has reached or + * exceeded maxfev. + * + * info = 6 ftol is too small. no further reduction in + * the sum of squares is possible. + * + * info = 7 xtol is too small. no further improvement in + * the approximate solution x is possible. + * + * info = 8 gtol is too small. fvec is orthogonal to the + * columns of the jacobian to machine precision. + * + * nfev is an integer output variable set to the number of + * calls to fcn. + * + * fjac is an output m by n array. the upper n by n submatrix + * of fjac contains an upper triangular matrix r with + * diagonal elements of nonincreasing magnitude such that + * + * t t t + * p *(jac *jac)*p = r *r, + * + * where p is a permutation matrix and jac is the final + * calculated jacobian. column j of p is column ipvt(j) + * (see below) of the identity matrix. the lower trapezoidal + * part of fjac contains information generated during + * the computation of r. + * + * ldfjac is a positive integer input variable not less than m + * which specifies the leading dimension of the array fjac. + * + * ipvt is an integer output array of length n. ipvt + * defines a permutation matrix p such that jac*p = q*r, + * where jac is the final calculated jacobian, q is + * orthogonal (not stored), and r is upper triangular + * with diagonal elements of nonincreasing magnitude. + * column j of p is column ipvt(j) of the identity matrix. + * + * qtf is an output array of length n which contains + * the first n elements of the vector (q transpose)*fvec. + * + * wa1, wa2, and wa3 are work arrays of length n. + * + * wa4 is a work array of length m. + * + * subprograms called + * + * user-supplied ...... fcn + * + * minpack-supplied ... dpmpar,enorm,fdjac2,lmpar,qrfac + * + * fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod + * + * argonne national laboratory. minpack project. march 1980. + * burton s. garbow, kenneth e. hillstrom, jorge j. more + * + * ********** + */ + +void LM_LeastSquare::lmdif(int m, int n, double x[], double fvec[], double ftol, double xtol, + double gtol, int maxfev, double epsfcn, double diag[], int mode, + double factor, int nprint, int *info, int *nfev, double fjac[], + int ldfjac, int ipvt[], double qtf[], double wa1[], double wa2[], + double wa3[], double wa4[]) { - int i, iflag, ij, jj, iter, j, l; - double actred, delta, dirder, fnorm, fnorm1, gnorm; - double par, pnorm, prered, ratio; - double sum, temp, temp1, temp2, temp3, xnorm; - static double one = 1.0; - static double p1 = 0.1; - static double p5 = 0.5; - static double p25 = 0.25; - static double p75 = 0.75; - static double p0001 = 1.0e-4; - static double zero = 0.0; - // static double p05 = 0.05; - - *info = 0; - iflag = 0; - *nfev = 0; - delta = 0.0; - xnorm = 0.0; - - // check the input parameters for errors. - - if ( (n <= 0) || (m < n) || (ldfjac < m) || (ftol < zero) - || (xtol < zero) || (gtol < zero) || (maxfev <= 0) || (factor <= zero) ) + int i, iflag, ij, jj, iter, j, l; + double actred, delta, dirder, fnorm, fnorm1, gnorm; + double par, pnorm, prered, ratio; + double sum, temp, temp1, temp2, temp3, xnorm; + static double one = 1.0; + static double p1 = 0.1; + static double p5 = 0.5; + static double p25 = 0.25; + static double p75 = 0.75; + static double p0001 = 1.0e-4; + static double zero = 0.0; + // static double p05 = 0.05; + + *info = 0; + iflag = 0; + *nfev = 0; + delta = 0.0; + xnorm = 0.0; + + // check the input parameters for errors. + + if ((n <= 0) || (m < n) || (ldfjac < m) || (ftol < zero) || (xtol < zero) || (gtol < zero) || + (maxfev <= 0) || (factor <= zero)) { + goto L300; + } + + if (mode == 2) { + // scaling by diag[] + for (j = 0; j < n; j++) { + if (diag[j] <= 0.0) { goto L300; - - if( mode == 2 ) - { - // scaling by diag[] - for( j=0; j 0 ) - { - iflag = 0; - if(mod(iter-1,nprint) == 0) - { - fcn(m,n,x,fvec,&iflag); - if(iflag < 0) - goto L300; + if (nprint > 0) { + iflag = 0; + if (mod(iter - 1, nprint) == 0) { + fcn(m, n, x, fvec, &iflag); + if (iflag < 0) { + goto L300; + } #if BUG - printf( "fnorm %.15e\n", enorm(m,fvec) ); + printf("fnorm %.15e\n", enorm(m, fvec)); #endif - } } + } - // compute the qr factorization of the jacobian. + // compute the qr factorization of the jacobian. - qrfac(m,n,fjac,ldfjac,1,ipvt,n,wa1,wa2,wa3); + qrfac(m, n, fjac, ldfjac, 1, ipvt, n, wa1, wa2, wa3); - // on the first iteration and if mode is 1, scale according - // to the norms of the columns of the initial jacobian. + // on the first iteration and if mode is 1, scale according + // to the norms of the columns of the initial jacobian. - if(iter == 1) - { - if(mode != 2) - { - for( j=0; j= zero) - temp = p5; - else - temp = p5*dirder/(dirder + p5*actred); + // update the step bound. - if( ((p1*fnorm1) >= fnorm) || (temp < p1) ) - temp = p1; - - delta = temp*dmin1(delta,pnorm/p1); - par = par/temp; + if (ratio <= p25) { + if (actred >= zero) { + temp = p5; } - else - { - if( (par == zero) || (ratio >= p75) ) - { - delta = pnorm/p5; - par = p5*par; - } + else { + temp = p5 * dirder / (dirder + p5 * actred); } - // test for successful iteration. - - if(ratio >= p0001) - { - // successful iteration. update x, fvec, and their norms. - - for( j=0; j= fnorm) || (temp < p1)) { + temp = p1; } - // tests for convergence. - - if( (fabs(actred) <= ftol) && (prered <= ftol) && (p5*ratio <= one) ) - *info = 1; - if(delta <= xtol*xnorm) - *info = 2; - if( (fabs(actred) <= ftol) && (prered <= ftol) && (p5*ratio <= one) && ( *info == 2) ) - *info = 3; - if( *info != 0) - goto L300; - - // tests for termination and stringent tolerances. - - if( *nfev >= maxfev) - *info = 5; - if( (fabs(actred) <= m_eps) && (prered <= m_eps) && (p5*ratio <= one) ) - *info = 6; - if(delta <= m_eps*xnorm) - *info = 7; - if(gnorm <= m_eps) - *info = 8; - if( *info != 0) - goto L300; - - // end of the inner loop. repeat if iteration unsuccessful. + delta = temp * dmin1(delta, pnorm / p1); + par = par / temp; + } + else { + if ((par == zero) || (ratio >= p75)) { + delta = pnorm / p5; + par = p5 * par; + } + } - if(ratio < p0001) - goto L200; + // test for successful iteration. - // end of the outer loop. + if (ratio >= p0001) { + // successful iteration. update x, fvec, and their norms. - goto L30; + for (j = 0; j < n; j++) { + x[j] = wa2[j]; + wa2[j] = diag[j] * x[j]; + } + for (i = 0; i < m; i++) { + fvec[i] = wa4[i]; + } + xnorm = enorm(n, wa2); + fnorm = fnorm1; + iter += 1; + } + + // tests for convergence. + + if ((fabs(actred) <= ftol) && (prered <= ftol) && (p5 * ratio <= one)) { + *info = 1; + } + if (delta <= xtol * xnorm) { + *info = 2; + } + if ((fabs(actred) <= ftol) && (prered <= ftol) && (p5 * ratio <= one) && (*info == 2)) { + *info = 3; + } + if (*info != 0) { + goto L300; + } + + // tests for termination and stringent tolerances. + + if (*nfev >= maxfev) { + *info = 5; + } + if ((fabs(actred) <= m_eps) && (prered <= m_eps) && (p5 * ratio <= one)) { + *info = 6; + } + if (delta <= m_eps * xnorm) { + *info = 7; + } + if (gnorm <= m_eps) { + *info = 8; + } + if (*info != 0) { + goto L300; + } + + // end of the inner loop. repeat if iteration unsuccessful. + + if (ratio < p0001) { + goto L200; + } + + // end of the outer loop. + + goto L30; L300: - // termination, either normal or user imposed. + // termination, either normal or user imposed. - if(iflag < 0) - *info = iflag; - iflag = 0; - if(nprint > 0) - fcn(m,n,x,fvec,&iflag); + if (iflag < 0) { + *info = iflag; + } + iflag = 0; + if (nprint > 0) { + fcn(m, n, x, fvec, &iflag); + } } /************************lmpar.c*************************/ #define BUG 0 /* ********** -* -* subroutine lmpar -* -* given an m by n matrix a, an n by n nonsingular diagonal -* matrix d, an m-vector b, and a positive number delta, -* the problem is to determine a value for the parameter -* par such that if x solves the system -* -* a*x = b , sqrt(par)*d*x = 0 , -* -* in the least squares sense, and dxnorm is the euclidean -* norm of d*x, then either par is zero and -* -* (dxnorm-delta) .le. 0.1*delta , -* -* or par is positive and -* -* abs(dxnorm-delta) .le. 0.1*delta . -* -* this subroutine completes the solution of the problem -* if it is provided with the necessary information from the -* qr factorization, with column pivoting, of a. that is, if -* a*p = q*r, where p is a permutation matrix, q has orthogonal -* columns, and r is an upper triangular matrix with diagonal -* elements of nonincreasing magnitude, then lmpar expects -* the full upper triangle of r, the permutation matrix p, -* and the first n components of (q transpose)*b. on output -* lmpar also provides an upper triangular matrix s such that -* -* t t t -* p *(a *a + par*d*d)*p = s *s . -* -* s is employed within lmpar and may be of separate interest. -* -* only a few iterations are generally needed for convergence -* of the algorithm. if, however, the limit of 10 iterations -* is reached, then the output par will contain the best -* value obtained so far. -* -* the subroutine statement is -* -* subroutine lmpar(n,r,ldr,ipvt,diag,qtb,delta,par,x,sdiag, -* wa1,wa2) -* -* where -* -* n is a positive integer input variable set to the order of r. -* -* r is an n by n array. on input the full upper triangle -* must contain the full upper triangle of the matrix r. -* on output the full upper triangle is unaltered, and the -* strict lower triangle contains the strict upper triangle -* (transposed) of the upper triangular matrix s. -* -* ldr is a positive integer input variable not less than n -* which specifies the leading dimension of the array r. -* -* ipvt is an integer input array of length n which defines the -* permutation matrix p such that a*p = q*r. column j of p -* is column ipvt(j) of the identity matrix. -* -* diag is an input array of length n which must contain the -* diagonal elements of the matrix d. -* -* qtb is an input array of length n which must contain the first -* n elements of the vector (q transpose)*b. -* -* delta is a positive input variable which specifies an upper -* bound on the euclidean norm of d*x. -* -* par is a nonnegative variable. on input par contains an -* initial estimate of the levenberg-marquardt parameter. -* on output par contains the final estimate. -* -* x is an output array of length n which contains the least -* squares solution of the system a*x = b, sqrt(par)*d*x = 0, -* for the output par. -* -* sdiag is an output array of length n which contains the -* diagonal elements of the upper triangular matrix s. -* -* wa1 and wa2 are work arrays of length n. -* -* subprograms called -* -* minpack-supplied ... dpmpar,enorm,qrsolv -* -* fortran-supplied ... dabs,dmax1,dmin1,dsqrt -* -* argonne national laboratory. minpack project. march 1980. -* burton s. garbow, kenneth e. hillstrom, jorge j. more -* -* ********** -*/ - -void LM_LeastSquare::lmpar(int n, double r[], int ldr, int ipvt[], - double diag[], double qtb[], double delta, double *par, - double x[], double sdiag[], double wa1[], double wa2[]) + * + * subroutine lmpar + * + * given an m by n matrix a, an n by n nonsingular diagonal + * matrix d, an m-vector b, and a positive number delta, + * the problem is to determine a value for the parameter + * par such that if x solves the system + * + * a*x = b , sqrt(par)*d*x = 0 , + * + * in the least squares sense, and dxnorm is the euclidean + * norm of d*x, then either par is zero and + * + * (dxnorm-delta) .le. 0.1*delta , + * + * or par is positive and + * + * abs(dxnorm-delta) .le. 0.1*delta . + * + * this subroutine completes the solution of the problem + * if it is provided with the necessary information from the + * qr factorization, with column pivoting, of a. that is, if + * a*p = q*r, where p is a permutation matrix, q has orthogonal + * columns, and r is an upper triangular matrix with diagonal + * elements of nonincreasing magnitude, then lmpar expects + * the full upper triangle of r, the permutation matrix p, + * and the first n components of (q transpose)*b. on output + * lmpar also provides an upper triangular matrix s such that + * + * t t t + * p *(a *a + par*d*d)*p = s *s . + * + * s is employed within lmpar and may be of separate interest. + * + * only a few iterations are generally needed for convergence + * of the algorithm. if, however, the limit of 10 iterations + * is reached, then the output par will contain the best + * value obtained so far. + * + * the subroutine statement is + * + * subroutine lmpar(n,r,ldr,ipvt,diag,qtb,delta,par,x,sdiag, + * wa1,wa2) + * + * where + * + * n is a positive integer input variable set to the order of r. + * + * r is an n by n array. on input the full upper triangle + * must contain the full upper triangle of the matrix r. + * on output the full upper triangle is unaltered, and the + * strict lower triangle contains the strict upper triangle + * (transposed) of the upper triangular matrix s. + * + * ldr is a positive integer input variable not less than n + * which specifies the leading dimension of the array r. + * + * ipvt is an integer input array of length n which defines the + * permutation matrix p such that a*p = q*r. column j of p + * is column ipvt(j) of the identity matrix. + * + * diag is an input array of length n which must contain the + * diagonal elements of the matrix d. + * + * qtb is an input array of length n which must contain the first + * n elements of the vector (q transpose)*b. + * + * delta is a positive input variable which specifies an upper + * bound on the euclidean norm of d*x. + * + * par is a nonnegative variable. on input par contains an + * initial estimate of the levenberg-marquardt parameter. + * on output par contains the final estimate. + * + * x is an output array of length n which contains the least + * squares solution of the system a*x = b, sqrt(par)*d*x = 0, + * for the output par. + * + * sdiag is an output array of length n which contains the + * diagonal elements of the upper triangular matrix s. + * + * wa1 and wa2 are work arrays of length n. + * + * subprograms called + * + * minpack-supplied ... dpmpar,enorm,qrsolv + * + * fortran-supplied ... dabs,dmax1,dmin1,dsqrt + * + * argonne national laboratory. minpack project. march 1980. + * burton s. garbow, kenneth e. hillstrom, jorge j. more + * + * ********** + */ + +void LM_LeastSquare::lmpar(int n, double r[], int ldr, int ipvt[], double diag[], double qtb[], + double delta, double *par, double x[], double sdiag[], double wa1[], + double wa2[]) { - int i,iter,ij,jj,j,jm1,jp1,k,l,nsing; - double dxnorm,fp,gnorm,parc,parl,paru; - double sum,temp; - static double zero = 0.0; - // static double one = 1.0; - static double p1 = 0.1; - static double p001 = 0.001; + int i, iter, ij, jj, j, jm1, jp1, k, l, nsing; + double dxnorm, fp, gnorm, parc, parl, paru; + double sum, temp; + static double zero = 0.0; + // static double one = 1.0; + static double p1 = 0.1; + static double p001 = 0.001; #if BUG - printf( "lmpar\n" ); + printf("lmpar\n"); #endif - // compute and store in x the gauss-newton direction. if the - // jacobian is rank-deficient, obtain a least squares solution. + // compute and store in x the gauss-newton direction. if the + // jacobian is rank-deficient, obtain a least squares solution. - nsing = n; - jj = 0; - for( j=0; j= 1) - { - for( k=0; k= 0) - { - ij = ldr * j; - for( i=0; i<=jm1; i++ ) - { - wa1[i] -= r[ij]*temp; - ij += 1; - } - } + if (nsing >= 1) { + for (k = 0; k < nsing; k++) { + j = nsing - k - 1; + wa1[j] = wa1[j] / r[j + ldr * j]; + temp = wa1[j]; + jm1 = j - 1; + if (jm1 >= 0) { + ij = ldr * j; + for (i = 0; i <= jm1; i++) { + wa1[i] -= r[ij] * temp; + ij += 1; } + } } - - for( j=0; j= n) { + for (j = 0; j < n; j++) { + l = ipvt[j]; + wa1[j] = diag[l] * (wa2[l] / dxnorm); } - - // if the jacobian is not rank deficient, the newton - // step provides a lower bound, parl, for the zero of - // the function. otherwise set this bound to zero. - - parl = zero; - if(nsing >= n) - { - for( j=0; j= 0) - { - ij = jj; - for( i=0; i<=jm1; i++ ) - { - sum += r[ij]*wa1[i]; - ij += 1; - } - } - wa1[j] = (wa1[j] - sum)/r[j+ldr*j]; - jj += ldr; // [i+ldr*j] - } - temp = enorm(n,wa1); - parl = ((fp/delta)/temp)/temp; - } - - // calculate an upper bound, paru, for the zero of the function. - jj = 0; - for( j=0; j= 0) { ij = jj; - for( i=0; i<=j; i++ ) - { - sum += r[ij]*qtb[i]; - ij += 1; + for (i = 0; i <= jm1; i++) { + sum += r[ij] * wa1[i]; + ij += 1; } - l = ipvt[j]; - wa1[j] = sum/diag[l]; - jj += ldr; // [i+ldr*j] + } + wa1[j] = (wa1[j] - sum) / r[j + ldr * j]; + jj += ldr; // [i+ldr*j] } - gnorm = enorm(n,wa1); - paru = gnorm/delta; - if(paru == zero) - paru = m_dwarf/dmin1(delta,p1); - - // if the input par lies outside of the interval (parl,paru), - // set par to the closer endpoint. - - *par = dmax1( *par,parl); - *par = dmin1( *par,paru); - if( *par == zero) - *par = gnorm/dxnorm; + temp = enorm(n, wa1); + parl = ((fp / delta) / temp) / temp; + } + + // calculate an upper bound, paru, for the zero of the function. + + jj = 0; + for (j = 0; j < n; j++) { + sum = zero; + ij = jj; + for (i = 0; i <= j; i++) { + sum += r[ij] * qtb[i]; + ij += 1; + } + l = ipvt[j]; + wa1[j] = sum / diag[l]; + jj += ldr; // [i+ldr*j] + } + gnorm = enorm(n, wa1); + paru = gnorm / delta; + if (paru == zero) { + paru = m_dwarf / dmin1(delta, p1); + } + + // if the input par lies outside of the interval (parl,paru), + // set par to the closer endpoint. + + *par = dmax1(*par, parl); + *par = dmin1(*par, paru); + if (*par == zero) { + *par = gnorm / dxnorm; + } #if BUG - printf( "parl %.4e par %.4e paru %.4e\n", parl, *par, paru ); + printf("parl %.4e par %.4e paru %.4e\n", parl, *par, paru); #endif - // beginning of an iteration. + // beginning of an iteration. L150: - iter += 1; - - // evaluate the function at the current value of par. - - if( *par == zero) - *par = dmax1(m_dwarf,p001*paru); - temp = sqrt( *par ); - for( j=0; j zero) - parl = dmax1(parl, *par); - if(fp < zero) - paru = dmin1(paru, *par); + if (fp > zero) { + parl = dmax1(parl, *par); + } + if (fp < zero) { + paru = dmin1(paru, *par); + } - // compute an improved estimate for par. + // compute an improved estimate for par. - *par = dmax1(parl, *par + parc); + *par = dmax1(parl, *par + parc); - // end of an iteration. + // end of an iteration. - goto L150; + goto L150; L220: - // termination. + // termination. - if(iter == 0) - *par = zero; + if (iter == 0) { + *par = zero; + } } /************************qrfac.c*************************/ #define BUG 0 /* -* ********** -* -* subroutine qrfac -* -* this subroutine uses householder transformations with column -* pivoting (optional) to compute a qr factorization of the -* m by n matrix a. that is, qrfac determines an orthogonal -* matrix q, a permutation matrix p, and an upper trapezoidal -* matrix r with diagonal elements of nonincreasing magnitude, -* such that a*p = q*r. the householder transformation for -* column k, k = 1,2,...,min(m,n), is of the form -* -* t -* i - (1/u(k))*u*u -* -* where u has zeros in the first k-1 positions. the form of -* this transformation and the method of pivoting first -* appeared in the corresponding linpack subroutine. -* -* the subroutine statement is -* -* subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) -* -* where -* -* m is a positive integer input variable set to the number -* of rows of a. -* -* n is a positive integer input variable set to the number -* of columns of a. -* -* a is an m by n array. on input a contains the matrix for -* which the qr factorization is to be computed. on output -* the strict upper trapezoidal part of a contains the strict -* upper trapezoidal part of r, and the lower trapezoidal -* part of a contains a factored form of q (the non-trivial -* elements of the u vectors described above). -* -* lda is a positive integer input variable not less than m -* which specifies the leading dimension of the array a. -* -* pivot is a logical input variable. if pivot is set true, -* then column pivoting is enforced. if pivot is set false, -* then no column pivoting is done. -* -* ipvt is an integer output array of length lipvt. ipvt -* defines the permutation matrix p such that a*p = q*r. -* column j of p is column ipvt(j) of the identity matrix. -* if pivot is false, ipvt is not referenced. -* -* lipvt is a positive integer input variable. if pivot is false, -* then lipvt may be as small as 1. if pivot is true, then -* lipvt must be at least n. -* -* rdiag is an output array of length n which contains the -* diagonal elements of r. -* -* acnorm is an output array of length n which contains the -* norms of the corresponding columns of the input matrix a. -* if this information is not needed, then acnorm can coincide -* with rdiag. -* -* wa is a work array of length n. if pivot is false, then wa -* can coincide with rdiag. -* -* subprograms called -* -* minpack-supplied ... dpmpar,enorm -* -* fortran-supplied ... dmax1,dsqrt,min0 -* -* argonne national laboratory. minpack project. march 1980. -* burton s. garbow, kenneth e. hillstrom, jorge j. more -* -* ********** -*/ + * ********** + * + * subroutine qrfac + * + * this subroutine uses householder transformations with column + * pivoting (optional) to compute a qr factorization of the + * m by n matrix a. that is, qrfac determines an orthogonal + * matrix q, a permutation matrix p, and an upper trapezoidal + * matrix r with diagonal elements of nonincreasing magnitude, + * such that a*p = q*r. the householder transformation for + * column k, k = 1,2,...,min(m,n), is of the form + * + * t + * i - (1/u(k))*u*u + * + * where u has zeros in the first k-1 positions. the form of + * this transformation and the method of pivoting first + * appeared in the corresponding linpack subroutine. + * + * the subroutine statement is + * + * subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) + * + * where + * + * m is a positive integer input variable set to the number + * of rows of a. + * + * n is a positive integer input variable set to the number + * of columns of a. + * + * a is an m by n array. on input a contains the matrix for + * which the qr factorization is to be computed. on output + * the strict upper trapezoidal part of a contains the strict + * upper trapezoidal part of r, and the lower trapezoidal + * part of a contains a factored form of q (the non-trivial + * elements of the u vectors described above). + * + * lda is a positive integer input variable not less than m + * which specifies the leading dimension of the array a. + * + * pivot is a logical input variable. if pivot is set true, + * then column pivoting is enforced. if pivot is set false, + * then no column pivoting is done. + * + * ipvt is an integer output array of length lipvt. ipvt + * defines the permutation matrix p such that a*p = q*r. + * column j of p is column ipvt(j) of the identity matrix. + * if pivot is false, ipvt is not referenced. + * + * lipvt is a positive integer input variable. if pivot is false, + * then lipvt may be as small as 1. if pivot is true, then + * lipvt must be at least n. + * + * rdiag is an output array of length n which contains the + * diagonal elements of r. + * + * acnorm is an output array of length n which contains the + * norms of the corresponding columns of the input matrix a. + * if this information is not needed, then acnorm can coincide + * with rdiag. + * + * wa is a work array of length n. if pivot is false, then wa + * can coincide with rdiag. + * + * subprograms called + * + * minpack-supplied ... dpmpar,enorm + * + * fortran-supplied ... dmax1,dsqrt,min0 + * + * argonne national laboratory. minpack project. march 1980. + * burton s. garbow, kenneth e. hillstrom, jorge j. more + * + * ********** + */ void LM_LeastSquare::qrfac(int m, int n, double a[], int WXUNUSED(lda), int pivot, int ipvt[], int WXUNUSED(lipvt), double rdiag[], double acnorm[], double wa[]) { - int i,ij,jj,j,jp1,k,kmax,minmn; - double ajnorm,sum,temp; - static double zero = 0.0; - static double one = 1.0; - static double p05 = 0.05; - - // compute the initial column norms and initialize several arrays. - - ij = 0; - for( j=0; j rdiag[kmax]) - kmax = k; - } - if(kmax == j) - goto L40; - - ij = m * j; - jj = m * kmax; - for( i=0; i rdiag[kmax]) { + kmax = k; + } + } + if (kmax == j) { + goto L40; + } - // apply the transformation to the remaining columns and update the norms. + ij = m * j; + jj = m * kmax; + for (i = 0; i < m; i++) { + temp = a[ij]; // [i+m*j] + a[ij] = a[jj]; // [i+m*kmax] + a[jj] = temp; + ij += 1; + jj += 1; + } + rdiag[kmax] = rdiag[j]; + wa[kmax] = wa[j]; + k = ipvt[j]; + ipvt[j] = ipvt[kmax]; + ipvt[kmax] = k; - jp1 = j + 1; - if(jp1 < n ) - { - for( k=jp1; k kp1 ) - { - ik = kk + 1; - for( i=kp1; i kp1) { + ik = kk + 1; + for (i = kp1; i < n; i++) { + temp = cos * r[ik] + sin * sdiag[i]; + sdiag[i] = -sin * r[ik] + cos * sdiag[i]; + r[ik] = temp; + ik += 1; // [i+ldr*k] } -L90: + } + } + L90: - // store the diagonal element of s and restore - // the corresponding diagonal element of r. + // store the diagonal element of s and restore + // the corresponding diagonal element of r. - kk = j + ldr*j; - sdiag[j] = r[kk]; - r[kk] = x[j]; - } + kk = j + ldr * j; + sdiag[j] = r[kk]; + r[kk] = x[j]; + } - // solve the triangular system for z. if the system is - // singular, then obtain a least squares solution. + // solve the triangular system for z. if the system is + // singular, then obtain a least squares solution. - nsing = n; - for( j=0; j jp1) - { - ij = jp1 + ldr * j; - for( i=jp1; i jp1) { + ij = jp1 + ldr * j; + for (i = jp1; i < nsing; i++) { + sum += r[ij] * wa[i]; + ij += 1; // [i+ldr*j] + } } + wa[j] = (wa[j] - sum) / sdiag[j]; + } L150: - // permute the components of z back to components of x. + // permute the components of z back to components of x. - for( j=0; j rdwarf) && (xabs < agiant) ) - { - // sum for intermediate components. - s2 += xabs*xabs; - continue; - } - - if(xabs > rdwarf) - { - // sum for large components. - if(xabs > x1max) - { - temp = x1max/xabs; - s1 = one + s1*temp*temp; - x1max = xabs; - } - else - { - temp = xabs/x1max; - s1 += temp*temp; - } - continue; - } + int i; + double agiant, floatn, s1, s2, s3, xabs, x1max, x3max; + double ans, temp; + static double rdwarf = 3.834e-20; + static double rgiant = 1.304e19; + static double zero = 0.0; + static double one = 1.0; + + s1 = zero; + s2 = zero; + s3 = zero; + x1max = zero; + x3max = zero; + floatn = n; + agiant = rgiant / floatn; + + for (i = 0; i < n; i++) { + xabs = fabs(x[i]); + if ((xabs > rdwarf) && (xabs < agiant)) { + // sum for intermediate components. + s2 += xabs * xabs; + continue; + } - // sum for small components. - if(xabs > x3max) - { - temp = x3max/xabs; - s3 = one + s3*temp*temp; - x3max = xabs; - } - else - { - if(xabs != zero) - { - temp = xabs/x3max; - s3 += temp*temp; - } - } + if (xabs > rdwarf) { + // sum for large components. + if (xabs > x1max) { + temp = x1max / xabs; + s1 = one + s1 * temp * temp; + x1max = xabs; + } + else { + temp = xabs / x1max; + s1 += temp * temp; + } + continue; } - // calculation of norm. - if(s1 != zero) - { - temp = s1 + (s2/x1max)/x1max; - ans = x1max*sqrt(temp); - return(ans); + // sum for small components. + if (xabs > x3max) { + temp = x3max / xabs; + s3 = one + s3 * temp * temp; + x3max = xabs; + } + else { + if (xabs != zero) { + temp = xabs / x3max; + s3 += temp * temp; + } } - if(s2 != zero) - { - if(s2 >= x3max) - temp = s2*(one+(x3max/s2)*(x3max*s3)); - else - temp = x3max*((s2/x3max)+(x3max*s3)); - ans = sqrt(temp); + } + + // calculation of norm. + if (s1 != zero) { + temp = s1 + (s2 / x1max) / x1max; + ans = x1max * sqrt(temp); + return (ans); + } + if (s2 != zero) { + if (s2 >= x3max) { + temp = s2 * (one + (x3max / s2) * (x3max * s3)); } - else - { - ans = x3max*sqrt(s3); + else { + temp = x3max * ((s2 / x3max) + (x3max * s3)); } - return(ans); + ans = sqrt(temp); + } + else { + ans = x3max * sqrt(s3); + } + return (ans); } /************************fdjac2.c*************************/ @@ -1811,114 +1847,114 @@ double LM_LeastSquare::enorm(int n, double x[]) #define BUG 0 /* -* ********** -* -* subroutine fdjac2 -* -* this subroutine computes a forward-difference approximation -* to the m by n jacobian matrix associated with a specified -* problem of m functions in n variables. -* -* the subroutine statement is -* -* subroutine fdjac2(fcn,m,n,x,fvec,fjac,ldfjac,iflag,epsfcn,wa) -* -* where -* -* fcn is the name of the user-supplied subroutine which -* calculates the functions. fcn must be declared -* in an external statement in the user calling -* program, and should be written as follows. -* -* subroutine fcn(m,n,x,fvec,iflag) -* integer m,n,iflag -* double precision x(n),fvec(m) -* ---------- -* calculate the functions at x and -* return this vector in fvec. -* ---------- -* return -* end -* -* the value of iflag should not be changed by fcn unless -* the user wants to terminate execution of fdjac2. -* in this case set iflag to a negative integer. -* -* m is a positive integer input variable set to the number -* of functions. -* -* n is a positive integer input variable set to the number -* of variables. n must not exceed m. -* -* x is an input array of length n. -* -* fvec is an input array of length m which must contain the -* functions evaluated at x. -* -* fjac is an output m by n array which contains the -* approximation to the jacobian matrix evaluated at x. -* -* ldfjac is a positive integer input variable not less than m -* which specifies the leading dimension of the array fjac. -* -* iflag is an integer variable which can be used to terminate -* the execution of fdjac2. see description of fcn. -* -* epsfcn is an input variable used in determining a suitable -* step length for the forward-difference approximation. this -* approximation assumes that the relative errors in the -* functions are of the order of epsfcn. if epsfcn is less -* than the machine precision, it is assumed that the relative -* errors in the functions are of the order of the machine -* precision. -* -* wa is a work array of length m. -* -* subprograms called -* -* user-supplied ...... fcn -* -* minpack-supplied ... dpmpar -* -* fortran-supplied ... dabs,dmax1,dsqrt -* -* argonne national laboratory. minpack project. march 1980. -* burton s. garbow, kenneth e. hillstrom, jorge j. more -* - ********** -*/ - -void LM_LeastSquare::fdjac2(int m,int n, double x[], double fvec[], double fjac[], + * ********** + * + * subroutine fdjac2 + * + * this subroutine computes a forward-difference approximation + * to the m by n jacobian matrix associated with a specified + * problem of m functions in n variables. + * + * the subroutine statement is + * + * subroutine fdjac2(fcn,m,n,x,fvec,fjac,ldfjac,iflag,epsfcn,wa) + * + * where + * + * fcn is the name of the user-supplied subroutine which + * calculates the functions. fcn must be declared + * in an external statement in the user calling + * program, and should be written as follows. + * + * subroutine fcn(m,n,x,fvec,iflag) + * integer m,n,iflag + * double precision x(n),fvec(m) + * ---------- + * calculate the functions at x and + * return this vector in fvec. + * ---------- + * return + * end + * + * the value of iflag should not be changed by fcn unless + * the user wants to terminate execution of fdjac2. + * in this case set iflag to a negative integer. + * + * m is a positive integer input variable set to the number + * of functions. + * + * n is a positive integer input variable set to the number + * of variables. n must not exceed m. + * + * x is an input array of length n. + * + * fvec is an input array of length m which must contain the + * functions evaluated at x. + * + * fjac is an output m by n array which contains the + * approximation to the jacobian matrix evaluated at x. + * + * ldfjac is a positive integer input variable not less than m + * which specifies the leading dimension of the array fjac. + * + * iflag is an integer variable which can be used to terminate + * the execution of fdjac2. see description of fcn. + * + * epsfcn is an input variable used in determining a suitable + * step length for the forward-difference approximation. this + * approximation assumes that the relative errors in the + * functions are of the order of epsfcn. if epsfcn is less + * than the machine precision, it is assumed that the relative + * errors in the functions are of the order of the machine + * precision. + * + * wa is a work array of length m. + * + * subprograms called + * + * user-supplied ...... fcn + * + * minpack-supplied ... dpmpar + * + * fortran-supplied ... dabs,dmax1,dsqrt + * + * argonne national laboratory. minpack project. march 1980. + * burton s. garbow, kenneth e. hillstrom, jorge j. more + * + ********** + */ + +void LM_LeastSquare::fdjac2(int m, int n, double x[], double fvec[], double fjac[], int WXUNUSED(ldfjac), int *iflag, double epsfcn, double wa[]) { - int i,j,ij; - double eps,h,temp; - static double zero = 0.0; + int i, j, ij; + double eps, h, temp; + static double zero = 0.0; - temp = dmax1(epsfcn,m_eps); - eps = sqrt(temp); + temp = dmax1(epsfcn, m_eps); + eps = sqrt(temp); #if BUG - printf( "fdjac2\n" ); + printf("fdjac2\n"); #endif - ij = 0; - for( j=0; jm_type = buff; + s++; + start = i + 1; + break; + } + else if ((*s != tab) && (*s != cr) && (*s != lf) && (*s != ccr)) { + buff.Append(*s); + } + else { + return false; + } + } + } + + buff.Clear(); + for (i = start; i < length; i++) // add options + { + // add up characters until an = sign then the word before is the name + // the rest of the string before that is the value for the previous name + if (*s != equals) { + buff.Append(*s); + } + else { + buff.Trim(false).Trim(true); + if (!buff.IsEmpty()) { + const wxChar *t = buff.GetData(); + int j; + for (j = buff.Length() - 1; j >= 0; j--) { + const wxChar c = t[j]; + if ((c == cr) || (c == lf) || (c == ccr) || (c == tab)) { + j++; break; + } } - } - if (has_type) - { - for (i=start; im_type = buff; - s++; - start = i+1; - break; - } - else if ((*s != tab) && (*s != cr) && (*s != lf) && (*s != ccr)) - { - buff.Append(*s); - } - else - return false; + if (j < 0) { + j = 0; } - } + M_OPTVALUDATA->m_optionNames.Add(buff.Mid(j)); + buff.Remove(j).Trim(true); + } + if (!buff.IsEmpty()) { + M_OPTVALUDATA->m_optionValues.Add(buff); + } - buff.Clear(); - for (i=start; i=0; j--) - { - const wxChar c = t[j]; - if ((c == cr) || (c == lf) || (c == ccr) || (c == tab)) - { - j++; - break; - } - } - if (j<0) j = 0; - M_OPTVALUDATA->m_optionNames.Add(buff.Mid(j)); - buff.Remove(j).Trim(true); - } - if (!buff.IsEmpty()) - M_OPTVALUDATA->m_optionValues.Add(buff); - - buff.Clear(); - } - s++; + buff.Clear(); } + s++; + } - buff.Trim(false).Trim(true); - if (!buff.IsEmpty()) - M_OPTVALUDATA->m_optionValues.Add(buff); + buff.Trim(false).Trim(true); + if (!buff.IsEmpty()) { + M_OPTVALUDATA->m_optionValues.Add(buff); + } - if ((M_OPTVALUDATA->m_optionValues.GetCount() != M_OPTVALUDATA->m_optionNames.GetCount())) - { - int i; - wxPrintf(wxT("wxOptionValue::wxOptionValue( const wxString &string BUSTED\n")); - - wxPrintf(wxT("[%s]\n"), M_OPTVALUDATA->m_type.c_str()); - for (i=0; i<(int)M_OPTVALUDATA->m_optionNames.GetCount(); i++) - wxPrintf(wxT("{%s}\n"), M_OPTVALUDATA->m_optionNames[i].c_str()); - for (i=0; i<(int)M_OPTVALUDATA->m_optionValues.GetCount(); i++) - wxPrintf(wxT("{%s}\n"), M_OPTVALUDATA->m_optionValues[i].c_str()); - fflush(stdout); + if ((M_OPTVALUDATA->m_optionValues.GetCount() != M_OPTVALUDATA->m_optionNames.GetCount())) { + int i; + wxPrintf(wxT("wxOptionValue::wxOptionValue( const wxString &string BUSTED\n")); + + wxPrintf(wxT("[%s]\n"), M_OPTVALUDATA->m_type.c_str()); + for (i = 0; i < (int)M_OPTVALUDATA->m_optionNames.GetCount(); i++) { + wxPrintf(wxT("{%s}\n"), M_OPTVALUDATA->m_optionNames[i].c_str()); + } + for (i = 0; i < (int)M_OPTVALUDATA->m_optionValues.GetCount(); i++) { + wxPrintf(wxT("{%s}\n"), M_OPTVALUDATA->m_optionValues[i].c_str()); } + fflush(stdout); + } - return ((M_OPTVALUDATA->m_optionValues.GetCount() > 0) && - (M_OPTVALUDATA->m_optionValues.GetCount() != - M_OPTVALUDATA->m_optionNames.GetCount())); + return ((M_OPTVALUDATA->m_optionValues.GetCount() > 0) && + (M_OPTVALUDATA->m_optionValues.GetCount() != M_OPTVALUDATA->m_optionNames.GetCount())); } -bool wxOptionValue::Copy( const wxOptionValue &optValue ) +bool wxOptionValue::Copy(const wxOptionValue &optValue) { - wxCHECK_MSG( optValue.Ok(), false, wxT("Invalid wxOptionValue") ); + wxCHECK_MSG(optValue.Ok(), false, wxT("Invalid wxOptionValue")); - if (!Ok()) Create(); + if (!Ok()) { + Create(); + } - M_OPTVALUDATA->m_type = optValue.GetType(); - M_OPTVALUDATA->m_optionNames = optValue.GetOptionNames(); - M_OPTVALUDATA->m_optionValues = optValue.GetOptionValues(); - if (optValue.GetChildrenCount()) - M_OPTVALUDATA->m_children = *optValue.GetChildren(); - else - M_OPTVALUDATA->m_children.Clear(); + M_OPTVALUDATA->m_type = optValue.GetType(); + M_OPTVALUDATA->m_optionNames = optValue.GetOptionNames(); + M_OPTVALUDATA->m_optionValues = optValue.GetOptionValues(); + if (optValue.GetChildrenCount()) { + M_OPTVALUDATA->m_children = *optValue.GetChildren(); + } + else { + M_OPTVALUDATA->m_children.Clear(); + } - return true; + return true; } -bool wxOptionValue::Ok() const -{ - return M_OPTVALUDATA != NULL; -} +bool wxOptionValue::Ok() const { return M_OPTVALUDATA != NULL; } -void wxOptionValue::Destroy() -{ - UnRef(); -} +void wxOptionValue::Destroy() { UnRef(); } //----------------------------------------------------------------------------- wxString wxOptionValue::GetType() const { - wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxOptionValue") ); - return M_OPTVALUDATA->m_type; + wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxOptionValue")); + return M_OPTVALUDATA->m_type; } -void wxOptionValue::SetType( const wxString &type ) +void wxOptionValue::SetType(const wxString &type) { - wxCHECK_RET( Ok(), wxT("Invalid wxOptionValue") ); - M_OPTVALUDATA->m_type = type; + wxCHECK_RET(Ok(), wxT("Invalid wxOptionValue")); + M_OPTVALUDATA->m_type = type; } //----------------------------------------------------------------------------- size_t wxOptionValue::GetChildrenCount() const { - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxOptionValue") ); - return M_OPTVALUDATA->m_children.GetCount(); + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxOptionValue")); + return M_OPTVALUDATA->m_children.GetCount(); } wxArrayOptionValue *wxOptionValue::GetChildren() const { - wxCHECK_MSG( Ok(), NULL, wxT("Invalid wxOptionValue") ); - return &M_OPTVALUDATA->m_children; + wxCHECK_MSG(Ok(), NULL, wxT("Invalid wxOptionValue")); + return &M_OPTVALUDATA->m_children; } -bool wxOptionValue::AddChild( const wxOptionValue& child ) +bool wxOptionValue::AddChild(const wxOptionValue &child) { - wxCHECK_MSG( Ok() && child.Ok(), 0, wxT("Invalid wxOptionValue") ); - M_OPTVALUDATA->m_children.Add(child); - return true; + wxCHECK_MSG(Ok() && child.Ok(), 0, wxT("Invalid wxOptionValue")); + M_OPTVALUDATA->m_children.Add(child); + return true; } void wxOptionValue::DeleteChildren() { - wxCHECK_RET( Ok(), wxT("Invalid wxOptionValue") ); - M_OPTVALUDATA->m_children.Clear(); + wxCHECK_RET(Ok(), wxT("Invalid wxOptionValue")); + M_OPTVALUDATA->m_children.Clear(); } //----------------------------------------------------------------------------- size_t wxOptionValue::GetOptionCount() const { - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxOptionValue") ); - return M_OPTVALUDATA->m_optionNames.GetCount(); + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxOptionValue")); + return M_OPTVALUDATA->m_optionNames.GetCount(); } wxArrayString wxOptionValue::GetOptionNames() const { - wxCHECK_MSG( Ok(), wxArrayString(), wxT("Invalid wxOptionValue") ); - return M_OPTVALUDATA->m_optionNames; + wxCHECK_MSG(Ok(), wxArrayString(), wxT("Invalid wxOptionValue")); + return M_OPTVALUDATA->m_optionNames; } wxArrayString wxOptionValue::GetOptionValues() const { - wxCHECK_MSG( Ok(), wxArrayString(), wxT("Invalid wxOptionValue") ); - return M_OPTVALUDATA->m_optionValues; + wxCHECK_MSG(Ok(), wxArrayString(), wxT("Invalid wxOptionValue")); + return M_OPTVALUDATA->m_optionValues; } -wxString wxOptionValue::GetOptionName( size_t n ) const +wxString wxOptionValue::GetOptionName(size_t n) const { - wxCHECK_MSG( Ok() && (nm_optionNames.GetCount()), - wxEmptyString, wxT("Invalid wxOptionValue") ); - return M_OPTVALUDATA->m_optionNames[n]; + wxCHECK_MSG(Ok() && (n < M_OPTVALUDATA->m_optionNames.GetCount()), wxEmptyString, + wxT("Invalid wxOptionValue")); + return M_OPTVALUDATA->m_optionNames[n]; } -wxString wxOptionValue::GetOptionValue( size_t n ) const +wxString wxOptionValue::GetOptionValue(size_t n) const { - wxCHECK_MSG( Ok() && (nm_optionValues.GetCount()), - wxEmptyString, wxT("Invalid wxOptionValue") ); - return M_OPTVALUDATA->m_optionValues[n]; + wxCHECK_MSG(Ok() && (n < M_OPTVALUDATA->m_optionValues.GetCount()), wxEmptyString, + wxT("Invalid wxOptionValue")); + return M_OPTVALUDATA->m_optionValues[n]; } -int wxOptionValue::HasOption(const wxString& name) const +int wxOptionValue::HasOption(const wxString &name) const { - wxCHECK_MSG( Ok(), wxNOT_FOUND, wxT("Invalid wxOptionValue") ); - int index = M_OPTVALUDATA->m_optionNames.Index(name, false); - return index; + wxCHECK_MSG(Ok(), wxNOT_FOUND, wxT("Invalid wxOptionValue")); + int index = M_OPTVALUDATA->m_optionNames.Index(name, false); + return index; } int wxOptionValue::FindOption(const wxString &part_of_option_name) const { - wxCHECK_MSG( Ok(), wxNOT_FOUND, wxT("Invalid wxOptionValue") ); - int i, count = M_OPTVALUDATA->m_optionNames.GetCount(); + wxCHECK_MSG(Ok(), wxNOT_FOUND, wxT("Invalid wxOptionValue")); + int i, count = M_OPTVALUDATA->m_optionNames.GetCount(); - for (i=0; im_optionNames[i].Contains(part_of_option_name)) - return i; + for (i = 0; i < count; i++) { + if (M_OPTVALUDATA->m_optionNames[i].Contains(part_of_option_name)) { + return i; } - return wxNOT_FOUND; + } + return wxNOT_FOUND; } bool wxOptionValue::DeleteOption(const wxString &name) { - wxCHECK_MSG( Ok(), false, wxT("Invalid wxOptionValue")); - int index = M_OPTVALUDATA->m_optionNames.Index(name, false); - if (index == wxNOT_FOUND) return false; - M_OPTVALUDATA->m_optionNames.RemoveAt(index); - M_OPTVALUDATA->m_optionValues.RemoveAt(index); - return true; + wxCHECK_MSG(Ok(), false, wxT("Invalid wxOptionValue")); + int index = M_OPTVALUDATA->m_optionNames.Index(name, false); + if (index == wxNOT_FOUND) { + return false; + } + M_OPTVALUDATA->m_optionNames.RemoveAt(index); + M_OPTVALUDATA->m_optionValues.RemoveAt(index); + return true; } -bool wxOptionValue::DeleteOption( size_t n ) +bool wxOptionValue::DeleteOption(size_t n) { - wxCHECK_MSG( Ok(), false, wxT("Invalid wxOptionValue") ); - wxCHECK_MSG( n < M_OPTVALUDATA->m_optionValues.GetCount(), false, wxT("invalid index")); - M_OPTVALUDATA->m_optionNames.RemoveAt(n); - M_OPTVALUDATA->m_optionValues.RemoveAt(n); - return true; + wxCHECK_MSG(Ok(), false, wxT("Invalid wxOptionValue")); + wxCHECK_MSG(n < M_OPTVALUDATA->m_optionValues.GetCount(), false, wxT("invalid index")); + M_OPTVALUDATA->m_optionNames.RemoveAt(n); + M_OPTVALUDATA->m_optionValues.RemoveAt(n); + return true; } //----------------------------------------------------------------------------- // Set Options // Option functions (arbitrary name/value mapping) -void wxOptionValue::SetOption(const wxString& name, const wxString& value, bool force) +void wxOptionValue::SetOption(const wxString &name, const wxString &value, bool force) { - wxCHECK_RET( Ok() && (name.Length() > 0), wxT("Invalid wxOptionValue or option") ); + wxCHECK_RET(Ok() && (name.Length() > 0), wxT("Invalid wxOptionValue or option")); - int idx = M_OPTVALUDATA->m_optionNames.Index(name, false); - if (idx == wxNOT_FOUND) - { - M_OPTVALUDATA->m_optionNames.Add(name); - M_OPTVALUDATA->m_optionValues.Add(value); - } - else if (force) - { - M_OPTVALUDATA->m_optionNames[idx] = name; - M_OPTVALUDATA->m_optionValues[idx] = value; - } + int idx = M_OPTVALUDATA->m_optionNames.Index(name, false); + if (idx == wxNOT_FOUND) { + M_OPTVALUDATA->m_optionNames.Add(name); + M_OPTVALUDATA->m_optionValues.Add(value); + } + else if (force) { + M_OPTVALUDATA->m_optionNames[idx] = name; + M_OPTVALUDATA->m_optionValues[idx] = value; + } } void wxOptionValue::SetOption(const wxString &name, bool update, const wxChar *format, ...) { - va_list argptr; - va_start(argptr, format); - wxString s; - s.PrintfV(format, argptr); - va_end(argptr); - SetOption(name, s, update); + va_list argptr; + va_start(argptr, format); + wxString s; + s.PrintfV(format, argptr); + va_end(argptr); + SetOption(name, s, update); } //----------------------------------------------------------------------------- // Get Options -wxString wxOptionValue::GetOption(const wxString& name) const +wxString wxOptionValue::GetOption(const wxString &name) const { - wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxOptionValue") ); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxOptionValue")); - int idx = M_OPTVALUDATA->m_optionNames.Index(name, false); - if (idx != wxNOT_FOUND) - return M_OPTVALUDATA->m_optionValues[idx]; + int idx = M_OPTVALUDATA->m_optionNames.Index(name, false); + if (idx != wxNOT_FOUND) { + return M_OPTVALUDATA->m_optionValues[idx]; + } - return wxEmptyString; + return wxEmptyString; } -int wxOptionValue::GetOptionInt(const wxString& name) const -{ - return wxAtoi(GetOption(name)); -} +int wxOptionValue::GetOptionInt(const wxString &name) const { return wxAtoi(GetOption(name)); } -bool wxOptionValue::GetOption(const wxString& name, wxString &value ) const +bool wxOptionValue::GetOption(const wxString &name, wxString &value) const { - wxString s = GetOption(name); - if (!s.IsEmpty()) { value = s; return true; } - return false; + wxString s = GetOption(name); + if (!s.IsEmpty()) { + value = s; + return true; + } + return false; } -bool wxOptionValue::GetOption(const wxString& name, int *value ) const +bool wxOptionValue::GetOption(const wxString &name, int *value) const { - long n; - if (GetOption(name).ToLong(&n)) - { - *value = (int)n; - return true; - } - return false; + long n; + if (GetOption(name).ToLong(&n)) { + *value = (int)n; + return true; + } + return false; } -bool wxOptionValue::GetOption(const wxString& name, float *value ) const +bool wxOptionValue::GetOption(const wxString &name, float *value) const { - double n; - if (GetOption(name, &n)) - { - *value = (float)n; - return true; - } - return false; + double n; + if (GetOption(name, &n)) { + *value = (float)n; + return true; + } + return false; } -bool wxOptionValue::GetOption(const wxString& name, double *value ) const +bool wxOptionValue::GetOption(const wxString &name, double *value) const { - double n; - if (GetOption(name).ToDouble(&n)) - { - *value = n; - return true; - } - return false; + double n; + if (GetOption(name).ToDouble(&n)) { + *value = n; + return true; + } + return false; } -int wxOptionValue::GetOption(const wxString& name, const wxChar *format, ...) const +int wxOptionValue::GetOption(const wxString &name, const wxChar *format, ...) const { - wxString n = GetOption(name); - if (n.IsEmpty()) return 0; - va_list argptr; - va_start(argptr, format); -// int i = wxVsscanf(n.c_str(), format, argptr); // VisualStudio doesn't have this - int i = wxSscanf(n.c_str(), format, argptr); - va_end(argptr); - return i; + wxString n = GetOption(name); + if (n.IsEmpty()) { + return 0; + } + va_list argptr; + va_start(argptr, format); + // int i = wxVsscanf(n.c_str(), format, argptr); // VisualStudio doesn't have this + int i = wxSscanf(n.c_str(), format, argptr); + va_end(argptr); + return i; } -int wxOptionValue::GetOption(const wxString& name, wxArrayInt &values, - int count, const wxString& delims) const +int wxOptionValue::GetOption(const wxString &name, wxArrayInt &values, int count, + const wxString &delims) const { - wxString value = GetOption(name); - wxStringTokenizer tokens(value, delims, wxTOKEN_STRTOK); - int read_count = 0; + wxString value = GetOption(name); + wxStringTokenizer tokens(value, delims, wxTOKEN_STRTOK); + int read_count = 0; - while (((count < 0) || (read_count <= count)) && tokens.HasMoreTokens()) - { - long num; - if (!tokens.GetNextToken().ToLong(&num)) return read_count; - values.Add(num); - read_count++; + while (((count < 0) || (read_count <= count)) && tokens.HasMoreTokens()) { + long num; + if (!tokens.GetNextToken().ToLong(&num)) { + return read_count; } - return read_count; + values.Add(num); + read_count++; + } + return read_count; } -bool wxOptionValue::GetOption(const wxString& name, unsigned char *value, int count, - const wxString& delims) const +bool wxOptionValue::GetOption(const wxString &name, unsigned char *value, int count, + const wxString &delims) const { - wxArrayInt intArr; intArr.Alloc(count); - if (GetOption(name, intArr, count, delims) != count) - return false; + wxArrayInt intArr; + intArr.Alloc(count); + if (GetOption(name, intArr, count, delims) != count) { + return false; + } - for (int i = 0; i < count; i++) value[i] = (unsigned char)intArr[i]; - return true; + for (int i = 0; i < count; i++) { + value[i] = (unsigned char)intArr[i]; + } + return true; } -bool wxOptionValue::GetOption(const wxString& name, int *value, int count, - const wxString& delims) const +bool wxOptionValue::GetOption(const wxString &name, int *value, int count, + const wxString &delims) const { - wxArrayInt intArr; intArr.Alloc(count); - if (GetOption(name, intArr, count, delims) != count) - return false; + wxArrayInt intArr; + intArr.Alloc(count); + if (GetOption(name, intArr, count, delims) != count) { + return false; + } - for (int i = 0; i < count; i++) value[i] = intArr[i]; - return true; + for (int i = 0; i < count; i++) { + value[i] = intArr[i]; + } + return true; } -bool wxOptionValue::GetOption(const wxString& name, long *value, int count, - const wxString& delims) const +bool wxOptionValue::GetOption(const wxString &name, long *value, int count, + const wxString &delims) const { - wxArrayInt intArr; intArr.Alloc(count); - if (GetOption(name, intArr, count, delims) != count) - return false; + wxArrayInt intArr; + intArr.Alloc(count); + if (GetOption(name, intArr, count, delims) != count) { + return false; + } - for (int i = 0; i < count; i++) value[i] = intArr[i]; - return true; + for (int i = 0; i < count; i++) { + value[i] = intArr[i]; + } + return true; } -bool wxOptionValue::GetOption(const wxString& name, float *value, int count, - const wxString& delims) const +bool wxOptionValue::GetOption(const wxString &name, float *value, int count, + const wxString &delims) const { - double *nums = (double*)malloc(sizeof(double)*count); - if (GetOption(name, nums, count, delims)) - { - for (int i=0; i < count; i++) value[i] = (float)nums[i]; - free(nums); - return true; + double *nums = (double *)malloc(sizeof(double) * count); + if (GetOption(name, nums, count, delims)) { + for (int i = 0; i < count; i++) { + value[i] = (float)nums[i]; } free(nums); - return false; -} -bool wxOptionValue::GetOption(const wxString& name, double *value, int count, - const wxString& delims) const -{ - wxString optValue = GetOption(name); - wxStringTokenizer tokens(optValue, delims, wxTOKEN_STRTOK); - int read_count = 0; - double *nums = (double*)malloc(sizeof(double)*count); - double num; - - while ((read_count <= count) && tokens.HasMoreTokens()) - { - if (!tokens.GetNextToken().ToDouble(&num)) - { - free(nums); - return false; - } - if (read_count >= count) break; - read_count++; + return true; + } + free(nums); + return false; +} +bool wxOptionValue::GetOption(const wxString &name, double *value, int count, + const wxString &delims) const +{ + wxString optValue = GetOption(name); + wxStringTokenizer tokens(optValue, delims, wxTOKEN_STRTOK); + int read_count = 0; + double *nums = (double *)malloc(sizeof(double) * count); + double num; + + while ((read_count <= count) && tokens.HasMoreTokens()) { + if (!tokens.GetNextToken().ToDouble(&num)) { + free(nums); + return false; } - - if (read_count == count) - { - for (int i = 0; i < count; i++) value[i] = nums[i]; - free(nums); - return true; + if (read_count >= count) { + break; } + read_count++; + } + if (read_count == count) { + for (int i = 0; i < count; i++) { + value[i] = nums[i]; + } free(nums); - return false; -} - - -bool wxOptionValue::GetOption(const wxString& name, int *v1, int *v2, - const wxString& delims) const -{ - wxArrayInt intArr; - if (GetOption(name, intArr, 2, delims) != 2) - return false; - - if (v1) *v1 = intArr[0]; - if (v2) *v2 = intArr[1]; return true; + } + + free(nums); + return false; } -bool wxOptionValue::GetOption(const wxString& name, int *v1, int *v2, int *v3, - const wxString& delims) const + +bool wxOptionValue::GetOption(const wxString &name, int *v1, int *v2, const wxString &delims) const { - wxArrayInt intArr; - if (GetOption(name, intArr, 3, delims) != 3) - return false; + wxArrayInt intArr; + if (GetOption(name, intArr, 2, delims) != 2) { + return false; + } - if (v1) *v1 = intArr[0]; - if (v2) *v2 = intArr[1]; - if (v3) *v3 = intArr[2]; - return true; + if (v1) { + *v1 = intArr[0]; + } + if (v2) { + *v2 = intArr[1]; + } + return true; } -bool wxOptionValue::GetOption(const wxString& name, float *v1, float *v2, float *v3, - const wxString& delims) const +bool wxOptionValue::GetOption(const wxString &name, int *v1, int *v2, int *v3, + const wxString &delims) const { - double nums[3]; - if (GetOption(name, nums, 3, delims)) - return false; + wxArrayInt intArr; + if (GetOption(name, intArr, 3, delims) != 3) { + return false; + } + + if (v1) { + *v1 = intArr[0]; + } + if (v2) { + *v2 = intArr[1]; + } + if (v3) { + *v3 = intArr[2]; + } + return true; +} +bool wxOptionValue::GetOption(const wxString &name, float *v1, float *v2, float *v3, + const wxString &delims) const +{ + double nums[3]; + if (GetOption(name, nums, 3, delims)) { + return false; + } - if (v1) *v1 = (float)nums[0]; - if (v2) *v2 = (float)nums[1]; - if (v3) *v3 = (float)nums[2]; - return true; + if (v1) { + *v1 = (float)nums[0]; + } + if (v2) { + *v2 = (float)nums[1]; + } + if (v3) { + *v3 = (float)nums[2]; + } + return true; } -bool wxOptionValue::GetOption(const wxString& name, wxRect &value, - const wxString& delims) const +bool wxOptionValue::GetOption(const wxString &name, wxRect &value, const wxString &delims) const { - wxArrayInt intArr; - if (GetOption(name, intArr, 4, delims) != 4) - return false; + wxArrayInt intArr; + if (GetOption(name, intArr, 4, delims) != 4) { + return false; + } - value = wxRect(intArr[0], intArr[1], intArr[2], intArr[3]); - return true; + value = wxRect(intArr[0], intArr[1], intArr[2], intArr[3]); + return true; } diff --git a/src/labenski/src/plotctrl.cpp b/src/labenski/src/plotctrl.cpp index 94ed7d10c..a8854240b 100644 --- a/src/labenski/src/plotctrl.cpp +++ b/src/labenski/src/plotctrl.cpp @@ -12,24 +12,24 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/scrolbar.h" - #include "wx/event.h" - #include "wx/timer.h" - #include "wx/dcmemory.h" - #include "wx/msgdlg.h" - #include "wx/geometry.h" - #include "wx/sizer.h" - #include "wx/dcclient.h" - #include "wx/textctrl.h" +#include "wx/scrolbar.h" +#include "wx/event.h" +#include "wx/timer.h" +#include "wx/dcmemory.h" +#include "wx/msgdlg.h" +#include "wx/geometry.h" +#include "wx/sizer.h" +#include "wx/dcclient.h" +#include "wx/textctrl.h" #endif // WX_PRECOMP #include "wx/math.h" #include "wx/image.h" -#include "wx/crt.h" // for wxPrintf() +#include "wx/crt.h" // for wxPrintf() #include "wx/plotctrl/plotctrl.h" @@ -37,40 +37,40 @@ // MSVC hogs global namespace with these min/max macros - remove them #ifdef max - #undef max +#undef max #endif #ifdef min - #undef min +#undef min #endif -#ifdef GetYValue // Visual Studio 7 defines this - #undef GetYValue +#ifdef GetYValue // Visual Studio 7 defines this +#undef GetYValue #endif #ifdef wxFinite #undef wxFinite #define wxFinite(x) std::isfinite(x) -#endif // wxFinite +#endif // wxFinite +// #define LONG_TO_WXCOLOUR(c) wxColour((unsigned char)((c>>16)&0xFF), (unsigned char)((c>>8 +// )&0xFF), (unsigned char)((c)&0xFF)) #define WXCOLOUR_TO_LONG(c) +// ((c.Red()<<16)|(c.Green()<<8)|(c.Blue())) -//#define LONG_TO_WXCOLOUR(c) wxColour((unsigned char)((c>>16)&0xFF), (unsigned char)((c>>8 )&0xFF), (unsigned char)((c)&0xFF)) -//#define WXCOLOUR_TO_LONG(c) ((c.Red()<<16)|(c.Green()<<8)|(c.Blue())) +#define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x)-0.5)) -#define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x) - 0.5)) - -#if !wxCHECK_VERSION(2,5,0) - bool WXRECT2DDOUBLE_EQUAL(const wxRect2DDouble& r1, const wxRect2DDouble& r2) - { - return (r1.m_x == r1.m_x) && (r1.m_y == r1.m_y) && - (r1.m_width == r1.m_width) && (r1.m_height == r1.m_height); - } +#if !wxCHECK_VERSION(2, 5, 0) +bool WXRECT2DDOUBLE_EQUAL(const wxRect2DDouble &r1, const wxRect2DDouble &r2) +{ + return (r1.m_x == r1.m_x) && (r1.m_y == r1.m_y) && (r1.m_width == r1.m_width) && + (r1.m_height == r1.m_height); +} #else - #define WXRECT2DDOUBLE_EQUAL(r1, r2) ((r1) == (r2)) +#define WXRECT2DDOUBLE_EQUAL(r1, r2) ((r1) == (r2)) #endif // wxCHECK_VERSION(2,5,0) -#if !wxCHECK_VERSION(2,6,0) - #define wxIMAGE_OPTION_CUR_HOTSPOT_X wxCUR_HOTSPOT_X - #define wxIMAGE_OPTION_CUR_HOTSPOT_Y wxCUR_HOTSPOT_Y -#endif //wxCHECK_VERSION(2,6,0) +#if !wxCHECK_VERSION(2, 6, 0) +#define wxIMAGE_OPTION_CUR_HOTSPOT_X wxCUR_HOTSPOT_X +#define wxIMAGE_OPTION_CUR_HOTSPOT_Y wxCUR_HOTSPOT_Y +#endif // wxCHECK_VERSION(2,6,0) //----------------------------------------------------------------------------- // Consts @@ -80,19 +80,19 @@ #define TIC_STEPS 3 std::numeric_limits wxDouble_limits; -const wxDouble wxPlot_MIN_DBL = wxDouble_limits.min()*10; -const wxDouble wxPlot_MAX_DBL = wxDouble_limits.max()/10; -const wxDouble wxPlot_MAX_RANGE = wxDouble_limits.max()/5; +const wxDouble wxPlot_MIN_DBL = wxDouble_limits.min() * 10; +const wxDouble wxPlot_MAX_DBL = wxDouble_limits.max() / 10; +const wxDouble wxPlot_MAX_RANGE = wxDouble_limits.max() / 5; -//#define BORDER 4 +// #define BORDER 4 // Draw borders around the axes, title, and labels for sizing testing -//#define DRAW_BORDERS +// #define DRAW_BORDERS #include "wx/arrimpl.cpp" -WX_DEFINE_OBJARRAY( wxArrayPoint2DDouble ); -WX_DEFINE_OBJARRAY( wxArrayRect2DDouble ); -WX_DEFINE_OBJARRAY( wxArrayPlotCurve ); +WX_DEFINE_OBJARRAY(wxArrayPoint2DDouble); +WX_DEFINE_OBJARRAY(wxArrayRect2DDouble); +WX_DEFINE_OBJARRAY(wxArrayPlotCurve); #include "../art/ledgrey.xpm" #include "../art/ledgreen.xpm" @@ -106,115 +106,112 @@ static wxCursor s_grabCursor; // Skip the wxWidgets drawing routines since they calc an unnecessary bounding rect // You may turn this off by defining wxPLOT_FAST_GRAPHICS=0 to the compilier #ifndef wxPLOT_FAST_GRAPHICS - #define wxPLOT_FAST_GRAPHICS 0 +#define wxPLOT_FAST_GRAPHICS 0 #endif // wxPLOT_FAST_GRAPHICS #if defined(__WXGTK__) && wxPLOT_FAST_GRAPHICS extern "C" { - #include -} - #define INITIALIZE_FAST_GRAPHICS \ - double dc_scale_x = 1, dc_scale_y = 1; \ - dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ - wxPoint dc_origin = dc->GetDeviceOrigin(); \ - wxWindowDC *winDC = wxDynamicCast(dc, wxWindowDC); \ - GdkWindow *window = NULL; \ - GdkGC *pen = NULL; \ - if (winDC && (dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ - { \ - window = winDC->m_window; \ - pen = winDC->m_penGC; \ - } - - // inline void wxPLOT_DRAW_LINE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0, int x1, int y1) - #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ - if (win && pen) \ - gdk_draw_line( win, pen, x0, y0, x1, y1 ); \ - else \ - dc->DrawLine( x0, y0, x1, y1 ); - - // note : need to draw outline since the filled part isn't really a circle - // gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); // false for outline, true for inside - //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0) - #define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ - if (win && pen) \ - gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); \ - else \ - dc->DrawCircle(x0, y0, 2); +#include +} +#define INITIALIZE_FAST_GRAPHICS \ + double dc_scale_x = 1, dc_scale_y = 1; \ + dc->GetUserScale(&dc_scale_x, &dc_scale_y); \ + wxPoint dc_origin = dc->GetDeviceOrigin(); \ + wxWindowDC *winDC = wxDynamicCast(dc, wxWindowDC); \ + GdkWindow *window = NULL; \ + GdkGC *pen = NULL; \ + if (winDC && (dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0, 0))) { \ + window = winDC->m_window; \ + pen = winDC->m_penGC; \ + } + +// inline void wxPLOT_DRAW_LINE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0, int x1, int +// y1) +#define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ + if (win && pen) \ + gdk_draw_line(win, pen, x0, y0, x1, y1); \ + else \ + dc->DrawLine(x0, y0, x1, y1); + +// note : need to draw outline since the filled part isn't really a circle +// gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); // false for outline, true +// for inside +// inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0) +#define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ + if (win && pen) \ + gdk_draw_arc(win, pen, false, x0 - 2, y0 - 2, 4, 4, 0, 360 * 64); \ + else \ + dc->DrawCircle(x0, y0, 2); #elif defined(__WXMSW__) && wxPLOT_FAST_GRAPHICS - #define INITIALIZE_FAST_GRAPHICS \ - double dc_scale_x = 1, dc_scale_y = 1; \ - dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ - wxPoint dc_origin = dc->GetDeviceOrigin(); \ - HDC window = 0; \ - if ((dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ - window = (HDC)dc->GetHDC(); \ - int pen = 0; pen = 0; // no unused var warning - - //inline void wxPLOT_DRAW_LINE(wxDC *dc, HDC win, int pen, int x0, int y0, int x1, int y1) - #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ - if (win) \ - { \ - (void)MoveToEx(win, x0, y0, NULL); \ - (void)LineTo(win, x1, y1); \ - } \ - else \ - dc->DrawLine( x0, y0, x1, y1 ); - - //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, HDC win, int pen, int x0, int y0) - #define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ - if (win) \ - (void)Ellipse(win, x0-2, y0-2, x0+4, y0+4); \ - else \ - dc->DrawCircle(x0, y0, 2); +#define INITIALIZE_FAST_GRAPHICS \ + double dc_scale_x = 1, dc_scale_y = 1; \ + dc->GetUserScale(&dc_scale_x, &dc_scale_y); \ + wxPoint dc_origin = dc->GetDeviceOrigin(); \ + HDC window = 0; \ + if ((dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0, 0))) \ + window = (HDC)dc->GetHDC(); \ + int pen = 0; \ + pen = 0; // no unused var warning + +// inline void wxPLOT_DRAW_LINE(wxDC *dc, HDC win, int pen, int x0, int y0, int x1, int y1) +#define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ + if (win) { \ + (void)MoveToEx(win, x0, y0, NULL); \ + (void)LineTo(win, x1, y1); \ + } \ + else \ + dc->DrawLine(x0, y0, x1, y1); + +// inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, HDC win, int pen, int x0, int y0) +#define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ + if (win) \ + (void)Ellipse(win, x0 - 2, y0 - 2, x0 + 4, y0 + 4); \ + else \ + dc->DrawCircle(x0, y0, 2); #else // !wxPLOT_FAST_GRAPHICS or not gtk/msw - #define INITIALIZE_FAST_GRAPHICS \ - int window = 0; window = 0; \ - int pen = 0; pen = 0; +#define INITIALIZE_FAST_GRAPHICS \ + int window = 0; \ + window = 0; \ + int pen = 0; \ + pen = 0; - //inline void wxPLOT_DRAW_LINE(wxDC *dc, int win, int pen, int x0, int y0, int x1, int y1) - #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ - dc->DrawLine( x0, y0, x1, y1 ); +// inline void wxPLOT_DRAW_LINE(wxDC *dc, int win, int pen, int x0, int y0, int x1, int y1) +#define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) dc->DrawLine(x0, y0, x1, y1); - //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, int win, int pen, int x0, int y0) - #define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) \ - dc->DrawCircle(x0, y0, 2); +// inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, int win, int pen, int x0, int y0) +#define wxPLOT_DRAW_CIRCLE(dc, win, pen, x0, y0) dc->DrawCircle(x0, y0, 2); #endif // wxPLOT_FAST_GRAPHICS - // differs from wxRect2DDouble::Intersects by allowing for 0 width or height inline bool wxPlotRect2DDoubleIntersects(const wxRect2DDouble &a, const wxRect2DDouble &b) { - return (wxMax(a.m_x, b.m_x) <= wxMin(a.GetRight(), b.GetRight())) && - (wxMax(a.m_y, b.m_y) <= wxMin(a.GetBottom(), b.GetBottom())); + return (wxMax(a.m_x, b.m_x) <= wxMin(a.GetRight(), b.GetRight())) && + (wxMax(a.m_y, b.m_y) <= wxMin(a.GetBottom(), b.GetBottom())); } // same as wxPlotRect2DDouble::Contains, but doesn't convert to wxPoint2DDouble inline bool wxPlotRect2DDoubleContains(double x, double y, const wxRect2DDouble &rect) { - return ((x>=rect.m_x) && (y>=rect.m_y) && (x<=rect.GetRight()) && (y<=rect.GetBottom())); + return ((x >= rect.m_x) && (y >= rect.m_y) && (x <= rect.GetRight()) && (y <= rect.GetBottom())); } // differs from wxRect2DDouble::GetOutCode by swaping top and bottom for plot origin -//inline wxOutCode wxPlotRect2DDoubleOutCode( double x, double y, const wxRect2DDouble &rect ) +// inline wxOutCode wxPlotRect2DDoubleOutCode( double x, double y, const wxRect2DDouble &rect ) //{ // return wxOutCode((x < rect.m_x ? wxOutLeft : // (x > rect.GetRight() ? wxOutRight : wxInside )) + // (y < rect.m_y ? wxOutTop : // (y > rect.GetBottom() ? wxOutBottom : wxInside )) ); //} -#define wxPlotRect2DDoubleOutCode( x, y, rect ) \ - wxOutCode((x < rect.m_x ? wxOutLeft : \ - (x > rect.GetRight() ? wxOutRight : wxInside )) + \ - (y < rect.m_y ? wxOutTop : \ - (y > rect.GetBottom() ? wxOutBottom : wxInside )) ) - +#define wxPlotRect2DDoubleOutCode(x, y, rect) \ + wxOutCode((x < rect.m_x ? wxOutLeft : (x > rect.GetRight() ? wxOutRight : wxInside)) + \ + (y < rect.m_y ? wxOutTop : (y > rect.GetBottom() ? wxOutBottom : wxInside))) // modified Cohen-Sutherland Algorithm for line clipping in at most two passes // the the original endless loop is too unstable @@ -222,23 +219,21 @@ inline bool wxPlotRect2DDoubleContains(double x, double y, const wxRect2DDouble // The line connecting (x0,y0)-(x1,y1) is clipped to rect and which // points were clipped is returned. -enum ClipLine_Type -{ - ClippedNeither = 0x0000, - ClippedFirstX = 0x0001, - ClippedFirstY = 0x0002, - ClippedFirst = ClippedFirstX | ClippedFirstY, - ClippedSecondX = 0x0010, - ClippedSecondY = 0x0020, - ClippedSecond = ClippedSecondX | ClippedSecondY, - ClippedBoth = ClippedFirst | ClippedSecond, - ClippedOut = 0x0100 // no intersection, so can't clip +enum ClipLine_Type { + ClippedNeither = 0x0000, + ClippedFirstX = 0x0001, + ClippedFirstY = 0x0002, + ClippedFirst = ClippedFirstX | ClippedFirstY, + ClippedSecondX = 0x0010, + ClippedSecondY = 0x0020, + ClippedSecond = ClippedSecondX | ClippedSecondY, + ClippedBoth = ClippedFirst | ClippedSecond, + ClippedOut = 0x0100 // no intersection, so can't clip }; // in plotdraw.cpp -extern int ClipLineToRect( double &x0, double &y0, - double &x1, double &y1, - const wxRect2DDouble &rect ); +extern int ClipLineToRect(double &x0, double &y0, double &x1, double &y1, + const wxRect2DDouble &rect); //*************************************************************************** @@ -285,9 +280,9 @@ DEFINE_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGED) // wxPlotSelectionEvent -//DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATING) -//DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATED) -//DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGING) +// DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATING) +// DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATED) +// DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGING) DEFINE_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGED) /* @@ -301,52 +296,57 @@ DEFINE_EVENT_TYPE(wxEVT_PLOT_AREA_CREATE) */ // The code below translates the event.GetEventType to a string name for debugging -#define aDEFINE_LOCAL_EVENT_TYPE(t) if (event.GetEventType() == t) return wxT(#t); +#define aDEFINE_LOCAL_EVENT_TYPE(t) \ + if (event.GetEventType() == t) \ + return wxT(#t); -wxString GetEventName(const wxPlotEvent& event) +wxString GetEventName(const wxPlotEvent &event) { - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_ADD_CURVE) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DELETING_CURVE) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DELETED_CURVE) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_ADD_CURVE) aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_DELETING_CURVE) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DELETED_CURVE) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURVE_SEL_CHANGING) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURVE_SEL_CHANGED) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURVE_SEL_CHANGING) aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_CURVE_SEL_CHANGED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_MOUSE_MOTION) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CLICKED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DOUBLECLICKED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_POINT_CLICKED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_POINT_DOUBLECLICKED) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_MOUSE_MOTION) aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_CLICKED) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_DOUBLECLICKED) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_POINT_CLICKED) aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_POINT_DOUBLECLICKED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATING) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CHANGING) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATED) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATING) aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_AREA_SEL_CHANGING) aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_AREA_SEL_CREATED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_VIEW_CHANGING) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_VIEW_CHANGED) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_VIEW_CHANGING) aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_VIEW_CHANGED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGING) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGED) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGING) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_CURSOR_CHANGED) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_ERROR) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_ERROR) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_BEGIN_TITLE_EDIT) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_END_TITLE_EDIT) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_BEGIN_X_LABEL_EDIT) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_END_X_LABEL_EDIT) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_END_Y_LABEL_EDIT) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_BEGIN_TITLE_EDIT) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_END_TITLE_EDIT) + aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_BEGIN_X_LABEL_EDIT) + aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_END_X_LABEL_EDIT) + aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_BEGIN_Y_LABEL_EDIT) + aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_END_Y_LABEL_EDIT) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGING) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_MOUSE_FUNC_CHANGED) + aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_MOUSE_FUNC_CHANGING) + aDEFINE_LOCAL_EVENT_TYPE( + wxEVT_PLOT_MOUSE_FUNC_CHANGED) - // wxPlotSelectionEvent - //DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATING) - //DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATED) - //DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGING) - aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGED) + // wxPlotSelectionEvent + // DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATING) + // DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CREATED) + // DEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGING) + aDEFINE_LOCAL_EVENT_TYPE(wxEVT_PLOT_RANGE_SEL_CHANGED) - return wxT("Unknown Event Type"); + return wxT("Unknown Event Type"); } //----------------------------------------------------------------------------- @@ -356,17 +356,16 @@ wxString GetEventName(const wxPlotEvent& event) IMPLEMENT_ABSTRACT_CLASS(wxPlotEvent, wxNotifyEvent) wxPlotEvent::wxPlotEvent(wxEventType commandType, int id, wxPlotCtrl *window) - :wxNotifyEvent(commandType, id), m_curve(NULL), m_curveIndex(-1), - m_curveData_index(-1), m_x(0), m_y(0) + : wxNotifyEvent(commandType, id), m_curve(NULL), m_curveIndex(-1), m_curveData_index(-1), m_x(0), + m_y(0) { - SetEventObject( (wxObject*)window ); + SetEventObject((wxObject *)window); } IMPLEMENT_ABSTRACT_CLASS(wxPlotSelectionEvent, wxPlotEvent) -wxPlotSelectionEvent::wxPlotSelectionEvent(wxEventType commandType, int id, - wxPlotCtrl *window) - :wxPlotEvent(commandType, id, window), m_selecting(false) +wxPlotSelectionEvent::wxPlotSelectionEvent(wxEventType commandType, int id, wxPlotCtrl *window) + : wxPlotEvent(commandType, id, window), m_selecting(false) { } @@ -376,108 +375,115 @@ wxPlotSelectionEvent::wxPlotSelectionEvent(wxEventType commandType, int id, IMPLEMENT_CLASS(wxPlotArea, wxWindow) BEGIN_EVENT_TABLE(wxPlotArea, wxWindow) - EVT_ERASE_BACKGROUND( wxPlotArea::OnEraseBackground ) - EVT_PAINT ( wxPlotArea::OnPaint ) - EVT_MOUSE_EVENTS ( wxPlotArea::OnMouse ) - EVT_CHAR ( wxPlotArea::OnChar ) - EVT_KEY_DOWN ( wxPlotArea::OnKeyDown ) - EVT_KEY_UP ( wxPlotArea::OnKeyUp ) +EVT_ERASE_BACKGROUND(wxPlotArea::OnEraseBackground) +EVT_PAINT(wxPlotArea::OnPaint) +EVT_MOUSE_EVENTS(wxPlotArea::OnMouse) +EVT_CHAR(wxPlotArea::OnChar) +EVT_KEY_DOWN(wxPlotArea::OnKeyDown) +EVT_KEY_UP(wxPlotArea::OnKeyUp) END_EVENT_TABLE() -bool wxPlotArea::Create( wxWindow *parent, wxWindowID win_id ) +bool wxPlotArea::Create(wxWindow *parent, wxWindowID win_id) { - if (!wxWindow::Create(parent, win_id, wxDefaultPosition, wxSize(100,100), - wxNO_BORDER|wxWANTS_CHARS|wxCLIP_CHILDREN, wxT("wxPlotArea"))) - return false; + if (!wxWindow::Create(parent, win_id, wxDefaultPosition, wxSize(100, 100), + wxNO_BORDER | wxWANTS_CHARS | wxCLIP_CHILDREN, wxT("wxPlotArea"))) { + return false; + } - m_owner = wxDynamicCast(parent, wxPlotCtrl); - return true; + m_owner = wxDynamicCast(parent, wxPlotCtrl); + return true; } -void wxPlotArea::Init() -{ - m_owner = NULL; -} +void wxPlotArea::Init() { m_owner = NULL; } -void wxPlotArea::OnChar( wxKeyEvent &event ) +void wxPlotArea::OnChar(wxKeyEvent &event) { - if (m_owner) m_owner->ProcessAreaEVT_CHAR(event); + if (m_owner) { + m_owner->ProcessAreaEVT_CHAR(event); + } } -void wxPlotArea::OnKeyDown( wxKeyEvent &event ) +void wxPlotArea::OnKeyDown(wxKeyEvent &event) { - if (m_owner) m_owner->ProcessAreaEVT_KEY_DOWN(event); + if (m_owner) { + m_owner->ProcessAreaEVT_KEY_DOWN(event); + } } -void wxPlotArea::OnKeyUp( wxKeyEvent &event ) +void wxPlotArea::OnKeyUp(wxKeyEvent &event) { - if (m_owner) m_owner->ProcessAreaEVT_KEY_UP(event); + if (m_owner) { + m_owner->ProcessAreaEVT_KEY_UP(event); + } } -void wxPlotArea::OnMouse( wxMouseEvent &event ) +void wxPlotArea::OnMouse(wxMouseEvent &event) { - if (m_owner) m_owner->ProcessAreaEVT_MOUSE_EVENTS(event); + if (m_owner) { + m_owner->ProcessAreaEVT_MOUSE_EVENTS(event); + } } -void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) +void wxPlotArea::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc( this ); - - if (!m_owner || (m_owner->GetRedrawType() & wxPLOT_REDRAW_BLOCKER)) - return; - - int redraw_type = m_owner->GetRedrawType(); + wxPaintDC dc(this); -/* - wxRegionIterator upd( GetUpdateRegion() ); - while (upd) - { - //printf("Region %d %d %d %d \n", upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() ); fflush(stdout); - Paint( &dc, upd.GetRect() ); - upd++; - } -*/ - - if (redraw_type & wxPLOT_REDRAW_PLOT) - { - CreateBitmap( m_owner->GetPlotAreaRect() ); - m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_PLOT); - } - - if (m_bitmap.Ok()) - dc.DrawBitmap(m_bitmap, 0, 0, false); - -#if wxCHECK_VERSION(2,7,0) - if (m_owner->GetCrossHairCursor() && m_owner->GetPlotAreaRect().Contains(m_mousePt)) + if (!m_owner || (m_owner->GetRedrawType() & wxPLOT_REDRAW_BLOCKER)) { + return; + } + + int redraw_type = m_owner->GetRedrawType(); + + /* + wxRegionIterator upd( GetUpdateRegion() ); + while (upd) + { + //printf("Region %d %d %d %d \n", upd.GetX(), upd.GetY(), upd.GetWidth(), upd.GetHeight() + ); fflush(stdout); Paint( &dc, upd.GetRect() ); upd++; + } + */ + + if (redraw_type & wxPLOT_REDRAW_PLOT) { + CreateBitmap(m_owner->GetPlotAreaRect()); + m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_PLOT); + } + + if (m_bitmap.Ok()) { + dc.DrawBitmap(m_bitmap, 0, 0, false); + } + +#if wxCHECK_VERSION(2, 7, 0) + if (m_owner->GetCrossHairCursor() && m_owner->GetPlotAreaRect().Contains(m_mousePt)) #else - if (m_owner->GetCrossHairCursor() && m_owner->GetPlotAreaRect().Inside(m_mousePt)) + if (m_owner->GetCrossHairCursor() && m_owner->GetPlotAreaRect().Inside(m_mousePt)) #endif - m_owner->DrawCrosshairCursor( &dc, m_mousePt ); + m_owner->DrawCrosshairCursor(&dc, m_mousePt); - - m_owner->DrawMouseMarker(&dc, m_owner->GetAreaMouseMarker(), m_mouseRect); + m_owner->DrawMouseMarker(&dc, m_owner->GetAreaMouseMarker(), m_mouseRect); } -void wxPlotArea::CreateBitmap( const wxRect &rect ) +void wxPlotArea::CreateBitmap(const wxRect &rect) { - if (!m_owner) - return; + if (!m_owner) { + return; + } - wxRect refreshRect(rect); - wxRect clientRect(m_owner->GetPlotAreaRect()); - refreshRect.Intersect(clientRect); + wxRect refreshRect(rect); + wxRect clientRect(m_owner->GetPlotAreaRect()); + refreshRect.Intersect(clientRect); - if ((refreshRect.width == 0) || (refreshRect.height == 0)) return; + if ((refreshRect.width == 0) || (refreshRect.height == 0)) { + return; + } - // if the bitmap need to be recreated then refresh everything - if (!m_bitmap.Ok() || (clientRect.width != m_bitmap.GetWidth()) || - (clientRect.height != m_bitmap.GetHeight()) ) - { - m_bitmap.Create(clientRect.width, clientRect.height); - refreshRect = clientRect; - } + // if the bitmap need to be recreated then refresh everything + if (!m_bitmap.Ok() || (clientRect.width != m_bitmap.GetWidth()) || + (clientRect.height != m_bitmap.GetHeight())) { + m_bitmap.Create(clientRect.width, clientRect.height); + refreshRect = clientRect; + } - wxMemoryDC mdc; - mdc.SelectObject( m_bitmap ); - m_owner->DrawAreaWindow( &mdc, refreshRect ); - mdc.SelectObject( wxNullBitmap ); + wxMemoryDC mdc; + mdc.SelectObject(m_bitmap); + m_owner->DrawAreaWindow(&mdc, refreshRect); + mdc.SelectObject(wxNullBitmap); } //----------------------------------------------------------------------------- @@ -486,743 +492,764 @@ void wxPlotArea::CreateBitmap( const wxRect &rect ) IMPLEMENT_CLASS(wxPlotAxis, wxWindow) BEGIN_EVENT_TABLE(wxPlotAxis, wxWindow) - EVT_ERASE_BACKGROUND( wxPlotAxis::OnEraseBackground ) - EVT_PAINT ( wxPlotAxis::OnPaint ) - EVT_MOUSE_EVENTS ( wxPlotAxis::OnMouse ) - EVT_CHAR ( wxPlotAxis::OnChar ) +EVT_ERASE_BACKGROUND(wxPlotAxis::OnEraseBackground) +EVT_PAINT(wxPlotAxis::OnPaint) +EVT_MOUSE_EVENTS(wxPlotAxis::OnMouse) +EVT_CHAR(wxPlotAxis::OnChar) END_EVENT_TABLE() -bool wxPlotAxis::Create( wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style ) +bool wxPlotAxis::Create(wxWindow *parent, wxWindowID win_id, wxPlotAxis_Type style) { - if (!wxWindow::Create(parent, win_id, wxDefaultPosition, wxDefaultSize, - wxNO_BORDER|wxWANTS_CHARS|wxCLIP_CHILDREN, wxT("wxPlotAxis"))) - return false; + if (!wxWindow::Create(parent, win_id, wxDefaultPosition, wxDefaultSize, + wxNO_BORDER | wxWANTS_CHARS | wxCLIP_CHILDREN, wxT("wxPlotAxis"))) { + return false; + } - m_style = style; - m_owner = wxDynamicCast(parent, wxPlotCtrl); + m_style = style; + m_owner = wxDynamicCast(parent, wxPlotCtrl); - if (style == wxPLOT_Y_AXIS) - SetCursor( wxCursor(wxCURSOR_SIZENS) ); - else - SetCursor( wxCursor(wxCURSOR_SIZEWE) ); + if (style == wxPLOT_Y_AXIS) { + SetCursor(wxCursor(wxCURSOR_SIZENS)); + } + else { + SetCursor(wxCursor(wxCURSOR_SIZEWE)); + } - return true; + return true; } void wxPlotAxis::Init() { - m_style = wxPLOT_X_AXIS; - m_owner = NULL; + m_style = wxPLOT_X_AXIS; + m_owner = NULL; } -void wxPlotAxis::OnChar( wxKeyEvent &event ) +void wxPlotAxis::OnChar(wxKeyEvent &event) { - if (m_owner) m_owner->ProcessAxisEVT_CHAR(event); + if (m_owner) { + m_owner->ProcessAxisEVT_CHAR(event); + } } -void wxPlotAxis::OnMouse( wxMouseEvent &event ) +void wxPlotAxis::OnMouse(wxMouseEvent &event) { - if (m_owner) m_owner->ProcessAxisEVT_MOUSE_EVENTS(event); + if (m_owner) { + m_owner->ProcessAxisEVT_MOUSE_EVENTS(event); + } } -void wxPlotAxis::OnPaint( wxPaintEvent &WXUNUSED(event) ) +void wxPlotAxis::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc( this ); - int redraw_type = m_owner->GetRedrawType(); - if (!m_owner || (redraw_type & wxPLOT_REDRAW_BLOCKER)) - return; + wxPaintDC dc(this); + int redraw_type = m_owner->GetRedrawType(); + if (!m_owner || (redraw_type & wxPLOT_REDRAW_BLOCKER)) { + return; + } - if (IsXAxis() && ((redraw_type & wxPLOT_REDRAW_XAXIS) != 0)) - { - m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_XAXIS); - CreateBitmap(); - } - else if (!IsXAxis() && ((redraw_type & wxPLOT_REDRAW_YAXIS) != 0)) - { - m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_YAXIS); - CreateBitmap(); - } + if (IsXAxis() && ((redraw_type & wxPLOT_REDRAW_XAXIS) != 0)) { + m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_XAXIS); + CreateBitmap(); + } + else if (!IsXAxis() && ((redraw_type & wxPLOT_REDRAW_YAXIS) != 0)) { + m_owner->SetRedrawType(redraw_type & ~wxPLOT_REDRAW_YAXIS); + CreateBitmap(); + } - if (m_bitmap.Ok()) - dc.DrawBitmap(m_bitmap, 0, 0, false); + if (m_bitmap.Ok()) { + dc.DrawBitmap(m_bitmap, 0, 0, false); + } } void wxPlotAxis::CreateBitmap() { - if (!m_owner) - return; + if (!m_owner) { + return; + } - m_owner->UpdateWindowSize(); - wxSize clientSize = GetClientSize(); - if ((clientSize.x < 2) || (clientSize.y < 2)) return; + m_owner->UpdateWindowSize(); + wxSize clientSize = GetClientSize(); + if ((clientSize.x < 2) || (clientSize.y < 2)) { + return; + } - if (!m_bitmap.Ok() || (clientSize.x != m_bitmap.GetWidth()) || - (clientSize.y != m_bitmap.GetHeight()) ) - { - m_bitmap.Create(clientSize.x, clientSize.y); - } + if (!m_bitmap.Ok() || (clientSize.x != m_bitmap.GetWidth()) || + (clientSize.y != m_bitmap.GetHeight())) { + m_bitmap.Create(clientSize.x, clientSize.y); + } - wxMemoryDC mdc; - mdc.SelectObject( m_bitmap ); - if (IsXAxis()) - m_owner->DrawXAxis( &mdc, true ); - else - m_owner->DrawYAxis( &mdc, true ); + wxMemoryDC mdc; + mdc.SelectObject(m_bitmap); + if (IsXAxis()) { + m_owner->DrawXAxis(&mdc, true); + } + else { + m_owner->DrawYAxis(&mdc, true); + } - mdc.SelectObject( wxNullBitmap ); + mdc.SelectObject(wxNullBitmap); } //----------------------------------------------------------------------------- // wxPlotCtrl //----------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS(wxPlotCtrl, wxWindow ) - -BEGIN_EVENT_TABLE(wxPlotCtrl, wxWindow ) - //EVT_ERASE_BACKGROUND ( wxPlotCtrl::OnEraseBackground ) // clear for MSW - EVT_SIZE ( wxPlotCtrl::OnSize ) - EVT_PAINT ( wxPlotCtrl::OnPaint ) - EVT_CHAR ( wxPlotCtrl::OnChar ) - EVT_SCROLL ( wxPlotCtrl::OnScroll ) - EVT_IDLE ( wxPlotCtrl::OnIdle ) - EVT_MOUSE_EVENTS ( wxPlotCtrl::OnMouse ) - EVT_TIMER ( wxID_ANY, wxPlotCtrl::OnTimer ) - - EVT_TEXT_ENTER ( wxID_ANY, wxPlotCtrl::OnTextEnter) +IMPLEMENT_ABSTRACT_CLASS(wxPlotCtrl, wxWindow) + +BEGIN_EVENT_TABLE(wxPlotCtrl, wxWindow) +// EVT_ERASE_BACKGROUND ( wxPlotCtrl::OnEraseBackground ) // clear for MSW +EVT_SIZE(wxPlotCtrl::OnSize) +EVT_PAINT(wxPlotCtrl::OnPaint) +EVT_CHAR(wxPlotCtrl::OnChar) +EVT_SCROLL(wxPlotCtrl::OnScroll) +EVT_IDLE(wxPlotCtrl::OnIdle) +EVT_MOUSE_EVENTS(wxPlotCtrl::OnMouse) +EVT_TIMER(wxID_ANY, wxPlotCtrl::OnTimer) + +EVT_TEXT_ENTER(wxID_ANY, wxPlotCtrl::OnTextEnter) END_EVENT_TABLE() void wxPlotCtrl::Init() { - m_activeCurve = NULL; - m_active_index = -1; + m_activeCurve = NULL; + m_active_index = -1; - m_cursorMarker.CreateEllipseMarker(wxPoint2DDouble(0,0), - wxSize(2, 2), - wxGenericPen(wxGenericColour(0, 255, 0))); - m_cursor_curve = -1; - m_cursor_index = -1; + m_cursorMarker.CreateEllipseMarker(wxPoint2DDouble(0, 0), wxSize(2, 2), + wxGenericPen(wxGenericColour(0, 255, 0))); + m_cursor_curve = -1; + m_cursor_index = -1; - m_selection_type = wxPLOT_SELECT_MULTIPLE; + m_selection_type = wxPLOT_SELECT_MULTIPLE; - m_show_key = true; + m_show_key = true; - m_show_title = m_show_xlabel = m_show_ylabel = false; - m_title = wxT("Title"); - m_xLabel = wxT("X-Axis"); - m_yLabel = wxT("Y-Axis"); + m_show_title = m_show_xlabel = m_show_ylabel = false; + m_title = wxT("Title"); + m_xLabel = wxT("X-Axis"); + m_yLabel = wxT("Y-Axis"); - m_titleFont = *wxSWISS_FONT; - m_titleColour = *wxBLACK; - m_borderColour = *wxBLACK; + m_titleFont = *wxSWISS_FONT; + m_titleColour = *wxBLACK; + m_borderColour = *wxBLACK; - m_scroll_on_thumb_release = false; - m_crosshair_cursor = false; - m_draw_symbols = true; - m_draw_lines = true; - m_draw_spline = false; - m_draw_grid = true; - m_fit_on_new_curve = true; - m_show_xAxis = true; - m_show_yAxis = true; + m_scroll_on_thumb_release = false; + m_crosshair_cursor = false; + m_draw_symbols = true; + m_draw_lines = true; + m_draw_spline = false; + m_draw_grid = true; + m_fit_on_new_curve = true; + m_show_xAxis = true; + m_show_yAxis = true; - m_zoom = wxPoint2DDouble( 1.0, 1.0 ); - m_history_views_index = -1; + m_zoom = wxPoint2DDouble(1.0, 1.0); + m_history_views_index = -1; - m_fix_aspectratio = false; - m_aspectratio = 1.0; + m_fix_aspectratio = false; + m_aspectratio = 1.0; - m_viewRect = m_defaultPlotRect; - m_curveBoundingRect = m_defaultPlotRect; - m_defaultPlotRect = wxRect2DDouble( -10.0, -10.0, 20.0, 20.0 ); - m_areaClientRect = wxRect(0, 0, 10, 10); - - m_xAxisTickFormat = m_yAxisTickFormat = wxT("%lf"); - m_xAxisTick_step = m_yAxisTick_step = 1.0; - m_xAxisTick_count = m_yAxisTick_count = 4; - m_correct_ticks = true; - - m_areaDrawer = NULL; - m_xAxisDrawer = NULL; - m_yAxisDrawer = NULL; - m_keyDrawer = NULL; - m_curveDrawer = NULL; - m_dataCurveDrawer = NULL; - m_markerDrawer = NULL; - - m_xAxis = NULL; - m_yAxis = NULL; - m_area = NULL; - m_xAxisScrollbar = NULL; - m_yAxisScrollbar = NULL; - m_textCtrl = NULL; - - m_activeBitmap = new wxBitmap(ledgreen_xpm); - m_inactiveBitmap = new wxBitmap(ledgrey_xpm); - m_focused = false; - m_greedy_focus = false; - - m_redraw_type = wxPLOT_REDRAW_BLOCKER; - m_batch_count = 0; - - m_axisFontSize.x = 6; - m_axisFontSize.y = 12; - m_y_axis_text_width = 60; - m_area_border_width = 1; - m_border = 4; - m_min_exponential = 1000; - m_pen_print_width = 0.4; - - m_timer = NULL; - m_winCapture = NULL; - - m_area_mouse_marker = wxPLOT_MARKER_RECT; - m_area_mouse_func = wxPLOT_MOUSE_ZOOM; - m_area_mouse_cursorid = wxCURSOR_CROSS; - - m_mouse_cursorid = wxCURSOR_ARROW; -} - -bool wxPlotCtrl::Create( wxWindow *parent, wxWindowID win_id, - const wxPoint &pos, const wxSize &size, - wxPlotAxis_Type WXUNUSED(flag), - const wxString &name ) -{ - m_redraw_type = wxPLOT_REDRAW_BLOCKER; // no paints until finished - - if (!wxWindow::Create(parent, win_id, pos, size, - wxWANTS_CHARS|wxCLIP_CHILDREN, name)) - return false; + m_viewRect = m_defaultPlotRect; + m_curveBoundingRect = m_defaultPlotRect; + m_defaultPlotRect = wxRect2DDouble(-10.0, -10.0, 20.0, 20.0); + m_areaClientRect = wxRect(0, 0, 10, 10); - //SetSizeHints( 100, 100 ); // Don't allow window to get smaller than this! + m_xAxisTickFormat = m_yAxisTickFormat = wxT("%lf"); + m_xAxisTick_step = m_yAxisTick_step = 1.0; + m_xAxisTick_count = m_yAxisTick_count = 4; + m_correct_ticks = true; - if (!s_handCursor.Ok()) - { - wxImage image(wxBitmap(hand_xpm).ConvertToImage()); - image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, image.GetWidth()/2); - image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, image.GetHeight()/2); - s_handCursor = wxCursor(image); - } - if (!s_grabCursor.Ok()) - { - wxImage image(wxBitmap(grab_xpm).ConvertToImage()); - image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, image.GetWidth()/2); - image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, image.GetHeight()/2); - s_grabCursor = wxCursor(image); - } - - m_areaDrawer = new wxPlotDrawerArea(this); - m_xAxisDrawer = new wxPlotDrawerXAxis(this); - m_yAxisDrawer = new wxPlotDrawerYAxis(this); - m_keyDrawer = new wxPlotDrawerKey(this); - m_curveDrawer = new wxPlotDrawerCurve(this); - m_dataCurveDrawer = new wxPlotDrawerDataCurve(this); - m_markerDrawer = new wxPlotDrawerMarker(this); - - m_xAxis = new wxPlotAxis( this, ID_PLOTCTRL_X_AXIS, wxPLOT_X_AXIS ); - m_yAxis = new wxPlotAxis( this, ID_PLOTCTRL_Y_AXIS, wxPLOT_Y_AXIS ); - m_area = new wxPlotArea( this, ID_PLOTCTRL_AREA ); - m_xAxisScrollbar = new wxScrollBar(this, ID_PLOTCTRL_X_SCROLLBAR, - wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL); - m_yAxisScrollbar = new wxScrollBar(this, ID_PLOTCTRL_Y_SCROLLBAR, - wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL); - - wxFont axisFont(m_xAxis->GetFont()); - GetTextExtent(wxT("5"), &m_axisFontSize.x, &m_axisFontSize.y, NULL, NULL, &axisFont); - if ((m_axisFontSize.x < 2) || (m_axisFontSize.y < 2)) // don't want to divide by 0 - { - m_axisFontSize.x = 6; - m_axisFontSize.y = 12; - wxFAIL_MSG(wxT("Can't determine the font size for the axis! I'll guess.\n" - "Thef display might be corrupted, however you may continue.")); - } + m_areaDrawer = NULL; + m_xAxisDrawer = NULL; + m_yAxisDrawer = NULL; + m_keyDrawer = NULL; + m_curveDrawer = NULL; + m_dataCurveDrawer = NULL; + m_markerDrawer = NULL; + + m_xAxis = NULL; + m_yAxis = NULL; + m_area = NULL; + m_xAxisScrollbar = NULL; + m_yAxisScrollbar = NULL; + m_textCtrl = NULL; + + m_activeBitmap = new wxBitmap(ledgreen_xpm); + m_inactiveBitmap = new wxBitmap(ledgrey_xpm); + m_focused = false; + m_greedy_focus = false; + + m_redraw_type = wxPLOT_REDRAW_BLOCKER; + m_batch_count = 0; - m_xAxisDrawer->SetTickFont(axisFont); - m_yAxisDrawer->SetTickFont(axisFont); -// m_xAxisDrawer->SetLabelFont(*wxSWISS_FONT); // needs to be rotated -// m_yAxisDrawer->SetLabelFont(*wxSWISS_FONT); // swiss works + m_axisFontSize.x = 6; + m_axisFontSize.y = 12; + m_y_axis_text_width = 60; + m_area_border_width = 1; + m_border = 4; + m_min_exponential = 1000; + m_pen_print_width = 0.4; - m_area->SetCursor( wxCURSOR_CROSS ); - m_area->SetBackgroundColour(*wxWHITE); - m_xAxis->SetBackgroundColour(*wxWHITE); - m_yAxis->SetBackgroundColour(*wxWHITE); - wxWindow::SetBackgroundColour(*wxWHITE); + m_timer = NULL; + m_winCapture = NULL; - m_area->SetForegroundColour(*wxLIGHT_GREY); + m_area_mouse_marker = wxPLOT_MARKER_RECT; + m_area_mouse_func = wxPLOT_MOUSE_ZOOM; + m_area_mouse_cursorid = wxCURSOR_CROSS; - m_redraw_type = 0; // redraw when all done - Redraw(wxPLOT_REDRAW_WHOLEPLOT); + m_mouse_cursorid = wxCURSOR_ARROW; +} + +bool wxPlotCtrl::Create(wxWindow *parent, wxWindowID win_id, const wxPoint &pos, + const wxSize &size, wxPlotAxis_Type WXUNUSED(flag), const wxString &name) +{ + m_redraw_type = wxPLOT_REDRAW_BLOCKER; // no paints until finished - return true; + if (!wxWindow::Create(parent, win_id, pos, size, wxWANTS_CHARS | wxCLIP_CHILDREN, name)) { + return false; + } + + // SetSizeHints( 100, 100 ); // Don't allow window to get smaller than this! + + if (!s_handCursor.Ok()) { + wxImage image(wxBitmap(hand_xpm).ConvertToImage()); + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, image.GetWidth() / 2); + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, image.GetHeight() / 2); + s_handCursor = wxCursor(image); + } + if (!s_grabCursor.Ok()) { + wxImage image(wxBitmap(grab_xpm).ConvertToImage()); + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, image.GetWidth() / 2); + image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, image.GetHeight() / 2); + s_grabCursor = wxCursor(image); + } + + m_areaDrawer = new wxPlotDrawerArea(this); + m_xAxisDrawer = new wxPlotDrawerXAxis(this); + m_yAxisDrawer = new wxPlotDrawerYAxis(this); + m_keyDrawer = new wxPlotDrawerKey(this); + m_curveDrawer = new wxPlotDrawerCurve(this); + m_dataCurveDrawer = new wxPlotDrawerDataCurve(this); + m_markerDrawer = new wxPlotDrawerMarker(this); + + m_xAxis = new wxPlotAxis(this, ID_PLOTCTRL_X_AXIS, wxPLOT_X_AXIS); + m_yAxis = new wxPlotAxis(this, ID_PLOTCTRL_Y_AXIS, wxPLOT_Y_AXIS); + m_area = new wxPlotArea(this, ID_PLOTCTRL_AREA); + m_xAxisScrollbar = new wxScrollBar(this, ID_PLOTCTRL_X_SCROLLBAR, wxDefaultPosition, + wxDefaultSize, wxSB_HORIZONTAL); + m_yAxisScrollbar = new wxScrollBar(this, ID_PLOTCTRL_Y_SCROLLBAR, wxDefaultPosition, + wxDefaultSize, wxSB_VERTICAL); + + wxFont axisFont(m_xAxis->GetFont()); + GetTextExtent(wxT("5"), &m_axisFontSize.x, &m_axisFontSize.y, NULL, NULL, &axisFont); + if ((m_axisFontSize.x < 2) || (m_axisFontSize.y < 2)) // don't want to divide by 0 + { + m_axisFontSize.x = 6; + m_axisFontSize.y = 12; + wxFAIL_MSG(wxT("Can't determine the font size for the axis! I'll guess.\n" + "Thef display might be corrupted, however you may continue.")); + } + + m_xAxisDrawer->SetTickFont(axisFont); + m_yAxisDrawer->SetTickFont(axisFont); + // m_xAxisDrawer->SetLabelFont(*wxSWISS_FONT); // needs to be rotated + // m_yAxisDrawer->SetLabelFont(*wxSWISS_FONT); // swiss works + + m_area->SetCursor(wxCURSOR_CROSS); + m_area->SetBackgroundColour(*wxWHITE); + m_xAxis->SetBackgroundColour(*wxWHITE); + m_yAxis->SetBackgroundColour(*wxWHITE); + wxWindow::SetBackgroundColour(*wxWHITE); + + m_area->SetForegroundColour(*wxLIGHT_GREY); + + m_redraw_type = 0; // redraw when all done + Redraw(wxPLOT_REDRAW_WHOLEPLOT); + + return true; } wxPlotCtrl::~wxPlotCtrl() { - delete m_activeBitmap; - delete m_inactiveBitmap; + delete m_activeBitmap; + delete m_inactiveBitmap; - delete m_areaDrawer; - delete m_xAxisDrawer; - delete m_yAxisDrawer; - delete m_keyDrawer; - delete m_curveDrawer; - delete m_dataCurveDrawer; - delete m_markerDrawer; + delete m_areaDrawer; + delete m_xAxisDrawer; + delete m_yAxisDrawer; + delete m_keyDrawer; + delete m_curveDrawer; + delete m_dataCurveDrawer; + delete m_markerDrawer; } -void wxPlotCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) ) +void wxPlotCtrl::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc(this); + wxPaintDC dc(this); - DrawActiveBitmap(&dc); - DrawPlotCtrl(&dc); + DrawActiveBitmap(&dc); + DrawPlotCtrl(&dc); } -void wxPlotCtrl::DrawActiveBitmap( wxDC* dc ) +void wxPlotCtrl::DrawActiveBitmap(wxDC *dc) { - if (m_xAxisScrollbar && m_yAxisScrollbar) - { - wxSize size = GetClientSize(); - int left = m_xAxisScrollbar->GetRect().GetRight(); - int top = m_yAxisScrollbar->GetRect().GetBottom(); - wxRect rect(left, top, size.x - left, size.y - top); - // clear background - dc->SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); - dc->SetPen(*wxTRANSPARENT_PEN); - dc->DrawRectangle(rect); - // center the bitmap - wxPoint pt(rect.x + (rect.width - 15)/2, rect.y + (rect.width - 15)/2); - dc->DrawBitmap(m_focused ? *m_activeBitmap : *m_inactiveBitmap, - pt.x, pt.y, true); - } + if (m_xAxisScrollbar && m_yAxisScrollbar) { + wxSize size = GetClientSize(); + int left = m_xAxisScrollbar->GetRect().GetRight(); + int top = m_yAxisScrollbar->GetRect().GetBottom(); + wxRect rect(left, top, size.x - left, size.y - top); + // clear background + dc->SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); + dc->SetPen(*wxTRANSPARENT_PEN); + dc->DrawRectangle(rect); + // center the bitmap + wxPoint pt(rect.x + (rect.width - 15) / 2, rect.y + (rect.width - 15) / 2); + dc->DrawBitmap(m_focused ? *m_activeBitmap : *m_inactiveBitmap, pt.x, pt.y, true); + } } -void wxPlotCtrl::DrawPlotCtrl( wxDC *dc ) +void wxPlotCtrl::DrawPlotCtrl(wxDC *dc) { - wxCHECK_RET(dc, wxT("invalid window")); + wxCHECK_RET(dc, wxT("invalid window")); - if (m_show_title && !m_title.IsEmpty()) - { - dc->SetFont(GetPlotTitleFont()); - dc->SetTextForeground(GetPlotTitleColour()); - dc->DrawText(m_title, m_titleRect.x, m_titleRect.y); - } + if (m_show_title && !m_title.IsEmpty()) { + dc->SetFont(GetPlotTitleFont()); + dc->SetTextForeground(GetPlotTitleColour()); + dc->DrawText(m_title, m_titleRect.x, m_titleRect.y); + } - bool draw_xlabel = (m_show_xlabel && !m_xLabel.IsEmpty()); - bool draw_ylabel = (m_show_ylabel && !m_yLabel.IsEmpty()); + bool draw_xlabel = (m_show_xlabel && !m_xLabel.IsEmpty()); + bool draw_ylabel = (m_show_ylabel && !m_yLabel.IsEmpty()); - if (draw_xlabel || draw_ylabel) - { - dc->SetFont(GetAxisLabelFont()); - dc->SetTextForeground(GetAxisLabelColour()); + if (draw_xlabel || draw_ylabel) { + dc->SetFont(GetAxisLabelFont()); + dc->SetTextForeground(GetAxisLabelColour()); - if (draw_xlabel) - dc->DrawText(m_xLabel, m_xLabelRect.x, m_xLabelRect.y); - if (draw_ylabel) - dc->DrawRotatedText(m_yLabel, m_yLabelRect.x, m_yLabelRect.y + m_yLabelRect.height, 90); + if (draw_xlabel) { + dc->DrawText(m_xLabel, m_xLabelRect.x, m_xLabelRect.y); + } + if (draw_ylabel) { + dc->DrawRotatedText(m_yLabel, m_yLabelRect.x, m_yLabelRect.y + m_yLabelRect.height, 90); } + } #ifdef DRAW_BORDERS - // Test code for sizing to show the extent of the axes - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - dc->SetPen( wxPen(GetBorderColour(), 1, wxSOLID) ); - dc->DrawRectangle(m_titleRect); - dc->DrawRectangle(m_xLabelRect); - dc->DrawRectangle(m_yLabelRect); + // Test code for sizing to show the extent of the axes + dc->SetBrush(*wxTRANSPARENT_BRUSH); + dc->SetPen(wxPen(GetBorderColour(), 1, wxSOLID)); + dc->DrawRectangle(m_titleRect); + dc->DrawRectangle(m_xLabelRect); + dc->DrawRectangle(m_yLabelRect); #endif // DRAW_BORDERS } void wxPlotCtrl::SetPlotWinMouseCursor(wxStockCursor cursorid) { - if (cursorid == m_mouse_cursorid) return; - m_mouse_cursorid = cursorid; - SetCursor(wxCursor(cursorid)); + if (cursorid == m_mouse_cursorid) { + return; + } + m_mouse_cursorid = cursorid; + SetCursor(wxCursor(cursorid)); } -void wxPlotCtrl::OnMouse( wxMouseEvent &event ) +void wxPlotCtrl::OnMouse(wxMouseEvent &event) { - if (event.ButtonDown() && IsTextCtrlShown()) - { - HideTextCtrl(true, true); - return; - } + if (event.ButtonDown() && IsTextCtrlShown()) { + HideTextCtrl(true, true); + return; + } - /*wxSize size(*/GetClientSize();/*);*/ - wxPoint mousePt(event.GetPosition()); + /*wxSize size(*/ GetClientSize(); /*);*/ + wxPoint mousePt(event.GetPosition()); -#if wxCHECK_VERSION(2,7,0) - if ((m_show_title && m_titleRect.Contains(mousePt)) || - (m_show_xlabel && m_xLabelRect.Contains(mousePt)) || - (m_show_ylabel && m_yLabelRect.Contains(mousePt))) +#if wxCHECK_VERSION(2, 7, 0) + if ((m_show_title && m_titleRect.Contains(mousePt)) || + (m_show_xlabel && m_xLabelRect.Contains(mousePt)) || + (m_show_ylabel && m_yLabelRect.Contains(mousePt))) #else - if ((m_show_title && m_titleRect.Inside(mousePt)) || - (m_show_xlabel && m_xLabelRect.Inside(mousePt)) || - (m_show_ylabel && m_yLabelRect.Inside(mousePt))) + if ((m_show_title && m_titleRect.Inside(mousePt)) || + (m_show_xlabel && m_xLabelRect.Inside(mousePt)) || + (m_show_ylabel && m_yLabelRect.Inside(mousePt))) #endif - { - SetPlotWinMouseCursor(wxCURSOR_IBEAM); + { + SetPlotWinMouseCursor(wxCURSOR_IBEAM); + } + else { + SetPlotWinMouseCursor(wxCURSOR_ARROW); + } + + if (event.ButtonDClick(1) && !IsTextCtrlShown()) { +#if wxCHECK_VERSION(2, 7, 0) + if (m_show_title && m_titleRect.Contains(mousePt)) { + ShowTextCtrl(wxPLOT_EDIT_TITLE, true); + } + else if (m_show_xlabel && m_xLabelRect.Contains(mousePt)) { + ShowTextCtrl(wxPLOT_EDIT_XAXIS, true); + } + else if (m_show_ylabel && m_yLabelRect.Contains(mousePt)) { + ShowTextCtrl(wxPLOT_EDIT_YAXIS, true); } - else - SetPlotWinMouseCursor(wxCURSOR_ARROW); - - if (event.ButtonDClick(1) && !IsTextCtrlShown()) - { -#if wxCHECK_VERSION(2,7,0) - if (m_show_title && m_titleRect.Contains(mousePt)) - ShowTextCtrl(wxPLOT_EDIT_TITLE, true); - else if (m_show_xlabel && m_xLabelRect.Contains(mousePt)) - ShowTextCtrl(wxPLOT_EDIT_XAXIS, true); - else if (m_show_ylabel && m_yLabelRect.Contains(mousePt)) - ShowTextCtrl(wxPLOT_EDIT_YAXIS, true); #else - if (m_show_title && m_titleRect.Inside(mousePt)) - ShowTextCtrl(wxPLOT_EDIT_TITLE, true); - else if (m_show_xlabel && m_xLabelRect.Inside(mousePt)) - ShowTextCtrl(wxPLOT_EDIT_XAXIS, true); - else if (m_show_ylabel && m_yLabelRect.Inside(mousePt)) - ShowTextCtrl(wxPLOT_EDIT_YAXIS, true); -#endif + if (m_show_title && m_titleRect.Inside(mousePt)) { + ShowTextCtrl(wxPLOT_EDIT_TITLE, true); + } + else if (m_show_xlabel && m_xLabelRect.Inside(mousePt)) { + ShowTextCtrl(wxPLOT_EDIT_XAXIS, true); + } + else if (m_show_ylabel && m_yLabelRect.Inside(mousePt)) { + ShowTextCtrl(wxPLOT_EDIT_YAXIS, true); } +#endif + } } void wxPlotCtrl::ShowTextCtrl(wxPlotCtrlTextCtrl_Type type, bool send_event) { - switch (type) - { - case wxPLOT_EDIT_TITLE : - { - if (m_textCtrl) - { - if (m_textCtrl->GetId() != wxEVT_PLOT_END_TITLE_EDIT) - HideTextCtrl(true, true); - else - return; // already shown - } - - if (send_event) - { - wxPlotEvent pevent(wxEVT_PLOT_BEGIN_TITLE_EDIT, GetId(), this); - pevent.SetString(m_title); - if (!DoSendEvent(pevent)) return; - } - - m_textCtrl = new wxTextCtrl(this, wxEVT_PLOT_END_TITLE_EDIT, GetPlotTitle(), - wxPoint(m_areaRect.x, 0), - wxSize(m_areaRect.width, m_titleRect.height+2*m_border), - wxTE_PROCESS_ENTER); + switch (type) { + case wxPLOT_EDIT_TITLE: { + if (m_textCtrl) { + if (m_textCtrl->GetId() != wxEVT_PLOT_END_TITLE_EDIT) { + HideTextCtrl(true, true); + } + else { + return; // already shown + } + } - m_textCtrl->SetFont(GetPlotTitleFont()); - m_textCtrl->SetForegroundColour(GetPlotTitleColour()); - m_textCtrl->SetBackgroundColour(GetBackgroundColour()); - break; - } - case wxPLOT_EDIT_XAXIS : - { - if (m_textCtrl) - { - if (m_textCtrl->GetId() != wxEVT_PLOT_END_X_LABEL_EDIT) - HideTextCtrl(true, true); - else - return; // already shown - } + if (send_event) { + wxPlotEvent pevent(wxEVT_PLOT_BEGIN_TITLE_EDIT, GetId(), this); + pevent.SetString(m_title); + if (!DoSendEvent(pevent)) { + return; + } + } - if (send_event) - { - wxPlotEvent pevent(wxEVT_PLOT_BEGIN_X_LABEL_EDIT, GetId(), this); - pevent.SetString(m_xLabel); - if (!DoSendEvent(pevent)) return; - } + m_textCtrl = new wxTextCtrl( + this, wxEVT_PLOT_END_TITLE_EDIT, GetPlotTitle(), wxPoint(m_areaRect.x, 0), + wxSize(m_areaRect.width, m_titleRect.height + 2 * m_border), wxTE_PROCESS_ENTER); + + m_textCtrl->SetFont(GetPlotTitleFont()); + m_textCtrl->SetForegroundColour(GetPlotTitleColour()); + m_textCtrl->SetBackgroundColour(GetBackgroundColour()); + break; + } + case wxPLOT_EDIT_XAXIS: { + if (m_textCtrl) { + if (m_textCtrl->GetId() != wxEVT_PLOT_END_X_LABEL_EDIT) { + HideTextCtrl(true, true); + } + else { + return; // already shown + } + } - m_textCtrl = new wxTextCtrl(this, wxEVT_PLOT_END_X_LABEL_EDIT, GetXAxisLabel(), - wxPoint(m_areaRect.x, m_xAxisRect.GetBottom()), - wxSize(m_areaRect.width, m_xLabelRect.height+2*m_border), - wxTE_PROCESS_ENTER); + if (send_event) { + wxPlotEvent pevent(wxEVT_PLOT_BEGIN_X_LABEL_EDIT, GetId(), this); + pevent.SetString(m_xLabel); + if (!DoSendEvent(pevent)) { + return; + } + } - m_textCtrl->SetFont(GetAxisLabelFont()); - m_textCtrl->SetForegroundColour(GetAxisLabelColour()); - m_textCtrl->SetBackgroundColour(GetBackgroundColour()); - break; - } - case wxPLOT_EDIT_YAXIS : - { - if (m_textCtrl) - { - if (m_textCtrl->GetId() != wxEVT_PLOT_END_Y_LABEL_EDIT) - HideTextCtrl(true, true); - else - return; // already shown - } + m_textCtrl = new wxTextCtrl(this, wxEVT_PLOT_END_X_LABEL_EDIT, GetXAxisLabel(), + wxPoint(m_areaRect.x, m_xAxisRect.GetBottom()), + wxSize(m_areaRect.width, m_xLabelRect.height + 2 * m_border), + wxTE_PROCESS_ENTER); + + m_textCtrl->SetFont(GetAxisLabelFont()); + m_textCtrl->SetForegroundColour(GetAxisLabelColour()); + m_textCtrl->SetBackgroundColour(GetBackgroundColour()); + break; + } + case wxPLOT_EDIT_YAXIS: { + if (m_textCtrl) { + if (m_textCtrl->GetId() != wxEVT_PLOT_END_Y_LABEL_EDIT) { + HideTextCtrl(true, true); + } + else { + return; // already shown + } + } - if (send_event) - { - wxPlotEvent pevent(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, GetId(), this); - pevent.SetString(m_yLabel); - if (!DoSendEvent(pevent)) return; - } + if (send_event) { + wxPlotEvent pevent(wxEVT_PLOT_BEGIN_Y_LABEL_EDIT, GetId(), this); + pevent.SetString(m_yLabel); + if (!DoSendEvent(pevent)) { + return; + } + } - m_textCtrl = new wxTextCtrl(this, wxEVT_PLOT_END_Y_LABEL_EDIT, GetYAxisLabel(), - wxPoint(0, m_areaRect.y+m_areaRect.height/2), - wxSize(m_clientRect.width - m_axisFontSize.y/2, m_yLabelRect.width+2*m_border), - wxTE_PROCESS_ENTER); + m_textCtrl = new wxTextCtrl( + this, wxEVT_PLOT_END_Y_LABEL_EDIT, GetYAxisLabel(), + wxPoint(0, m_areaRect.y + m_areaRect.height / 2), + wxSize(m_clientRect.width - m_axisFontSize.y / 2, m_yLabelRect.width + 2 * m_border), + wxTE_PROCESS_ENTER); - m_textCtrl->SetFont(GetAxisLabelFont()); - m_textCtrl->SetForegroundColour(GetAxisLabelColour()); - m_textCtrl->SetBackgroundColour(GetBackgroundColour()); - break; - } - } + m_textCtrl->SetFont(GetAxisLabelFont()); + m_textCtrl->SetForegroundColour(GetAxisLabelColour()); + m_textCtrl->SetBackgroundColour(GetBackgroundColour()); + break; + } + } } void wxPlotCtrl::HideTextCtrl(bool save_value, bool send_event) { - wxCHECK_RET(m_textCtrl, wxT("HideTextCtrl, but textctrl is not shown")); + wxCHECK_RET(m_textCtrl, wxT("HideTextCtrl, but textctrl is not shown")); - long event_type = m_textCtrl->GetId(); - wxString value = m_textCtrl->GetValue(); + long event_type = m_textCtrl->GetId(); + wxString value = m_textCtrl->GetValue(); - m_textCtrl->Destroy(); - m_textCtrl = NULL; + m_textCtrl->Destroy(); + m_textCtrl = NULL; - if (!save_value) - return; + if (!save_value) { + return; + } - bool changed = false; + bool changed = false; - if (event_type == wxEVT_PLOT_END_TITLE_EDIT) - changed = (value != GetPlotTitle()); - else if (event_type == wxEVT_PLOT_END_X_LABEL_EDIT) - changed = (value != GetXAxisLabel()); - else if (event_type == wxEVT_PLOT_END_Y_LABEL_EDIT) - changed = (value != GetYAxisLabel()); + if (event_type == wxEVT_PLOT_END_TITLE_EDIT) { + changed = (value != GetPlotTitle()); + } + else if (event_type == wxEVT_PLOT_END_X_LABEL_EDIT) { + changed = (value != GetXAxisLabel()); + } + else if (event_type == wxEVT_PLOT_END_Y_LABEL_EDIT) { + changed = (value != GetYAxisLabel()); + } - if (!changed) - return; + if (!changed) { + return; + } - if (send_event) - { - wxPlotEvent event(event_type, GetId(), this); - event.SetString(value); - if (!DoSendEvent(event)) return; + if (send_event) { + wxPlotEvent event(event_type, GetId(), this); + event.SetString(value); + if (!DoSendEvent(event)) { + return; } + } - if (event_type == wxEVT_PLOT_END_TITLE_EDIT) - SetPlotTitle(value); - else if (event_type == wxEVT_PLOT_END_X_LABEL_EDIT) - SetXAxisLabel(value); - else if (event_type == wxEVT_PLOT_END_Y_LABEL_EDIT) - SetYAxisLabel(value); + if (event_type == wxEVT_PLOT_END_TITLE_EDIT) { + SetPlotTitle(value); + } + else if (event_type == wxEVT_PLOT_END_X_LABEL_EDIT) { + SetXAxisLabel(value); + } + else if (event_type == wxEVT_PLOT_END_Y_LABEL_EDIT) { + SetYAxisLabel(value); + } } -bool wxPlotCtrl::IsTextCtrlShown() const -{ - return m_textCtrl && m_textCtrl->IsShown(); -} +bool wxPlotCtrl::IsTextCtrlShown() const { return m_textCtrl && m_textCtrl->IsShown(); } -void wxPlotCtrl::OnTextEnter( wxCommandEvent &event ) +void wxPlotCtrl::OnTextEnter(wxCommandEvent &event) { - if (event.GetId() == 1) - HideTextCtrl(true, true); - else - { - wxCommandEvent newevt(wxEVT_COMMAND_TEXT_ENTER, 1); - GetEventHandler()->AddPendingEvent( newevt ); - } + if (event.GetId() == 1) { + HideTextCtrl(true, true); + } + else { + wxCommandEvent newevt(wxEVT_COMMAND_TEXT_ENTER, 1); + GetEventHandler()->AddPendingEvent(newevt); + } } -void wxPlotCtrl::OnIdle( wxIdleEvent &event ) +void wxPlotCtrl::OnIdle(wxIdleEvent &event) { - CheckFocus(); - event.Skip(); + CheckFocus(); + event.Skip(); } bool wxPlotCtrl::CheckFocus() { - wxWindow *win = FindFocus(); - if ((win==m_area)||(win==m_xAxis)||(win==m_yAxis)||(win==this)) - { - if (!m_focused) - { - m_focused = true; - wxClientDC dc(this); - wxSize size = GetClientSize(); - dc.DrawBitmap(*m_activeBitmap, size.GetWidth()-15, size.GetHeight()-15,true); - } - } - else if (m_focused) - { - m_focused = false; - wxClientDC dc(this); - wxSize size = GetClientSize(); - dc.DrawBitmap(*m_inactiveBitmap, size.GetWidth()-15, size.GetHeight()-15,true); + wxWindow *win = FindFocus(); + if ((win == m_area) || (win == m_xAxis) || (win == m_yAxis) || (win == this)) { + if (!m_focused) { + m_focused = true; + wxClientDC dc(this); + wxSize size = GetClientSize(); + dc.DrawBitmap(*m_activeBitmap, size.GetWidth() - 15, size.GetHeight() - 15, true); } - return m_focused; + } + else if (m_focused) { + m_focused = false; + wxClientDC dc(this); + wxSize size = GetClientSize(); + dc.DrawBitmap(*m_inactiveBitmap, size.GetWidth() - 15, size.GetHeight() - 15, true); + } + return m_focused; } void wxPlotCtrl::EndBatch(bool force_refresh) { - if ( m_batch_count > 0 ) - { - m_batch_count--; - if ( (m_batch_count <= 0) && force_refresh ) - { - Redraw(wxPLOT_REDRAW_WHOLEPLOT); - AdjustScrollBars(); - } + if (m_batch_count > 0) { + m_batch_count--; + if ((m_batch_count <= 0) && force_refresh) { + Redraw(wxPLOT_REDRAW_WHOLEPLOT); + AdjustScrollBars(); } + } } -bool wxPlotCtrl::SetBackgroundColour( const wxColour &colour ) +bool wxPlotCtrl::SetBackgroundColour(const wxColour &colour) { - wxCHECK_MSG(colour.Ok(), false, wxT("invalid colour")); - m_area->SetBackgroundColour(colour); - m_xAxis->SetBackgroundColour(colour); - m_yAxis->SetBackgroundColour(colour); - wxWindow::SetBackgroundColour(colour); + wxCHECK_MSG(colour.Ok(), false, wxT("invalid colour")); + m_area->SetBackgroundColour(colour); + m_xAxis->SetBackgroundColour(colour); + m_yAxis->SetBackgroundColour(colour); + wxWindow::SetBackgroundColour(colour); - Redraw(wxPLOT_REDRAW_EVERYTHING); - return true; -} -void wxPlotCtrl::SetGridColour( const wxColour &colour ) -{ - wxCHECK_RET(colour.Ok(), wxT("invalid colour")); - m_area->SetForegroundColour(colour); - Redraw(wxPLOT_REDRAW_PLOT); -} -void wxPlotCtrl::SetBorderColour( const wxColour &colour ) -{ - wxCHECK_RET(colour.Ok(), wxT("invalid colour")); - m_borderColour = colour; - Redraw(wxPLOT_REDRAW_PLOT); -} -void wxPlotCtrl::SetCursorColour( const wxColour &colour ) -{ - wxCHECK_RET(colour.Ok(), wxT("invalid colour")); - m_cursorMarker.GetPen().SetColour(colour); - wxClientDC dc(m_area); - DrawCurveCursor( &dc ); + Redraw(wxPLOT_REDRAW_EVERYTHING); + return true; } -wxColour wxPlotCtrl::GetCursorColour() const +void wxPlotCtrl::SetGridColour(const wxColour &colour) { - return m_cursorMarker.GetPen().GetColour(); + wxCHECK_RET(colour.Ok(), wxT("invalid colour")); + m_area->SetForegroundColour(colour); + Redraw(wxPLOT_REDRAW_PLOT); } -int wxPlotCtrl::GetCursorSize() const +void wxPlotCtrl::SetBorderColour(const wxColour &colour) { - return m_cursorMarker.GetSize().x; + wxCHECK_RET(colour.Ok(), wxT("invalid colour")); + m_borderColour = colour; + Redraw(wxPLOT_REDRAW_PLOT); } -void wxPlotCtrl::SetCursorSize(int size) +void wxPlotCtrl::SetCursorColour(const wxColour &colour) { - m_cursorMarker.SetSize(wxSize(size, size)); + wxCHECK_RET(colour.Ok(), wxT("invalid colour")); + m_cursorMarker.GetPen().SetColour(colour); + wxClientDC dc(m_area); + DrawCurveCursor(&dc); } +wxColour wxPlotCtrl::GetCursorColour() const { return m_cursorMarker.GetPen().GetColour(); } +int wxPlotCtrl::GetCursorSize() const { return m_cursorMarker.GetSize().x; } +void wxPlotCtrl::SetCursorSize(int size) { m_cursorMarker.SetSize(wxSize(size, size)); } wxFont wxPlotCtrl::GetAxisFont() const { - return m_xAxisDrawer->m_tickFont; // FIXME + return m_xAxisDrawer->m_tickFont; // FIXME } wxColour wxPlotCtrl::GetAxisColour() const { - return m_xAxisDrawer->m_tickColour.GetColour(); // FIXME + return m_xAxisDrawer->m_tickColour.GetColour(); // FIXME } -void wxPlotCtrl::SetAxisFont( const wxFont &font ) +void wxPlotCtrl::SetAxisFont(const wxFont &font) { - wxCHECK_RET(font.Ok(), wxT("invalid font")); + wxCHECK_RET(font.Ok(), wxT("invalid font")); - if (m_xAxisDrawer) m_xAxisDrawer->SetTickFont(font); - if (m_yAxisDrawer) m_yAxisDrawer->SetTickFont(font); + if (m_xAxisDrawer) { + m_xAxisDrawer->SetTickFont(font); + } + if (m_yAxisDrawer) { + m_yAxisDrawer->SetTickFont(font); + } - int x=6, y=12, decent=0, leading=0; + int x = 6, y = 12, decent = 0, leading = 0; - GetTextExtent(wxT("5"), &x, &y, &decent, &leading, &font); - m_axisFontSize.x = x+leading; - m_axisFontSize.y = y+decent; + GetTextExtent(wxT("5"), &x, &y, &decent, &leading, &font); + m_axisFontSize.x = x + leading; + m_axisFontSize.y = y + decent; - GetTextExtent(wxT("-5.5e+555"), &x, &y, &decent, &leading, &font); - m_y_axis_text_width = x + leading; + GetTextExtent(wxT("-5.5e+555"), &x, &y, &decent, &leading, &font); + m_y_axis_text_width = x + leading; - //m_axisFontSize.x = m_xAxis->GetCharWidth(); - //m_axisFontSize.y = m_xAxis->GetCharHeight(); - if ((m_axisFontSize.x < 2) || (m_axisFontSize.y < 2)) // don't want to divide by 0 - { - static bool first_try = false; + // m_axisFontSize.x = m_xAxis->GetCharWidth(); + // m_axisFontSize.y = m_xAxis->GetCharHeight(); + if ((m_axisFontSize.x < 2) || (m_axisFontSize.y < 2)) // don't want to divide by 0 + { + static bool first_try = false; - m_axisFontSize.x = 6; - m_axisFontSize.y = 12; - wxMessageBox(wxT("Can't determine the font size for the axis.\n") + m_axisFontSize.x = 6; + m_axisFontSize.y = 12; + wxMessageBox(wxT("Can't determine the font size for the axis.\n") wxT("Reverting to a default font."), - wxT("Font error")); + wxT("Font error")); - if (!first_try) - { - first_try = true; - SetAxisFont(*wxNORMAL_FONT); - } - else - first_try = false; + if (!first_try) { + first_try = true; + SetAxisFont(*wxNORMAL_FONT); } + else { + first_try = false; + } + } - DoSize(); - Redraw(wxPLOT_REDRAW_XAXIS|wxPLOT_REDRAW_YAXIS); + DoSize(); + Redraw(wxPLOT_REDRAW_XAXIS | wxPLOT_REDRAW_YAXIS); } -void wxPlotCtrl::SetAxisColour( const wxColour &colour ) +void wxPlotCtrl::SetAxisColour(const wxColour &colour) { - wxCHECK_RET(colour.Ok(), wxT("invalid colour")); - if (m_xAxisDrawer) m_xAxisDrawer->SetTickColour(colour); - if (m_yAxisDrawer) m_yAxisDrawer->SetTickColour(colour); - Redraw(wxPLOT_REDRAW_XAXIS|wxPLOT_REDRAW_YAXIS); + wxCHECK_RET(colour.Ok(), wxT("invalid colour")); + if (m_xAxisDrawer) { + m_xAxisDrawer->SetTickColour(colour); + } + if (m_yAxisDrawer) { + m_yAxisDrawer->SetTickColour(colour); + } + Redraw(wxPLOT_REDRAW_XAXIS | wxPLOT_REDRAW_YAXIS); } wxFont wxPlotCtrl::GetAxisLabelFont() const { - return m_xAxisDrawer->m_labelFont; // FIXME + return m_xAxisDrawer->m_labelFont; // FIXME } wxColour wxPlotCtrl::GetAxisLabelColour() const { - return m_xAxisDrawer->m_labelColour.GetColour(); // FIXME + return m_xAxisDrawer->m_labelColour.GetColour(); // FIXME } -void wxPlotCtrl::SetAxisLabelFont( const wxFont &font ) +void wxPlotCtrl::SetAxisLabelFont(const wxFont &font) { - wxCHECK_RET(font.Ok(), wxT("invalid font")); - if (m_xAxisDrawer) m_xAxisDrawer->SetLabelFont(font); - if (m_yAxisDrawer) m_yAxisDrawer->SetLabelFont(font); - SetXAxisLabel(GetXAxisLabel()); // FIXME - lazy hack - SetYAxisLabel(GetYAxisLabel()); + wxCHECK_RET(font.Ok(), wxT("invalid font")); + if (m_xAxisDrawer) { + m_xAxisDrawer->SetLabelFont(font); + } + if (m_yAxisDrawer) { + m_yAxisDrawer->SetLabelFont(font); + } + SetXAxisLabel(GetXAxisLabel()); // FIXME - lazy hack + SetYAxisLabel(GetYAxisLabel()); } -void wxPlotCtrl::SetAxisLabelColour( const wxColour &colour ) +void wxPlotCtrl::SetAxisLabelColour(const wxColour &colour) { - wxCHECK_RET(colour.Ok(), wxT("invalid colour")); - if (m_xAxisDrawer) m_xAxisDrawer->SetLabelColour(colour); - if (m_yAxisDrawer) m_yAxisDrawer->SetLabelColour(colour); - SetXAxisLabel(GetXAxisLabel()); // FIXME - lazy hack - SetYAxisLabel(GetYAxisLabel()); + wxCHECK_RET(colour.Ok(), wxT("invalid colour")); + if (m_xAxisDrawer) { + m_xAxisDrawer->SetLabelColour(colour); + } + if (m_yAxisDrawer) { + m_yAxisDrawer->SetLabelColour(colour); + } + SetXAxisLabel(GetXAxisLabel()); // FIXME - lazy hack + SetYAxisLabel(GetYAxisLabel()); } void wxPlotCtrl::SetPlotTitleFont(const wxFont &font) { - wxCHECK_RET(font.Ok(), wxT("invalid font")); - m_titleFont = font; - SetPlotTitle(GetPlotTitle()); + wxCHECK_RET(font.Ok(), wxT("invalid font")); + m_titleFont = font; + SetPlotTitle(GetPlotTitle()); } void wxPlotCtrl::SetPlotTitleColour(const wxColour &colour) { - wxCHECK_RET(colour.Ok(), wxT("invalid colour")); - m_titleColour = colour; - SetPlotTitle(GetPlotTitle()); + wxCHECK_RET(colour.Ok(), wxT("invalid colour")); + m_titleColour = colour; + SetPlotTitle(GetPlotTitle()); } wxFont wxPlotCtrl::GetKeyFont() const { - return m_keyDrawer->m_font; // FIXME + return m_keyDrawer->m_font; // FIXME } wxColour wxPlotCtrl::GetKeyColour() const { - return m_keyDrawer->m_fontColour.GetColour(); // FIXME + return m_keyDrawer->m_fontColour.GetColour(); // FIXME } -void wxPlotCtrl::SetKeyFont( const wxFont &font ) +void wxPlotCtrl::SetKeyFont(const wxFont &font) { - wxCHECK_RET(font.Ok(), wxT("invalid font")); - m_keyDrawer->SetFont(font); - Redraw(wxPLOT_REDRAW_PLOT); + wxCHECK_RET(font.Ok(), wxT("invalid font")); + m_keyDrawer->SetFont(font); + Redraw(wxPLOT_REDRAW_PLOT); } -void wxPlotCtrl::SetKeyColour( const wxColour & colour ) +void wxPlotCtrl::SetKeyColour(const wxColour &colour) { - wxCHECK_RET(colour.Ok(), wxT("invalid colour")); - m_keyDrawer->SetFontColour(colour); - Redraw(wxPLOT_REDRAW_PLOT); + wxCHECK_RET(colour.Ok(), wxT("invalid colour")); + m_keyDrawer->SetFontColour(colour); + Redraw(wxPLOT_REDRAW_PLOT); } // ------------------------------------------------------------------------ @@ -1231,305 +1258,307 @@ void wxPlotCtrl::SetKeyColour( const wxColour & colour ) void wxPlotCtrl::SetXAxisLabel(const wxString &label) { - if (label.IsEmpty()) - m_xLabel = wxT("X - Axis"); - else - m_xLabel = label; + if (label.IsEmpty()) { + m_xLabel = wxT("X - Axis"); + } + else { + m_xLabel = label; + } - wxFont font = GetAxisLabelFont(); - GetTextExtent(m_xLabel, &m_xLabelRect.width, &m_xLabelRect.height, NULL, NULL, &font); + wxFont font = GetAxisLabelFont(); + GetTextExtent(m_xLabel, &m_xLabelRect.width, &m_xLabelRect.height, NULL, NULL, &font); - m_xLabel = label; - Refresh(); - DoSize(); + m_xLabel = label; + Refresh(); + DoSize(); } void wxPlotCtrl::SetYAxisLabel(const wxString &label) { - if (label.IsEmpty()) - m_yLabel = wxT("Y - Axis"); - else - m_yLabel = label; + if (label.IsEmpty()) { + m_yLabel = wxT("Y - Axis"); + } + else { + m_yLabel = label; + } - wxFont font = GetAxisLabelFont(); - GetTextExtent(m_yLabel, &m_yLabelRect.height, &m_yLabelRect.width, NULL, NULL, &font); + wxFont font = GetAxisLabelFont(); + GetTextExtent(m_yLabel, &m_yLabelRect.height, &m_yLabelRect.width, NULL, NULL, &font); - m_yLabel = label; + m_yLabel = label; - Refresh(); - DoSize(); + Refresh(); + DoSize(); } void wxPlotCtrl::SetPlotTitle(const wxString &title) { - if (title.IsEmpty()) - m_title = wxT("Title"); - else - m_title = title; + if (title.IsEmpty()) { + m_title = wxT("Title"); + } + else { + m_title = title; + } - wxFont font = GetPlotTitleFont(); - GetTextExtent(m_title, &m_titleRect.width, &m_titleRect.height, NULL, NULL, &font); + wxFont font = GetPlotTitleFont(); + GetTextExtent(m_title, &m_titleRect.width, &m_titleRect.height, NULL, NULL, &font); - m_title = title; + m_title = title; - Refresh(); - DoSize(); + Refresh(); + DoSize(); } -wxPoint wxPlotCtrl::GetKeyPosition() const -{ - return m_keyDrawer->m_keyPosition; -} -bool wxPlotCtrl::GetKeyInside() const -{ - return m_keyDrawer->m_key_inside; -} +wxPoint wxPlotCtrl::GetKeyPosition() const { return m_keyDrawer->m_keyPosition; } +bool wxPlotCtrl::GetKeyInside() const { return m_keyDrawer->m_key_inside; } void wxPlotCtrl::SetKeyPosition(const wxPoint &pos, bool stay_inside) { - m_keyDrawer->m_keyPosition = pos; - m_keyDrawer->m_key_inside = stay_inside; - Redraw(wxPLOT_REDRAW_PLOT); + m_keyDrawer->m_keyPosition = pos; + m_keyDrawer->m_key_inside = stay_inside; + Redraw(wxPLOT_REDRAW_PLOT); } void wxPlotCtrl::CreateKeyString() { - m_keyString.Clear(); - int n, count = m_curves.GetCount(); - for (n = 0; n < count; n++) - { - wxString key; - if (GetDataCurve(n)) - key = GetDataCurve(n)->GetFilename(); - else if (GetFunctionCurve(n)) - key = GetFunctionCurve(n)->GetFunctionString(); - else - key.Printf(wxT("Curve %d"), n); - - m_keyString += (key + wxT("\n")); + m_keyString.Clear(); + int n, count = m_curves.GetCount(); + for (n = 0; n < count; n++) { + wxString key; + if (GetDataCurve(n)) { + key = GetDataCurve(n)->GetFilename(); + } + else if (GetFunctionCurve(n)) { + key = GetFunctionCurve(n)->GetFunctionString(); + } + else { + key.Printf(wxT("Curve %d"), n); } + + m_keyString += (key + wxT("\n")); + } } // ------------------------------------------------------------------------ // Curve Accessors // ------------------------------------------------------------------------ -bool wxPlotCtrl::AddCurve( wxPlotCurve *curve, bool select, bool send_event ) +bool wxPlotCtrl::AddCurve(wxPlotCurve *curve, bool select, bool send_event) { - if (!curve || !curve->Ok()) - { - if (curve) delete curve; - wxCHECK_MSG( false, false, wxT("Invalid curve") ); - } - - m_curves.Add( curve ); - m_curveSelections.Add(new wxRangeDoubleSelection()); - m_dataSelections.Add(new wxRangeIntSelection()); - - CalcBoundingPlotRect(); - CreateKeyString(); - - if (send_event) - { - wxPlotEvent event(wxEVT_PLOT_ADD_CURVE, GetId(), this); - event.SetCurve(curve, m_curves.GetCount()-1); - (void)DoSendEvent( event ); + if (!curve || !curve->Ok()) { + if (curve) { + delete curve; } + wxCHECK_MSG(false, false, wxT("Invalid curve")); + } + + m_curves.Add(curve); + m_curveSelections.Add(new wxRangeDoubleSelection()); + m_dataSelections.Add(new wxRangeIntSelection()); + + CalcBoundingPlotRect(); + CreateKeyString(); + + if (send_event) { + wxPlotEvent event(wxEVT_PLOT_ADD_CURVE, GetId(), this); + event.SetCurve(curve, m_curves.GetCount() - 1); + (void)DoSendEvent(event); + } + + m_batch_count++; + if (select) { + SetActiveCurve(curve, send_event); + } + m_batch_count--; + + if (m_fit_on_new_curve) { + SetZoom(-1, -1, 0, 0, true); + } + else { + Redraw(wxPLOT_REDRAW_PLOT); + } - m_batch_count++; - if (select) SetActiveCurve(curve, send_event); - m_batch_count--; - - if (m_fit_on_new_curve) - SetZoom( -1, -1, 0, 0, true ); - else - Redraw(wxPLOT_REDRAW_PLOT); - - return true; + return true; } -bool wxPlotCtrl::AddCurve( const wxPlotCurve &curve, bool select, bool send_event ) +bool wxPlotCtrl::AddCurve(const wxPlotCurve &curve, bool select, bool send_event) { - wxCHECK_MSG(curve.Ok(), false, wxT("invalid wxPlotCurve")); + wxCHECK_MSG(curve.Ok(), false, wxT("invalid wxPlotCurve")); - if (wxDynamicCast(&curve, wxPlotData)) - return AddCurve(new wxPlotData(*wxDynamicCast(&curve, wxPlotData)), select, send_event); - if (wxDynamicCast(&curve, wxPlotFunction)) - return AddCurve(new wxPlotFunction(*wxDynamicCast(&curve, wxPlotFunction)), select, send_event); + if (wxDynamicCast(&curve, wxPlotData)) { + return AddCurve(new wxPlotData(*wxDynamicCast(&curve, wxPlotData)), select, send_event); + } + if (wxDynamicCast(&curve, wxPlotFunction)) { + return AddCurve(new wxPlotFunction(*wxDynamicCast(&curve, wxPlotFunction)), select, + send_event); + } - wxFAIL_MSG(wxT("Unable to ref curve type added to plot")); - return false; + wxFAIL_MSG(wxT("Unable to ref curve type added to plot")); + return false; } -bool wxPlotCtrl::DeleteCurve( wxPlotCurve* curve, bool send_event ) +bool wxPlotCtrl::DeleteCurve(wxPlotCurve *curve, bool send_event) { - wxCHECK_MSG(curve, false, wxT("invalid plotcurve")); + wxCHECK_MSG(curve, false, wxT("invalid plotcurve")); - int index = m_curves.Index( *curve ); - wxCHECK_MSG( index != wxNOT_FOUND, false, wxT("Unknown PlotCurve") ); + int index = m_curves.Index(*curve); + wxCHECK_MSG(index != wxNOT_FOUND, false, wxT("Unknown PlotCurve")); - return DeleteCurve(index, send_event); + return DeleteCurve(index, send_event); } -bool wxPlotCtrl::DeleteCurve( int n, bool send_event ) +bool wxPlotCtrl::DeleteCurve(int n, bool send_event) { - wxCHECK_MSG((n>=-1)&&(n= -1) && (n < int(m_curves.GetCount())), false, wxT("Invalid curve index")); - if (send_event) - { - wxPlotEvent event( wxEVT_PLOT_DELETING_CURVE, GetId(), this ); - event.SetCurveIndex(n); - if (!DoSendEvent(event)) return false; + if (send_event) { + wxPlotEvent event(wxEVT_PLOT_DELETING_CURVE, GetId(), this); + event.SetCurveIndex(n); + if (!DoSendEvent(event)) { + return false; } - - BeginBatch(); // don't redraw yet - - if (n < 0) - { - InvalidateCursor(send_event); - ClearSelectedRanges(-1, send_event); - m_dataSelections.Clear(); - m_curveSelections.Clear(); - m_curves.Clear(); + } + + BeginBatch(); // don't redraw yet + + if (n < 0) { + InvalidateCursor(send_event); + ClearSelectedRanges(-1, send_event); + m_dataSelections.Clear(); + m_curveSelections.Clear(); + m_curves.Clear(); + } + else { + if (m_cursor_curve == n) { + InvalidateCursor(send_event); } - else - { - if (m_cursor_curve == n) - InvalidateCursor(send_event); - else if (m_cursor_curve > n) - m_cursor_curve--; - - ClearSelectedRanges(n, send_event); - m_dataSelections.RemoveAt(n); - m_curveSelections.RemoveAt(n); - m_curves.RemoveAt(n); + else if (m_cursor_curve > n) { + m_cursor_curve--; } + ClearSelectedRanges(n, send_event); + m_dataSelections.RemoveAt(n); + m_curveSelections.RemoveAt(n); + m_curves.RemoveAt(n); + } - if (m_active_index >= int(m_curves.GetCount())) - { - // force this invalid, can't override this, the curve is "gone" - m_active_index = -1; - m_activeCurve = NULL; - SetActiveIndex( m_curves.GetCount() - 1, send_event ); - } - else if (m_active_index >= 0) - { - SetActiveIndex( m_active_index, send_event ); - } + if (m_active_index >= int(m_curves.GetCount())) { + // force this invalid, can't override this, the curve is "gone" + m_active_index = -1; + m_activeCurve = NULL; + SetActiveIndex(m_curves.GetCount() - 1, send_event); + } + else if (m_active_index >= 0) { + SetActiveIndex(m_active_index, send_event); + } - EndBatch(false); // still don't redraw + EndBatch(false); // still don't redraw - CalcBoundingPlotRect(); - CreateKeyString(); - Redraw(wxPLOT_REDRAW_PLOT); + CalcBoundingPlotRect(); + CreateKeyString(); + Redraw(wxPLOT_REDRAW_PLOT); - if (send_event) - { - wxPlotEvent event1( wxEVT_PLOT_DELETED_CURVE, GetId(), this ); - event1.SetCurveIndex(n); - (void)DoSendEvent( event1 ); - } + if (send_event) { + wxPlotEvent event1(wxEVT_PLOT_DELETED_CURVE, GetId(), this); + event1.SetCurveIndex(n); + (void)DoSendEvent(event1); + } - return true; + return true; } -wxPlotCurve* wxPlotCtrl::GetCurve( int n ) const +wxPlotCurve *wxPlotCtrl::GetCurve(int n) const { - wxCHECK_MSG((n >= 0) && (n < GetCurveCount()), NULL, wxT("Invalid index")); - return &(m_curves.Item(n)); + wxCHECK_MSG((n >= 0) && (n < GetCurveCount()), NULL, wxT("Invalid index")); + return &(m_curves.Item(n)); } -void wxPlotCtrl::SetActiveCurve( wxPlotCurve* current, bool send_event ) +void wxPlotCtrl::SetActiveCurve(wxPlotCurve *current, bool send_event) { - wxCHECK_RET(current, wxT("Invalid curve")); + wxCHECK_RET(current, wxT("Invalid curve")); - int index = m_curves.Index( *current ); - wxCHECK_RET( index != wxNOT_FOUND, wxT("Unknown PlotCurve") ); + int index = m_curves.Index(*current); + wxCHECK_RET(index != wxNOT_FOUND, wxT("Unknown PlotCurve")); - SetActiveIndex( index, send_event ); + SetActiveIndex(index, send_event); } -void wxPlotCtrl::SetActiveIndex( int curve_index, bool send_event ) +void wxPlotCtrl::SetActiveIndex(int curve_index, bool send_event) { - wxCHECK_RET((curve_index < GetCurveCount()), wxT("Invalid index")); + wxCHECK_RET((curve_index < GetCurveCount()), wxT("Invalid index")); - if (send_event) - { - wxPlotEvent event( wxEVT_PLOT_CURVE_SEL_CHANGING, GetId(), this); - event.SetCurve(m_activeCurve, m_active_index); - if (!DoSendEvent(event)) return; + if (send_event) { + wxPlotEvent event(wxEVT_PLOT_CURVE_SEL_CHANGING, GetId(), this); + event.SetCurve(m_activeCurve, m_active_index); + if (!DoSendEvent(event)) { + return; } + } - if ((curve_index >= 0) && m_curves.Item(curve_index).Ok()) - { - m_active_index = curve_index; - m_activeCurve = &(m_curves.Item(curve_index)); - } - else - { - m_active_index = -1; - m_activeCurve = NULL; - } + if ((curve_index >= 0) && m_curves.Item(curve_index).Ok()) { + m_active_index = curve_index; + m_activeCurve = &(m_curves.Item(curve_index)); + } + else { + m_active_index = -1; + m_activeCurve = NULL; + } - if (send_event) - { - wxPlotEvent event( wxEVT_PLOT_CURVE_SEL_CHANGED, GetId(), this); - event.SetCurve(m_activeCurve, m_active_index); - (void)DoSendEvent( event ); - } + if (send_event) { + wxPlotEvent event(wxEVT_PLOT_CURVE_SEL_CHANGED, GetId(), this); + event.SetCurve(m_activeCurve, m_active_index); + (void)DoSendEvent(event); + } - Redraw(wxPLOT_REDRAW_PLOT); + Redraw(wxPLOT_REDRAW_PLOT); } wxArrayInt wxPlotCtrl::GetPlotDataIndexes() const { - wxArrayInt array; - size_t n, count = m_curves.GetCount(); - for (n=0; n= 0) && (marker < (int)m_plotMarkers.GetCount()), wxT("Invalid marker number")); - m_plotMarkers.RemoveAt(marker); + wxCHECK_RET((marker >= 0) && (marker < (int)m_plotMarkers.GetCount()), + wxT("Invalid marker number")); + m_plotMarkers.RemoveAt(marker); } -void wxPlotCtrl::ClearMarkers() -{ - m_plotMarkers.Clear(); -} +void wxPlotCtrl::ClearMarkers() { m_plotMarkers.Clear(); } wxPlotMarker wxPlotCtrl::GetMarker(int marker) const { - wxCHECK_MSG((marker >= 0) && (marker < (int)m_plotMarkers.GetCount()), wxPlotMarker(), - wxT("Invalid marker number")); - return m_plotMarkers[marker]; + wxCHECK_MSG((marker >= 0) && (marker < (int)m_plotMarkers.GetCount()), wxPlotMarker(), + wxT("Invalid marker number")); + return m_plotMarkers[marker]; } //------------------------------------------------------------------------- @@ -1538,188 +1567,192 @@ wxPlotMarker wxPlotCtrl::GetMarker(int marker) const void wxPlotCtrl::InvalidateCursor(bool send_event) { - bool changed = m_cursor_curve >= 0; - m_cursor_curve = -1; - m_cursor_index = -1; - m_cursorMarker.SetPlotPosition(wxPoint2DDouble(0, 0)); + bool changed = m_cursor_curve >= 0; + m_cursor_curve = -1; + m_cursor_index = -1; + m_cursorMarker.SetPlotPosition(wxPoint2DDouble(0, 0)); - if (send_event && changed) - { - wxPlotEvent plotEvent(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this ); - (void)DoSendEvent( plotEvent ); - } + if (send_event && changed) { + wxPlotEvent plotEvent(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this); + (void)DoSendEvent(plotEvent); + } } bool wxPlotCtrl::IsCursorValid() { - if (m_cursor_curve < 0) return false; - - // sanity check - if (m_cursor_curve >= int(m_curves.GetCount())) - { - wxFAIL_MSG(wxT("Invalid cursor index")); - InvalidateCursor(true); - return false; - } + if (m_cursor_curve < 0) { + return false; + } - wxPlotData *plotData = GetDataCurve(m_cursor_curve); - if (plotData) - { - // sanity check - if (m_cursor_index < 0) - { - wxFAIL_MSG(wxT("Invalid cursor data index")); - InvalidateCursor(true); - return false; - } - // if the curve shrinks or is bad - if (!plotData->Ok() || (m_cursor_index >= (int)plotData->GetCount())) - { - InvalidateCursor(true); - return false; - } + // sanity check + if (m_cursor_curve >= int(m_curves.GetCount())) { + wxFAIL_MSG(wxT("Invalid cursor index")); + InvalidateCursor(true); + return false; + } - m_cursorMarker.SetPlotPosition(plotData->GetPoint(m_cursor_index)); + wxPlotData *plotData = GetDataCurve(m_cursor_curve); + if (plotData) { + // sanity check + if (m_cursor_index < 0) { + wxFAIL_MSG(wxT("Invalid cursor data index")); + InvalidateCursor(true); + return false; } - else - { - wxDouble x = m_cursorMarker.GetPlotRect().m_x; - m_cursorMarker.GetPlotRect().m_y = GetCurve(m_cursor_curve)->GetY(x); + // if the curve shrinks or is bad + if (!plotData->Ok() || (m_cursor_index >= (int)plotData->GetCount())) { + InvalidateCursor(true); + return false; } - return true; + m_cursorMarker.SetPlotPosition(plotData->GetPoint(m_cursor_index)); + } + else { + wxDouble x = m_cursorMarker.GetPlotRect().m_x; + m_cursorMarker.GetPlotRect().m_y = GetCurve(m_cursor_curve)->GetY(x); + } + + return true; } wxPoint2DDouble wxPlotCtrl::GetCursorPoint() { - wxCHECK_MSG(IsCursorValid(), wxPoint2DDouble(0, 0), wxT("invalid cursor")); - return m_cursorMarker.GetPlotPosition(); + wxCHECK_MSG(IsCursorValid(), wxPoint2DDouble(0, 0), wxT("invalid cursor")); + return m_cursorMarker.GetPlotPosition(); } bool wxPlotCtrl::SetCursorDataIndex(int curve_index, int cursor_index, bool send_event) { - wxCHECK_MSG(CurveIndexOk(curve_index) && GetDataCurve(curve_index), - false, wxT("invalid curve index")); - - wxPlotData *plotData = GetDataCurve(curve_index); - - wxCHECK_MSG((cursor_index>=0) && plotData->Ok() && (cursor_index < (int)plotData->GetCount()), - false, wxT("invalid index")); - - // do nothing if already set - if ((m_cursor_curve == curve_index) && (m_cursor_index == cursor_index)) - return false; + wxCHECK_MSG(CurveIndexOk(curve_index) && GetDataCurve(curve_index), false, + wxT("invalid curve index")); - wxPoint2DDouble cursorPt(plotData->GetPoint(cursor_index)); + wxPlotData *plotData = GetDataCurve(curve_index); - if (send_event) - { - wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGING, GetId(), this ); - cursor_event.SetPosition( cursorPt.m_x, cursorPt.m_y ); - cursor_event.SetCurve( plotData, curve_index ); - cursor_event.SetCurveDataIndex(cursor_index); - if (!DoSendEvent( cursor_event )) return false; - } + wxCHECK_MSG((cursor_index >= 0) && plotData->Ok() && (cursor_index < (int)plotData->GetCount()), + false, wxT("invalid index")); - int old_cursor_curve = m_cursor_curve; - int old_cursor_index = m_cursor_index; - m_cursorMarker.SetPlotPosition(cursorPt); - m_cursor_curve = curve_index; - m_cursor_index = cursor_index; + // do nothing if already set + if ((m_cursor_curve == curve_index) && (m_cursor_index == cursor_index)) { + return false; + } - if (send_event) - { - wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this ); - cursor_event.SetPosition( cursorPt.m_x, cursorPt.m_y ); - cursor_event.SetCurve( plotData, curve_index ); - cursor_event.SetCurveDataIndex(cursor_index); - (void)DoSendEvent( cursor_event ); - } + wxPoint2DDouble cursorPt(plotData->GetPoint(cursor_index)); - if ((m_active_index == old_cursor_curve) && (m_active_index == m_cursor_curve)) - { - RedrawDataCurve(curve_index, old_cursor_index, old_cursor_index); - RedrawDataCurve(curve_index, m_cursor_index, m_cursor_index); + if (send_event) { + wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGING, GetId(), this); + cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); + cursor_event.SetCurve(plotData, curve_index); + cursor_event.SetCurveDataIndex(cursor_index); + if (!DoSendEvent(cursor_event)) { + return false; } - else - Redraw(wxPLOT_REDRAW_PLOT); + } + + int old_cursor_curve = m_cursor_curve; + int old_cursor_index = m_cursor_index; + m_cursorMarker.SetPlotPosition(cursorPt); + m_cursor_curve = curve_index; + m_cursor_index = cursor_index; + + if (send_event) { + wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this); + cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); + cursor_event.SetCurve(plotData, curve_index); + cursor_event.SetCurveDataIndex(cursor_index); + (void)DoSendEvent(cursor_event); + } + + if ((m_active_index == old_cursor_curve) && (m_active_index == m_cursor_curve)) { + RedrawDataCurve(curve_index, old_cursor_index, old_cursor_index); + RedrawDataCurve(curve_index, m_cursor_index, m_cursor_index); + } + else { + Redraw(wxPLOT_REDRAW_PLOT); + } - return true; + return true; } bool wxPlotCtrl::SetCursorXPoint(int curve_index, double x, bool send_event) { - wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); + wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); - if (GetDataCurve(curve_index)) - return SetCursorDataIndex(curve_index, GetDataCurve(curve_index)->GetIndexFromX(x), send_event); + if (GetDataCurve(curve_index)) { + return SetCursorDataIndex(curve_index, GetDataCurve(curve_index)->GetIndexFromX(x), + send_event); + } - // do nothing if already set - if ((m_cursor_curve == curve_index) && (m_cursorMarker.GetPlotRect().m_x == x)) - return false; + // do nothing if already set + if ((m_cursor_curve == curve_index) && (m_cursorMarker.GetPlotRect().m_x == x)) { + return false; + } - wxPlotCurve *plotCurve = GetCurve(curve_index); - wxPoint2DDouble cursorPt(x, plotCurve->GetY(x)); + wxPlotCurve *plotCurve = GetCurve(curve_index); + wxPoint2DDouble cursorPt(x, plotCurve->GetY(x)); - if (send_event) - { - wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGING, GetId(), this ); - cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); - cursor_event.SetCurve( plotCurve, curve_index ); - if (!DoSendEvent( cursor_event )) return false; + if (send_event) { + wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGING, GetId(), this); + cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); + cursor_event.SetCurve(plotCurve, curve_index); + if (!DoSendEvent(cursor_event)) { + return false; } + } - m_cursorMarker.SetPlotPosition(cursorPt); - m_cursor_curve = curve_index; - m_cursor_index = -1; + m_cursorMarker.SetPlotPosition(cursorPt); + m_cursor_curve = curve_index; + m_cursor_index = -1; - if (send_event) - { - wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this ); - cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); - cursor_event.SetCurve( plotCurve, curve_index ); - (void)DoSendEvent( cursor_event ); - } + if (send_event) { + wxPlotEvent cursor_event(wxEVT_PLOT_CURSOR_CHANGED, GetId(), this); + cursor_event.SetPosition(cursorPt.m_x, cursorPt.m_y); + cursor_event.SetCurve(plotCurve, curve_index); + (void)DoSendEvent(cursor_event); + } - Redraw(wxPLOT_REDRAW_PLOT); - return true; + Redraw(wxPLOT_REDRAW_PLOT); + return true; } void wxPlotCtrl::MakeCursorVisible(bool center, bool send_event) { - wxCHECK_RET(IsCursorValid(), wxT("invalid plot cursor")); - - if (center) - { - wxPoint2DDouble origin = m_viewRect.GetLeftTop() - - m_viewRect.GetCentre() + - GetCursorPoint(); - - SetOrigin(origin.m_x, origin.m_y, send_event); - return; - } - - wxPoint2DDouble origin = GetCursorPoint(); + wxCHECK_RET(IsCursorValid(), wxT("invalid plot cursor")); - if (m_viewRect.Contains(origin)) - return; - - double dx = 4/m_zoom.m_x; - double dy = 4/m_zoom.m_y; + if (center) { + wxPoint2DDouble origin = m_viewRect.GetLeftTop() - m_viewRect.GetCentre() + GetCursorPoint(); - if (origin.m_x < m_viewRect.m_x) - origin.m_x -= dx; - else if (origin.m_x > m_viewRect.GetRight()) - origin.m_x = m_viewRect.m_x + (origin.m_x - m_viewRect.GetRight()) + dx; - else - origin.m_x = m_viewRect.m_x; + SetOrigin(origin.m_x, origin.m_y, send_event); + return; + } - if (origin.m_y < m_viewRect.m_y) - origin.m_y -= dy; - else if (origin.m_y > m_viewRect.GetBottom()) - origin.m_y = m_viewRect.m_y + (origin.m_y - m_viewRect.GetBottom()) + dy; - else - origin.m_y = m_viewRect.m_y; + wxPoint2DDouble origin = GetCursorPoint(); - SetOrigin(origin.m_x, origin.m_y, send_event); + if (m_viewRect.Contains(origin)) { + return; + } + + double dx = 4 / m_zoom.m_x; + double dy = 4 / m_zoom.m_y; + + if (origin.m_x < m_viewRect.m_x) { + origin.m_x -= dx; + } + else if (origin.m_x > m_viewRect.GetRight()) { + origin.m_x = m_viewRect.m_x + (origin.m_x - m_viewRect.GetRight()) + dx; + } + else { + origin.m_x = m_viewRect.m_x; + } + + if (origin.m_y < m_viewRect.m_y) { + origin.m_y -= dy; + } + else if (origin.m_y > m_viewRect.GetBottom()) { + origin.m_y = m_viewRect.m_y + (origin.m_y - m_viewRect.GetBottom()) + dy; + } + else { + origin.m_y = m_viewRect.m_y; + } + + SetOrigin(origin.m_x, origin.m_y, send_event); } //------------------------------------------------------------------------- @@ -1727,338 +1760,353 @@ void wxPlotCtrl::MakeCursorVisible(bool center, bool send_event) //------------------------------------------------------------------------- bool wxPlotCtrl::HasSelection(int curve_index) const { - if (curve_index == -1) - { - int n, count = m_curveSelections.GetCount(); - for ( n = 0; n < count; n++ ) - { - if ((m_curveSelections[n].GetCount() > 0) || - (m_dataSelections[n].GetCount() > 0)) - return true; - } - return false; + if (curve_index == -1) { + int n, count = m_curveSelections.GetCount(); + for (n = 0; n < count; n++) { + if ((m_curveSelections[n].GetCount() > 0) || (m_dataSelections[n].GetCount() > 0)) { + return true; + } } + return false; + } - wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); - return (m_curveSelections[curve_index].GetCount() > 0) || - (m_dataSelections[curve_index].GetCount() > 0); + wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); + return (m_curveSelections[curve_index].GetCount() > 0) || + (m_dataSelections[curve_index].GetCount() > 0); } wxRangeDoubleSelection *wxPlotCtrl::GetCurveSelection(int curve_index) const { - wxCHECK_MSG(CurveIndexOk(curve_index), NULL, wxT("invalid curve index")); - return &m_curveSelections[curve_index]; + wxCHECK_MSG(CurveIndexOk(curve_index), NULL, wxT("invalid curve index")); + return &m_curveSelections[curve_index]; } wxRangeIntSelection *wxPlotCtrl::GetDataCurveSelection(int curve_index) const { - wxCHECK_MSG(CurveIndexOk(curve_index), NULL, wxT("invalid curve index")); - return &m_dataSelections[curve_index]; + wxCHECK_MSG(CurveIndexOk(curve_index), NULL, wxT("invalid curve index")); + return &m_dataSelections[curve_index]; } bool wxPlotCtrl::UpdateSelectionState(int curve_index, bool send_event) { - wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); - switch (m_selection_type) - { - case wxPLOT_SELECT_NONE : break; // should have been handled - case wxPLOT_SELECT_SINGLE : - { - if (HasSelection()) - return ClearSelectedRanges(-1, send_event); - - break; - } - case wxPLOT_SELECT_SINGLE_CURVE : - { - int n, count = m_curves.GetCount(); - bool done = false; - for ( n = 0; n < count; n++ ) - { - if (n == curve_index) continue; - if (HasSelection(n)) - done |= ClearSelectedRanges(n, send_event); - } - return done; - } - case wxPLOT_SELECT_SINGLE_PER_CURVE : - { - if (HasSelection(curve_index)) - return ClearSelectedRanges(curve_index, send_event); + wxCHECK_MSG(CurveIndexOk(curve_index), false, wxT("invalid curve index")); + switch (m_selection_type) { + case wxPLOT_SELECT_NONE: + break; // should have been handled + case wxPLOT_SELECT_SINGLE: { + if (HasSelection()) { + return ClearSelectedRanges(-1, send_event); + } - break; - } - case wxPLOT_SELECT_MULTIPLE : break; // anything goes - default : break; + break; + } + case wxPLOT_SELECT_SINGLE_CURVE: { + int n, count = m_curves.GetCount(); + bool done = false; + for (n = 0; n < count; n++) { + if (n == curve_index) { + continue; + } + if (HasSelection(n)) { + done |= ClearSelectedRanges(n, send_event); + } + } + return done; + } + case wxPLOT_SELECT_SINGLE_PER_CURVE: { + if (HasSelection(curve_index)) { + return ClearSelectedRanges(curve_index, send_event); } - return false; + break; + } + case wxPLOT_SELECT_MULTIPLE: + break; // anything goes + default: + break; + } + + return false; } -bool wxPlotCtrl::DoSelectRectangle(int curve_index, const wxRect2DDouble &rect, - bool select, bool send_event) +bool wxPlotCtrl::DoSelectRectangle(int curve_index, const wxRect2DDouble &rect, bool select, + bool send_event) { - wxCHECK_MSG((curve_index >= -1) && (curve_index 0) || (rect.m_height > 0), false, wxT("invalid selection range")); + wxCHECK_MSG((curve_index >= -1) && (curve_index < int(m_curves.GetCount())), false, + wxT("invalid plotcurve index")); + wxCHECK_MSG((rect.m_width > 0) || (rect.m_height > 0), false, wxT("invalid selection range")); - if (m_selection_type == wxPLOT_SELECT_NONE) - return false; - - if (!IsFinite(rect.m_x, wxT("Selection x is NaN")) || - !IsFinite(rect.m_y, wxT("Selection y is NaN")) || - !IsFinite(rect.m_width, wxT("Selection width is NaN")) || - !IsFinite(rect.m_height, wxT("Selection height is NaN")) ) - return false; + if (m_selection_type == wxPLOT_SELECT_NONE) { + return false; + } - bool done = false; + if (!IsFinite(rect.m_x, wxT("Selection x is NaN")) || + !IsFinite(rect.m_y, wxT("Selection y is NaN")) || + !IsFinite(rect.m_width, wxT("Selection width is NaN")) || + !IsFinite(rect.m_height, wxT("Selection height is NaN"))) { + return false; + } - // Run this code for all the curves if curve == -1 then exit - if (curve_index == -1) - { - size_t n, curve_count = m_curves.GetCount(); + bool done = false; - for (n = 0; n < curve_count; n++) - done |= DoSelectRectangle(n, rect, select, send_event); + // Run this code for all the curves if curve == -1 then exit + if (curve_index == -1) { + size_t n, curve_count = m_curves.GetCount(); - return done; + for (n = 0; n < curve_count; n++) { + done |= DoSelectRectangle(n, rect, select, send_event); } - // check the selection type and clear previous selections if necessary - if (select) - UpdateSelectionState(curve_index, send_event); + return done; + } + + // check the selection type and clear previous selections if necessary + if (select) { + UpdateSelectionState(curve_index, send_event); + } + + bool is_x_range = rect.m_height <= 0; + bool is_y_range = rect.m_width <= 0; + wxRangeDouble xRange(rect.m_x, rect.GetRight()); + wxRangeDouble yRange(rect.m_y, rect.GetBottom()); + + wxPlotData *plotData = GetDataCurve(curve_index); + if (plotData) { + wxCHECK_MSG(plotData->Ok(), false, wxT("Invalid data curve")); + wxRect2DDouble r(plotData->GetBoundingRect()); - bool is_x_range = rect.m_height <= 0; - bool is_y_range = rect.m_width <= 0; - wxRangeDouble xRange(rect.m_x, rect.GetRight()); - wxRangeDouble yRange(rect.m_y, rect.GetBottom()); + if ((xRange.m_max < r.GetLeft()) || (xRange.m_min > r.GetRight())) { + return false; + } + + if (is_x_range && plotData->GetIsXOrdered()) { + int min_ = plotData->GetIndexFromX(xRange.m_min); + int max_ = plotData->GetIndexFromX(xRange.m_max); + int count = plotData->GetCount(); + + if ((plotData->GetXValue(min_) > xRange.m_min) && (min_ > 0) && + (plotData->GetXValue(min_ - 1) > xRange.m_min)) { + min_--; + } + if ((plotData->GetXValue(min_) < xRange.m_min) && (min_ < count - 1)) { + min_++; + } + + if ((plotData->GetXValue(max_) > xRange.m_max) && (max_ > 0)) { + max_--; + } + if ((plotData->GetXValue(max_) < xRange.m_max) && (max_ < count - 1) && + (plotData->GetXValue(max_ + 1) < xRange.m_max)) { + max_++; + } + + wxRangeInt sel(min_, max_); // always check if max < min! - not a bug + + if (!sel.IsEmpty()) { + if (select) { + m_curveSelections[curve_index].SelectRange(wxRangeDouble(rect.m_x, rect.GetRight())); + } + else { + m_curveSelections[curve_index].DeselectRange(wxRangeDouble(rect.m_x, rect.GetRight())); + } - wxPlotData *plotData = GetDataCurve(curve_index); - if (plotData) + return DoSelectDataRange(curve_index, sel, select, send_event); + } + else { + return false; + } + } + else // not ordered or not just an x selection { - wxCHECK_MSG(plotData->Ok(), false, wxT("Invalid data curve")); - wxRect2DDouble r(plotData->GetBoundingRect()); - - if ((xRange.m_max < r.GetLeft()) || (xRange.m_min > r.GetRight())) - return false; - - if (is_x_range && plotData->GetIsXOrdered()) - { - int min_ = plotData->GetIndexFromX(xRange.m_min); - int max_ = plotData->GetIndexFromX(xRange.m_max); - int count = plotData->GetCount(); - - if ( (plotData->GetXValue(min_) > xRange.m_min) && (min_ > 0) && - (plotData->GetXValue(min_-1) > xRange.m_min) ) - min_--; - if ( (plotData->GetXValue(min_) < xRange.m_min) && (min_ < count -1) ) - min_++; - - if ( (plotData->GetXValue(max_) > xRange.m_max) && (max_ > 0) ) - max_--; - if ( (plotData->GetXValue(max_) < xRange.m_max) && (max_ < count-1) && - (plotData->GetXValue(max_+1) < xRange.m_max) ) - max_++; - - wxRangeInt sel(min_, max_); // always check if max < min! - not a bug - - if (!sel.IsEmpty()) - { - if (select) - m_curveSelections[curve_index].SelectRange(wxRangeDouble(rect.m_x, rect.GetRight())); - else - m_curveSelections[curve_index].DeselectRange(wxRangeDouble(rect.m_x, rect.GetRight())); - - return DoSelectDataRange(curve_index, sel, select, send_event); + int i, count = plotData->GetCount(); + int first_sel = -1; + double *x_data = plotData->GetXData(); + double *y_data = plotData->GetYData(); + + int min_ = plotData->GetCount() - 1, max_ = 0; + + wxRangeIntSelection ranges; + + for (i = 0; i < count; i++) { + if ((is_x_range && xRange.Contains(*x_data)) || (is_y_range && yRange.Contains(*y_data)) || + (!is_x_range && !is_y_range && wxPlotRect2DDoubleContains(*x_data, *y_data, rect))) { + if (select) { + if (m_dataSelections[curve_index].SelectRange(wxRangeInt(i, i))) { + ranges.SelectRange(wxRangeInt(i, i)); + done = true; } - else - return false; - } - else // not ordered or not just an x selection - { - int i, count = plotData->GetCount(); - int first_sel = -1; - double *x_data = plotData->GetXData(); - double *y_data = plotData->GetYData(); - - int min_ = plotData->GetCount()-1, max_ = 0; - - wxRangeIntSelection ranges; - - for (i=0; i= 0) && (range.m_max < (int)plotData->GetCount()), false, wxT("invalid index")); + wxPlotData *plotData = GetDataCurve(curve_index); + wxCHECK_MSG(plotData && (range.m_min >= 0) && (range.m_max < (int)plotData->GetCount()), false, + wxT("invalid index")); - // check the selection type and clear previous selections if necessary - if (select) - UpdateSelectionState(curve_index, send_event); + // check the selection type and clear previous selections if necessary + if (select) { + UpdateSelectionState(curve_index, send_event); + } - bool done = false; + bool done = false; - if (select) - done = m_dataSelections[curve_index].SelectRange(range); - else - done = m_dataSelections[curve_index].DeselectRange(range); + if (select) { + done = m_dataSelections[curve_index].SelectRange(range); + } + else { + done = m_dataSelections[curve_index].DeselectRange(range); + } - wxPrintf(wxT("Do sel %d %d %d\n"), range.m_min, range.m_max, done); + wxPrintf(wxT("Do sel %d %d %d\n"), range.m_min, range.m_max, done); - if (send_event && done) - { - wxPlotSelectionEvent event( wxEVT_PLOT_RANGE_SEL_CHANGED, GetId(), this); - event.SetCurve(GetCurve(curve_index), curve_index); - event.SetDataSelectionRange( range, select ); - event.m_dataSelection.SelectRange(range); - (void)DoSendEvent( event ); - } + if (send_event && done) { + wxPlotSelectionEvent event(wxEVT_PLOT_RANGE_SEL_CHANGED, GetId(), this); + event.SetCurve(GetCurve(curve_index), curve_index); + event.SetDataSelectionRange(range, select); + event.m_dataSelection.SelectRange(range); + (void)DoSendEvent(event); + } - if (done) RedrawDataCurve(curve_index, range.m_min, range.m_max); + if (done) { + RedrawDataCurve(curve_index, range.m_min, range.m_max); + } - return done; + return done; } int wxPlotCtrl::GetSelectedRangeCount(int curve_index) const { - wxCHECK_MSG(CurveIndexOk(curve_index), 0, wxT("invalid plotcurve index")); + wxCHECK_MSG(CurveIndexOk(curve_index), 0, wxT("invalid plotcurve index")); - if (GetDataCurve(curve_index)) - return m_dataSelections[curve_index].GetCount(); - else - return m_curveSelections[curve_index].GetCount(); + if (GetDataCurve(curve_index)) { + return m_dataSelections[curve_index].GetCount(); + } + else { + return m_curveSelections[curve_index].GetCount(); + } } bool wxPlotCtrl::ClearSelectedRanges(int curve_index, bool send_event) { - wxCHECK_MSG((curve_index >= -1) && (curve_index= -1) && (curve_index < int(m_curves.GetCount())), false, + wxT("invalid plotcurve index")); - bool done = false; + bool done = false; - if (curve_index == -1) - { - for (size_t n=0; n 0; + m_dataSelections[curve_index].Clear(); + m_curveSelections[curve_index].Clear(); + if (done) { + RedrawDataCurve(curve_index, 0, GetDataCurve(curve_index)->GetCount() - 1); + } } - else - { - if (IsDataCurve(curve_index)) - { - done = m_dataSelections[curve_index].GetCount() > 0; - m_dataSelections[curve_index].Clear(); - m_curveSelections[curve_index].Clear(); - if (done) - RedrawDataCurve(curve_index, 0, GetDataCurve(curve_index)->GetCount()-1); - } - else - { - done = m_curveSelections[curve_index].GetCount() > 0; - m_curveSelections[curve_index].Clear(); - m_dataSelections[curve_index].Clear(); - if (done) - RedrawCurve(curve_index, m_viewRect.m_x, m_viewRect.GetRight()); - } + else { + done = m_curveSelections[curve_index].GetCount() > 0; + m_curveSelections[curve_index].Clear(); + m_dataSelections[curve_index].Clear(); + if (done) { + RedrawCurve(curve_index, m_viewRect.m_x, m_viewRect.GetRight()); + } } + } - if (send_event && done) - { - wxPlotSelectionEvent event( wxEVT_PLOT_RANGE_SEL_CHANGED, GetId(), this); - event.SetCurve(GetCurve(curve_index), curve_index); - - if (IsDataCurve(curve_index)) - event.SetDataSelectionRange(wxRangeInt(0, GetDataCurve(curve_index)->GetCount()-1), false); - else - event.SetCurveSelectionRange(wxEmptyRangeDouble, false); + if (send_event && done) { + wxPlotSelectionEvent event(wxEVT_PLOT_RANGE_SEL_CHANGED, GetId(), this); + event.SetCurve(GetCurve(curve_index), curve_index); - (void)DoSendEvent( event ); + if (IsDataCurve(curve_index)) { + event.SetDataSelectionRange(wxRangeInt(0, GetDataCurve(curve_index)->GetCount() - 1), false); } - return done; + else { + event.SetCurveSelectionRange(wxEmptyRangeDouble, false); + } + + (void)DoSendEvent(event); + } + return done; } // ------------------------------------------------------------------------ @@ -2094,16 +2142,17 @@ void wxPlotCtrl::ShiftOrigin( int dx, int dy, bool send_event ) if (dx != 0) { - rx = wxRect((dx>0 ? -5 : m_areaClientRect.width+dx-5), 0, labs(dx)+10, m_areaClientRect.height); - RedrawXAxis(false); + rx = wxRect((dx>0 ? -5 : m_areaClientRect.width+dx-5), 0, labs(dx)+10, +m_areaClientRect.height); RedrawXAxis(false); } if (dy != 0) { - ry = wxRect(0, (dy>0 ? -5 : m_areaClientRect.height+dy-5), m_areaClientRect.width, labs(dy)+10); - RedrawYAxis(false); + ry = wxRect(0, (dy>0 ? -5 : m_areaClientRect.height+dy-5), m_areaClientRect.width, +labs(dy)+10); RedrawYAxis(false); } - printf("Shift %d %d rx %d %d %d %d, ry %d %d %d %d\n", dx, dy, rx.x, rx.y, rx.width, rx.height, ry.x, ry.y, ry.width, ry.height); fflush(stdout); + printf("Shift %d %d rx %d %d %d %d, ry %d %d %d %d\n", dx, dy, rx.x, rx.y, rx.width, rx.height, +ry.x, ry.y, ry.width, ry.height); fflush(stdout); if (rx.width > 0) m_area->CreateBitmap( rx ); //m_area->Refresh(false, &rx); @@ -2128,961 +2177,1000 @@ void wxPlotCtrl::ShiftOrigin( int dx, int dy, bool send_event ) bool wxPlotCtrl::MakeCurveVisible(int curve_index, bool send_event) { - if (curve_index < 0) - return SetZoom( -1, -1, 0, 0, send_event ); + if (curve_index < 0) { + return SetZoom(-1, -1, 0, 0, send_event); + } - wxCHECK_MSG(curve_index < GetCurveCount(), false, wxT("Invalid curve index")); - wxPlotCurve *curve = GetCurve(curve_index); - wxCHECK_MSG(curve && curve->Ok(), false, wxT("Invalid curve")); - return SetViewRect(curve->GetBoundingRect(), send_event); + wxCHECK_MSG(curve_index < GetCurveCount(), false, wxT("Invalid curve index")); + wxPlotCurve *curve = GetCurve(curve_index); + wxCHECK_MSG(curve && curve->Ok(), false, wxT("Invalid curve")); + return SetViewRect(curve->GetBoundingRect(), send_event); } bool wxPlotCtrl::SetViewRect(const wxRect2DDouble &view, bool send_event) { - double zoom_x = m_areaClientRect.width/view.m_width; - double zoom_y = m_areaClientRect.height/view.m_height; - return SetZoom(zoom_x, zoom_y, view.m_x, view.m_y, send_event); + double zoom_x = m_areaClientRect.width / view.m_width; + double zoom_y = m_areaClientRect.height / view.m_height; + return SetZoom(zoom_x, zoom_y, view.m_x, view.m_y, send_event); } -bool wxPlotCtrl::SetZoom( const wxPoint2DDouble &zoom, bool around_center, bool send_event ) +bool wxPlotCtrl::SetZoom(const wxPoint2DDouble &zoom, bool around_center, bool send_event) { - if (around_center && (zoom.m_x > 0) && (zoom.m_y > 0)) - { - double origin_x = (m_viewRect.GetLeft() + m_viewRect.m_width/2.0); - origin_x -= (m_viewRect.m_width/2.0)*m_zoom.m_x/zoom.m_x; - double origin_y = (m_viewRect.GetTop() + m_viewRect.m_height/2.0); - origin_y -= (m_viewRect.m_height/2.0)*m_zoom.m_y/zoom.m_y; - return SetZoom( zoom.m_x, zoom.m_y, origin_x, origin_y, send_event ); - } - else - return SetZoom( zoom.m_x, zoom.m_y, m_viewRect.GetLeft(), m_viewRect.GetTop(), send_event ); + if (around_center && (zoom.m_x > 0) && (zoom.m_y > 0)) { + double origin_x = (m_viewRect.GetLeft() + m_viewRect.m_width / 2.0); + origin_x -= (m_viewRect.m_width / 2.0) * m_zoom.m_x / zoom.m_x; + double origin_y = (m_viewRect.GetTop() + m_viewRect.m_height / 2.0); + origin_y -= (m_viewRect.m_height / 2.0) * m_zoom.m_y / zoom.m_y; + return SetZoom(zoom.m_x, zoom.m_y, origin_x, origin_y, send_event); + } + else { + return SetZoom(zoom.m_x, zoom.m_y, m_viewRect.GetLeft(), m_viewRect.GetTop(), send_event); + } } -bool wxPlotCtrl::SetZoom( const wxRect &window, bool send_event ) +bool wxPlotCtrl::SetZoom(const wxRect &window, bool send_event) { - if ((window.GetHeight()<1) || (window.GetWidth()<1)) return false; + if ((window.GetHeight() < 1) || (window.GetWidth() < 1)) { + return false; + } - double origin_x = GetPlotCoordFromClientX(window.GetX()); - double origin_y = GetPlotCoordFromClientY(window.GetY()+window.GetHeight()); - double zoom_x = m_zoom.m_x * double(m_areaClientRect.width) /(window.GetWidth()); - double zoom_y = m_zoom.m_y * double(m_areaClientRect.height)/(window.GetHeight()); + double origin_x = GetPlotCoordFromClientX(window.GetX()); + double origin_y = GetPlotCoordFromClientY(window.GetY() + window.GetHeight()); + double zoom_x = m_zoom.m_x * double(m_areaClientRect.width) / (window.GetWidth()); + double zoom_y = m_zoom.m_y * double(m_areaClientRect.height) / (window.GetHeight()); - bool ok = SetZoom( zoom_x, zoom_y, origin_x, origin_y, send_event ); - if (ok) AddHistoryView(); - return ok; + bool ok = SetZoom(zoom_x, zoom_y, origin_x, origin_y, send_event); + if (ok) { + AddHistoryView(); + } + return ok; } -bool wxPlotCtrl::SetZoom( double zoom_x, double zoom_y, - double origin_x, double origin_y, bool send_event ) +bool wxPlotCtrl::SetZoom(double zoom_x, double zoom_y, double origin_x, double origin_y, + bool send_event) { - // fit to window if zoom <= 0 - if (zoom_x <= 0) - { - zoom_x = double(m_areaClientRect.width)/(m_curveBoundingRect.m_width); - origin_x = m_curveBoundingRect.m_x; - } - if (zoom_y <= 0) - { - zoom_y = double(m_areaClientRect.height)/(m_curveBoundingRect.m_height); - origin_y = m_curveBoundingRect.m_y; - } - - if (m_fix_aspectratio) - FixAspectRatio( &zoom_x, &zoom_y, &origin_x, &origin_y ); - - double view_width = m_areaClientRect.width/zoom_x; - double view_height = m_areaClientRect.height/zoom_y; - - if (!IsFinite(zoom_x, wxT("X zoom is NaN"))) return false; - if (!IsFinite(zoom_y, wxT("Y zoom is NaN"))) return false; - if (!IsFinite(origin_x, wxT("X origin is not finite"))) return false; - if (!IsFinite(origin_y, wxT("Y origin is not finite"))) return false; - if (!IsFinite(view_width, wxT("Plot width is NaN"))) return false; - if (!IsFinite(view_height, wxT("Plot height is NaN"))) return false; + // fit to window if zoom <= 0 + if (zoom_x <= 0) { + zoom_x = double(m_areaClientRect.width) / (m_curveBoundingRect.m_width); + origin_x = m_curveBoundingRect.m_x; + } + if (zoom_y <= 0) { + zoom_y = double(m_areaClientRect.height) / (m_curveBoundingRect.m_height); + origin_y = m_curveBoundingRect.m_y; + } - bool x_changed = false, y_changed = false; + if (m_fix_aspectratio) { + FixAspectRatio(&zoom_x, &zoom_y, &origin_x, &origin_y); + } - if ((m_viewRect.m_x != origin_x) || (m_zoom.m_x != zoom_x)) - x_changed = true; - if ((m_viewRect.m_y != origin_y) || (m_zoom.m_y != zoom_y)) - y_changed = true; + double view_width = m_areaClientRect.width / zoom_x; + double view_height = m_areaClientRect.height / zoom_y; - if (x_changed || y_changed) - { - if (send_event) - { - wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGING, GetId(), this); - event.SetCurve(m_activeCurve, m_active_index); - if (!DoSendEvent(event)) return false; - } + if (!IsFinite(zoom_x, wxT("X zoom is NaN"))) { + return false; + } + if (!IsFinite(zoom_y, wxT("Y zoom is NaN"))) { + return false; + } + if (!IsFinite(origin_x, wxT("X origin is not finite"))) { + return false; + } + if (!IsFinite(origin_y, wxT("Y origin is not finite"))) { + return false; + } + if (!IsFinite(view_width, wxT("Plot width is NaN"))) { + return false; + } + if (!IsFinite(view_height, wxT("Plot height is NaN"))) { + return false; + } + + bool x_changed = false, y_changed = false; + + if ((m_viewRect.m_x != origin_x) || (m_zoom.m_x != zoom_x)) { + x_changed = true; + } + if ((m_viewRect.m_y != origin_y) || (m_zoom.m_y != zoom_y)) { + y_changed = true; + } + + if (x_changed || y_changed) { + if (send_event) { + wxPlotEvent event(wxEVT_PLOT_VIEW_CHANGING, GetId(), this); + event.SetCurve(m_activeCurve, m_active_index); + if (!DoSendEvent(event)) { + return false; + } + } - m_zoom.m_x = zoom_x; - m_zoom.m_y = zoom_y; + m_zoom.m_x = zoom_x; + m_zoom.m_y = zoom_y; - m_viewRect.m_x = origin_x; - m_viewRect.m_y = origin_y; - m_viewRect.m_width = view_width; - m_viewRect.m_height = view_height; - } + m_viewRect.m_x = origin_x; + m_viewRect.m_y = origin_y; + m_viewRect.m_width = view_width; + m_viewRect.m_height = view_height; + } - // redraw even if unchanged since we expect that it should be different - Redraw(wxPLOT_REDRAW_PLOT | (x_changed?wxPLOT_REDRAW_XAXIS:0) | - (y_changed?wxPLOT_REDRAW_YAXIS:0)); + // redraw even if unchanged since we expect that it should be different + Redraw(wxPLOT_REDRAW_PLOT | (x_changed ? wxPLOT_REDRAW_XAXIS : 0) | + (y_changed ? wxPLOT_REDRAW_YAXIS : 0)); - if (!m_batch_count) - AdjustScrollBars(); + if (!m_batch_count) { + AdjustScrollBars(); + } - if (send_event && (x_changed || y_changed)) - { - wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGED, GetId(), this); - event.SetCurve(m_activeCurve, m_active_index); - (void)DoSendEvent( event ); - } + if (send_event && (x_changed || y_changed)) { + wxPlotEvent event(wxEVT_PLOT_VIEW_CHANGED, GetId(), this); + event.SetCurve(m_activeCurve, m_active_index); + (void)DoSendEvent(event); + } - return true; + return true; } void wxPlotCtrl::SetFixAspectRatio(bool fix, double ratio) { - wxCHECK_RET(ratio > 0, wxT("Invalid aspect ratio")); - m_fix_aspectratio = fix; - m_aspectratio = ratio; + wxCHECK_RET(ratio > 0, wxT("Invalid aspect ratio")); + m_fix_aspectratio = fix; + m_aspectratio = ratio; } -void wxPlotCtrl::FixAspectRatio( double *zoom_x, double *zoom_y, double *origin_x, double *origin_y ) +void wxPlotCtrl::FixAspectRatio(double *zoom_x, double *zoom_y, double *origin_x, double *origin_y) { - wxCHECK_RET(zoom_x && zoom_y && origin_x && origin_y, wxT("Invalid parameters")); + wxCHECK_RET(zoom_x && zoom_y && origin_x && origin_y, wxT("Invalid parameters")); - //get the width and height of the view in plot coordinates - double viewWidth = m_areaClientRect.width / (*zoom_x); - double viewHeight = m_areaClientRect.height / (*zoom_y); + // get the width and height of the view in plot coordinates + double viewWidth = m_areaClientRect.width / (*zoom_x); + double viewHeight = m_areaClientRect.height / (*zoom_y); - //get the centre of the visible area in plot coordinates - double xCentre = (*origin_x) + viewWidth / 2; - double yCentre = (*origin_y) + viewHeight / 2; + // get the centre of the visible area in plot coordinates + double xCentre = (*origin_x) + viewWidth / 2; + double yCentre = (*origin_y) + viewHeight / 2; - //if zoom in one direction is more than in the other, reduce both to the lower value - if( (*zoom_x) * m_aspectratio > (*zoom_y) ) - { - (*zoom_x) = (*zoom_y) * m_aspectratio; - (*zoom_y) = (*zoom_y); - } - else - { - (*zoom_x) = (*zoom_x); - (*zoom_y) = (*zoom_x) / m_aspectratio; - } + // if zoom in one direction is more than in the other, reduce both to the lower value + if ((*zoom_x) * m_aspectratio > (*zoom_y)) { + (*zoom_x) = (*zoom_y) * m_aspectratio; + (*zoom_y) = (*zoom_y); + } + else { + (*zoom_x) = (*zoom_x); + (*zoom_y) = (*zoom_x) / m_aspectratio; + } - //update the plot coordinate view width and height based on the new zooms - viewWidth = m_areaClientRect.width / (*zoom_x); - viewHeight = m_areaClientRect.height / (*zoom_y); + // update the plot coordinate view width and height based on the new zooms + viewWidth = m_areaClientRect.width / (*zoom_x); + viewHeight = m_areaClientRect.height / (*zoom_y); - //create the new bottom-left corner of the view in plot coordinates - *origin_x = xCentre - (viewWidth / 2); - *origin_y = yCentre - (viewHeight / 2); + // create the new bottom-left corner of the view in plot coordinates + *origin_x = xCentre - (viewWidth / 2); + *origin_y = yCentre - (viewHeight / 2); } -void wxPlotCtrl::SetDefaultBoundingRect( const wxRect2DDouble &rect, bool send_event ) +void wxPlotCtrl::SetDefaultBoundingRect(const wxRect2DDouble &rect, bool send_event) { - wxCHECK_RET(wxFinite(rect.m_x)&&wxFinite(rect.m_y)&&wxFinite(rect.GetRight())&&wxFinite(rect.GetBottom()), wxT("bounding rect is NaN")); - wxCHECK_RET((rect.m_width > 0) && (rect.m_height > 0), wxT("Plot Size < 0")); - m_defaultPlotRect = rect; - CalcBoundingPlotRect(); - SetZoom( m_areaClientRect.width/rect.m_width, - m_areaClientRect.height/rect.m_height, - rect.m_x, rect.m_y, send_event); + wxCHECK_RET(wxFinite(rect.m_x) && wxFinite(rect.m_y) && wxFinite(rect.GetRight()) && + wxFinite(rect.GetBottom()), + wxT("bounding rect is NaN")); + wxCHECK_RET((rect.m_width > 0) && (rect.m_height > 0), wxT("Plot Size < 0")); + m_defaultPlotRect = rect; + CalcBoundingPlotRect(); + SetZoom(m_areaClientRect.width / rect.m_width, m_areaClientRect.height / rect.m_height, rect.m_x, + rect.m_y, send_event); } void wxPlotCtrl::AddHistoryView() { - if (!(wxFinite(m_viewRect.GetLeft())&&wxFinite(m_viewRect.GetRight())&&wxFinite(m_viewRect.GetTop())&&wxFinite(m_viewRect.GetBottom()))) return; + if (!(wxFinite(m_viewRect.GetLeft()) && wxFinite(m_viewRect.GetRight()) && + wxFinite(m_viewRect.GetTop()) && wxFinite(m_viewRect.GetBottom()))) { + return; + } - if ((m_history_views_index >= 0) - && (m_history_views_index < int(m_historyViews.GetCount())) - && WXRECT2DDOUBLE_EQUAL(m_viewRect, m_historyViews[m_history_views_index])) - return; + if ((m_history_views_index >= 0) && (m_history_views_index < int(m_historyViews.GetCount())) && + WXRECT2DDOUBLE_EQUAL(m_viewRect, m_historyViews[m_history_views_index])) { + return; + } - if (int(m_historyViews.GetCount()) >= MAX_PLOT_ZOOMS) - { - if (m_history_views_index < int(m_historyViews.GetCount())-1) - { - m_historyViews[m_history_views_index] = m_viewRect; - } - else - { - m_historyViews.RemoveAt(0); - m_historyViews.Add(m_viewRect); - } + if (int(m_historyViews.GetCount()) >= MAX_PLOT_ZOOMS) { + if (m_history_views_index < int(m_historyViews.GetCount()) - 1) { + m_historyViews[m_history_views_index] = m_viewRect; } - else - { - m_historyViews.Add(m_viewRect); - m_history_views_index++; + else { + m_historyViews.RemoveAt(0); + m_historyViews.Add(m_viewRect); } + } + else { + m_historyViews.Add(m_viewRect); + m_history_views_index++; + } } void wxPlotCtrl::NextHistoryView(bool foward, bool send_event) { - int count = m_historyViews.GetCount(); + int count = m_historyViews.GetCount(); - // try to set it to the "current" history view - if ((m_history_views_index > -1) && (m_history_views_index < count)) - { - if (!WXRECT2DDOUBLE_EQUAL(m_viewRect, m_historyViews[m_history_views_index])) - SetViewRect(m_historyViews[m_history_views_index], send_event); + // try to set it to the "current" history view + if ((m_history_views_index > -1) && (m_history_views_index < count)) { + if (!WXRECT2DDOUBLE_EQUAL(m_viewRect, m_historyViews[m_history_views_index])) { + SetViewRect(m_historyViews[m_history_views_index], send_event); } + } - if (foward) - { - if ((count > 0) && (m_history_views_index < count - 1)) - { - m_history_views_index++; - SetViewRect(m_historyViews[m_history_views_index], send_event); - } + if (foward) { + if ((count > 0) && (m_history_views_index < count - 1)) { + m_history_views_index++; + SetViewRect(m_historyViews[m_history_views_index], send_event); } - else - { - if (m_history_views_index > 0) - { - m_history_views_index--; - SetViewRect(m_historyViews[m_history_views_index], send_event); - } - else - SetZoom(-1, -1, 0, 0, send_event); + } + else { + if (m_history_views_index > 0) { + m_history_views_index--; + SetViewRect(m_historyViews[m_history_views_index], send_event); } + else { + SetZoom(-1, -1, 0, 0, send_event); + } + } } -void wxPlotCtrl::SetAreaMouseFunction( wxPlotMouse_Type func, bool send_event ) +void wxPlotCtrl::SetAreaMouseFunction(wxPlotMouse_Type func, bool send_event) { - if (func == m_area_mouse_func) return; + if (func == m_area_mouse_func) { + return; + } - if (send_event) - { - wxPlotEvent event1(wxEVT_PLOT_MOUSE_FUNC_CHANGING, GetId(), this); - event1.SetMouseFunction(func); - if (!DoSendEvent(event1)) - return; + if (send_event) { + wxPlotEvent event1(wxEVT_PLOT_MOUSE_FUNC_CHANGING, GetId(), this); + event1.SetMouseFunction(func); + if (!DoSendEvent(event1)) { + return; } + } + + m_area_mouse_func = func; + + switch (func) { + case wxPLOT_MOUSE_ZOOM: { + SetAreaMouseCursor(wxCURSOR_MAGNIFIER); // wxCURSOR_CROSS); + break; + } + case wxPLOT_MOUSE_SELECT: + case wxPLOT_MOUSE_DESELECT: { + SetAreaMouseCursor(wxCURSOR_ARROW); + break; + } + case wxPLOT_MOUSE_PAN: { + SetAreaMouseCursor(wxCURSOR_HAND); + SetAreaMouseMarker(wxPLOT_MARKER_NONE); + break; + } + case wxPLOT_MOUSE_NOTHING: + default: { + SetAreaMouseCursor(wxCURSOR_CROSS); + SetAreaMouseMarker(wxPLOT_MARKER_NONE); + break; + } + } + + if (send_event) { + wxPlotEvent event2(wxEVT_PLOT_MOUSE_FUNC_CHANGED, GetId(), this); + event2.SetMouseFunction(func); + (void)DoSendEvent(event2); + } +} + +void wxPlotCtrl::SetAreaMouseMarker(wxPlotMarker_Type type) +{ + if (type == m_area_mouse_marker) { + return; + } - m_area_mouse_func = func; - - switch (func) - { - case wxPLOT_MOUSE_ZOOM : - { - SetAreaMouseCursor(wxCURSOR_MAGNIFIER); //wxCURSOR_CROSS); - break; - } - case wxPLOT_MOUSE_SELECT : - case wxPLOT_MOUSE_DESELECT : - { - SetAreaMouseCursor(wxCURSOR_ARROW); - break; - } - case wxPLOT_MOUSE_PAN : - { - SetAreaMouseCursor(wxCURSOR_HAND); - SetAreaMouseMarker(wxPLOT_MARKER_NONE); - break; - } - case wxPLOT_MOUSE_NOTHING : - default : - { - SetAreaMouseCursor(wxCURSOR_CROSS); - SetAreaMouseMarker(wxPLOT_MARKER_NONE); - break; - } - } - - if (send_event) - { - wxPlotEvent event2(wxEVT_PLOT_MOUSE_FUNC_CHANGED, GetId(), this); - event2.SetMouseFunction(func); - (void)DoSendEvent(event2); - } -} - -void wxPlotCtrl::SetAreaMouseMarker( wxPlotMarker_Type type ) -{ - if (type == m_area_mouse_marker) - return; - - wxClientDC dc(m_area); - DrawMouseMarker( &dc, m_area_mouse_marker, m_area->m_mouseRect ); - m_area_mouse_marker = type; - DrawMouseMarker( &dc, m_area_mouse_marker, m_area->m_mouseRect ); + wxClientDC dc(m_area); + DrawMouseMarker(&dc, m_area_mouse_marker, m_area->m_mouseRect); + m_area_mouse_marker = type; + DrawMouseMarker(&dc, m_area_mouse_marker, m_area->m_mouseRect); } void wxPlotCtrl::SetAreaMouseCursor(wxStockCursor cursorid) { - if (cursorid == m_area_mouse_cursorid) - return; + if (cursorid == m_area_mouse_cursorid) { + return; + } - m_area_mouse_cursorid = cursorid; + m_area_mouse_cursorid = cursorid; - if (cursorid == wxCURSOR_HAND) - m_area->SetCursor(s_handCursor); - else if (cursorid == CURSOR_GRAB) - m_area->SetCursor(s_grabCursor); - else - m_area->SetCursor(wxCursor(cursorid)); + if (cursorid == wxCURSOR_HAND) { + m_area->SetCursor(s_handCursor); + } + else if (cursorid == CURSOR_GRAB) { + m_area->SetCursor(s_grabCursor); + } + else { + m_area->SetCursor(wxCursor(cursorid)); + } } -void wxPlotCtrl::OnSize( wxSizeEvent& ) -{ - DoSize(); -} +void wxPlotCtrl::OnSize(wxSizeEvent &) { DoSize(); } void wxPlotCtrl::DoSize(const wxRect &boundingRect) { - if (!m_yAxisScrollbar) return; // we're not created yet + if (!m_yAxisScrollbar) { + return; // we're not created yet + } - m_redraw_type = wxPLOT_REDRAW_BLOCKER; // block OnPaints until done + m_redraw_type = wxPLOT_REDRAW_BLOCKER; // block OnPaints until done - wxSize size; + wxSize size; - if(boundingRect == wxRect(0, 0, 0, 0)) - { - UpdateWindowSize(); - size = GetClientSize(); - } - else - { - size.x = boundingRect.width; - size.y = boundingRect.height; - } + if (boundingRect == wxRect(0, 0, 0, 0)) { + UpdateWindowSize(); + size = GetClientSize(); + } + else { + size.x = boundingRect.width; + size.y = boundingRect.height; + } - int sb_width = m_yAxisScrollbar->GetSize().GetWidth(); + int sb_width = m_yAxisScrollbar->GetSize().GetWidth(); - m_clientRect = wxRect(0, 0, size.x-sb_width, size.y-sb_width); + m_clientRect = wxRect(0, 0, size.x - sb_width, size.y - sb_width); - // scrollbar to right and bottom - m_yAxisScrollbar->SetSize(m_clientRect.width, 0, sb_width, m_clientRect.height ); - m_xAxisScrollbar->SetSize(0, m_clientRect.height, m_clientRect.width, sb_width ); + // scrollbar to right and bottom + m_yAxisScrollbar->SetSize(m_clientRect.width, 0, sb_width, m_clientRect.height); + m_xAxisScrollbar->SetSize(0, m_clientRect.height, m_clientRect.width, sb_width); - // title and label positions, add padding here - wxRect titleRect = m_show_title ? wxRect(m_titleRect).Inflate(m_border) : wxRect(0,0,1,1); - wxRect xLabelRect = m_show_xlabel ? wxRect(m_xLabelRect).Inflate(m_border) : wxRect(0,0,1,1); - wxRect yLabelRect = m_show_ylabel ? wxRect(m_yLabelRect).Inflate(m_border) : wxRect(0,0,1,1); + // title and label positions, add padding here + wxRect titleRect = m_show_title ? wxRect(m_titleRect).Inflate(m_border) : wxRect(0, 0, 1, 1); + wxRect xLabelRect = m_show_xlabel ? wxRect(m_xLabelRect).Inflate(m_border) : wxRect(0, 0, 1, 1); + wxRect yLabelRect = m_show_ylabel ? wxRect(m_yLabelRect).Inflate(m_border) : wxRect(0, 0, 1, 1); - // this is the border around the area, it lets you see about 1 digit extra on axis - int area_border = m_axisFontSize.y/2; + // this is the border around the area, it lets you see about 1 digit extra on axis + int area_border = m_axisFontSize.y / 2; - // use the area_border between top of y-axis and area as bottom border of title - if (m_show_title) titleRect.height -= m_border; + // use the area_border between top of y-axis and area as bottom border of title + if (m_show_title) { + titleRect.height -= m_border; + } - int yaxis_width = GetShowYAxis() ? m_y_axis_text_width : 1; - int xaxis_height = GetShowXAxis() ? m_axisFontSize.y : 0; + int yaxis_width = GetShowYAxis() ? m_y_axis_text_width : 1; + int xaxis_height = GetShowXAxis() ? m_axisFontSize.y : 0; - int area_width = m_clientRect.width - yLabelRect.GetRight() - yaxis_width - 2*area_border; - int area_height = m_clientRect.height - titleRect.GetBottom() - xaxis_height - xLabelRect.height - area_border; + int area_width = m_clientRect.width - yLabelRect.GetRight() - yaxis_width - 2 * area_border; + int area_height = + m_clientRect.height - titleRect.GetBottom() - xaxis_height - xLabelRect.height - area_border; - m_yAxisRect = wxRect(yLabelRect.GetRight(), - titleRect.GetBottom(), - yaxis_width, - area_height + 2*area_border); + m_yAxisRect = wxRect(yLabelRect.GetRight(), titleRect.GetBottom(), yaxis_width, + area_height + 2 * area_border); - m_xAxisRect = wxRect(m_yAxisRect.GetRight(), - m_yAxisRect.GetBottom() - area_border + 1, - area_width + 2*area_border, - xaxis_height); + m_xAxisRect = wxRect(m_yAxisRect.GetRight(), m_yAxisRect.GetBottom() - area_border + 1, + area_width + 2 * area_border, xaxis_height); - m_areaRect = wxRect(m_yAxisRect.GetRight() + area_border, - m_yAxisRect.GetTop() + area_border, - area_width, - area_height); + m_areaRect = wxRect(m_yAxisRect.GetRight() + area_border, m_yAxisRect.GetTop() + area_border, + area_width, area_height); - m_yAxis->SetSize(m_yAxisRect); - m_xAxis->SetSize(m_xAxisRect); - m_area->SetSize(m_areaRect); + m_yAxis->SetSize(m_yAxisRect); + m_xAxis->SetSize(m_xAxisRect); + m_area->SetSize(m_areaRect); - m_titleRect.x = m_areaRect.x + ( m_areaRect.width - m_titleRect.GetWidth() ) / 2; - //m_titleRect.x = m_clientRect.width/2-m_titleRect.GetWidth()/2; center on whole plot - m_titleRect.y = m_border; + m_titleRect.x = m_areaRect.x + (m_areaRect.width - m_titleRect.GetWidth()) / 2; + // m_titleRect.x = m_clientRect.width/2-m_titleRect.GetWidth()/2; center on whole plot + m_titleRect.y = m_border; - m_xLabelRect.x = m_areaRect.x + m_areaRect.width/2 - m_xLabelRect.width/2; - m_xLabelRect.y = m_xAxisRect.GetBottom() + m_border; + m_xLabelRect.x = m_areaRect.x + m_areaRect.width / 2 - m_xLabelRect.width / 2; + m_xLabelRect.y = m_xAxisRect.GetBottom() + m_border; - m_yLabelRect.x = m_border; - m_yLabelRect.y = m_areaRect.y + m_areaRect.height/2 - m_yLabelRect.height/2; + m_yLabelRect.x = m_border; + m_yLabelRect.y = m_areaRect.y + m_areaRect.height / 2 - m_yLabelRect.height / 2; - UpdateWindowSize(); + UpdateWindowSize(); - double zoom_x = m_areaClientRect.width/m_viewRect.m_width; - double zoom_y = m_areaClientRect.height/m_viewRect.m_height; - if (!IsFinite(zoom_x, wxT("Plot zoom is NaN"))) return; - if (!IsFinite(zoom_y, wxT("Plot zoom is NaN"))) return; + double zoom_x = m_areaClientRect.width / m_viewRect.m_width; + double zoom_y = m_areaClientRect.height / m_viewRect.m_height; + if (!IsFinite(zoom_x, wxT("Plot zoom is NaN"))) { + return; + } + if (!IsFinite(zoom_y, wxT("Plot zoom is NaN"))) { + return; + } - if (m_fix_aspectratio) - { - double x = m_viewRect.m_x, y = m_viewRect.m_y; - //FixAspectRatio( &zoom_x, &zoom_y, &m_viewRect.m_x, &m_viewRect.m_y ); - FixAspectRatio(&zoom_x, &zoom_y, &x, &y); - m_viewRect.m_x = x; - m_viewRect.m_y = y; + if (m_fix_aspectratio) { + double x = m_viewRect.m_x, y = m_viewRect.m_y; + // FixAspectRatio( &zoom_x, &zoom_y, &m_viewRect.m_x, &m_viewRect.m_y ); + FixAspectRatio(&zoom_x, &zoom_y, &x, &y); + m_viewRect.m_x = x; + m_viewRect.m_y = y; - m_viewRect.m_width = m_areaClientRect.width/zoom_x; - m_viewRect.m_height = m_areaClientRect.height/zoom_y; - } + m_viewRect.m_width = m_areaClientRect.width / zoom_x; + m_viewRect.m_height = m_areaClientRect.height / zoom_y; + } - m_zoom.m_x = zoom_x; - m_zoom.m_y = zoom_y; + m_zoom.m_x = zoom_x; + m_zoom.m_y = zoom_y; - wxPlotEvent event( wxEVT_PLOT_VIEW_CHANGED, GetId(), this); - event.SetCurve(m_activeCurve, m_active_index); - (void)DoSendEvent( event ); + wxPlotEvent event(wxEVT_PLOT_VIEW_CHANGED, GetId(), this); + event.SetCurve(m_activeCurve, m_active_index); + (void)DoSendEvent(event); - m_redraw_type = 0; - Redraw(wxPLOT_REDRAW_WHOLEPLOT); + m_redraw_type = 0; + Redraw(wxPLOT_REDRAW_WHOLEPLOT); } void wxPlotCtrl::CalcBoundingPlotRect() { - int i, count = m_curves.GetCount(); + int i, count = m_curves.GetCount(); - if (count > 0) - { - bool valid_rect = false; + if (count > 0) { + bool valid_rect = false; - wxRect2DDouble rect = m_curves[0].GetBoundingRect(); + wxRect2DDouble rect = m_curves[0].GetBoundingRect(); - if ( IsFinite(rect.m_x, wxT("left curve boundary is NaN")) && - IsFinite(rect.m_y, wxT("bottom curve boundary is NaN")) && - IsFinite(rect.GetRight(), wxT("right curve boundary is NaN")) && - IsFinite(rect.GetBottom(), wxT("top curve boundary is NaN")) && - (rect.m_width >= 0) && (rect.m_height >= 0) ) - { - valid_rect = true; - } - else - rect = wxRect2DDouble(0, 0, 0, 0); - - for (i=1; i= 0) && (newRect.m_height >= 0)) - { - if (!valid_rect) valid_rect = true; - rect = newRect; - } - } - - // maybe just a single point, center it using default size - bool zeroWidth = false, zeroHeight = false; + if (IsFinite(rect.m_x, wxT("left curve boundary is NaN")) && + IsFinite(rect.m_y, wxT("bottom curve boundary is NaN")) && + IsFinite(rect.GetRight(), wxT("right curve boundary is NaN")) && + IsFinite(rect.GetBottom(), wxT("top curve boundary is NaN")) && (rect.m_width >= 0) && + (rect.m_height >= 0)) { + valid_rect = true; + } + else { + rect = wxRect2DDouble(0, 0, 0, 0); + } - if (rect.m_width == 0.0) - { - zeroWidth = true; - rect.m_x = m_defaultPlotRect.m_x; - rect.m_width = m_defaultPlotRect.m_width; - } - if (rect.m_height == 0.0) - { - zeroHeight = true; - rect.m_y = m_defaultPlotRect.m_y; - rect.m_height = m_defaultPlotRect.m_height; + for (i = 1; i < count; i++) { + wxRect2DDouble curveRect = m_curves[i].GetBoundingRect(); + + if ((curveRect.m_width) <= 0 || (curveRect.m_height <= 0)) { + continue; + } + + wxRect2DDouble newRect; + if (!valid_rect) { + newRect = curveRect; + } + else { + newRect = rect.CreateUnion(curveRect); + } + + if (IsFinite(newRect.m_x, wxT("left curve boundary is NaN")) && + IsFinite(newRect.m_y, wxT("bottom curve boundary is NaN")) && + IsFinite(newRect.GetRight(), wxT("right curve boundary is NaN")) && + IsFinite(newRect.GetBottom(), wxT("top curve boundary is NaN")) && + (newRect.m_width >= 0) && (newRect.m_height >= 0)) { + if (!valid_rect) { + valid_rect = true; } + rect = newRect; + } + } - m_curveBoundingRect = rect; + // maybe just a single point, center it using default size + bool zeroWidth = false, zeroHeight = false; - // add some padding so the edge points can be seen - double w = (!zeroWidth) ? rect.m_width/50.0 : 0.0; - double h = (!zeroHeight) ? rect.m_height/50.0 : 0.0; - m_curveBoundingRect.Inset(-w, -h, -w, -h); + if (rect.m_width == 0.0) { + zeroWidth = true; + rect.m_x = m_defaultPlotRect.m_x; + rect.m_width = m_defaultPlotRect.m_width; + } + if (rect.m_height == 0.0) { + zeroHeight = true; + rect.m_y = m_defaultPlotRect.m_y; + rect.m_height = m_defaultPlotRect.m_height; } - else - m_curveBoundingRect = m_defaultPlotRect; - AdjustScrollBars(); + m_curveBoundingRect = rect; + + // add some padding so the edge points can be seen + double w = (!zeroWidth) ? rect.m_width / 50.0 : 0.0; + double h = (!zeroHeight) ? rect.m_height / 50.0 : 0.0; + m_curveBoundingRect.Inset(-w, -h, -w, -h); + } + else { + m_curveBoundingRect = m_defaultPlotRect; + } + + AdjustScrollBars(); } void wxPlotCtrl::Redraw(int type) { - if (m_batch_count) return; + if (m_batch_count) { + return; + } - if (type & wxPLOT_REDRAW_XAXIS) - { - m_redraw_type |= wxPLOT_REDRAW_XAXIS; - AutoCalcXAxisTicks(); - if (m_correct_ticks == true) - CorrectXAxisTicks(); - CalcXAxisTickPositions(); + if (type & wxPLOT_REDRAW_XAXIS) { + m_redraw_type |= wxPLOT_REDRAW_XAXIS; + AutoCalcXAxisTicks(); + if (m_correct_ticks == true) { + CorrectXAxisTicks(); } - if (type & wxPLOT_REDRAW_YAXIS) - { - m_redraw_type |= wxPLOT_REDRAW_YAXIS; - AutoCalcYAxisTicks(); - if (m_correct_ticks == true) - CorrectYAxisTicks(); - CalcYAxisTickPositions(); + CalcXAxisTickPositions(); + } + if (type & wxPLOT_REDRAW_YAXIS) { + m_redraw_type |= wxPLOT_REDRAW_YAXIS; + AutoCalcYAxisTicks(); + if (m_correct_ticks == true) { + CorrectYAxisTicks(); } + CalcYAxisTickPositions(); + } - if (type & wxPLOT_REDRAW_PLOT) - { - m_redraw_type |= wxPLOT_REDRAW_PLOT; - m_area->Refresh(false); - } + if (type & wxPLOT_REDRAW_PLOT) { + m_redraw_type |= wxPLOT_REDRAW_PLOT; + m_area->Refresh(false); + } - if (type & wxPLOT_REDRAW_XAXIS) - m_xAxis->Refresh(false); - if (type & wxPLOT_REDRAW_YAXIS) - m_yAxis->Refresh(false); + if (type & wxPLOT_REDRAW_XAXIS) { + m_xAxis->Refresh(false); + } + if (type & wxPLOT_REDRAW_YAXIS) { + m_yAxis->Refresh(false); + } - if (type & wxPLOT_REDRAW_WINDOW) - Refresh(); + if (type & wxPLOT_REDRAW_WINDOW) { + Refresh(); + } } -void wxPlotCtrl::DrawAreaWindow( wxDC *dc, const wxRect &rect ) +void wxPlotCtrl::DrawAreaWindow(wxDC *dc, const wxRect &rect) { - wxCHECK_RET(dc, wxT("invalid dc")); + wxCHECK_RET(dc, wxT("invalid dc")); - // GTK doesn't like invalid parameters - wxRect refreshRect = rect; - wxRect clientRect(GetPlotAreaRect()); - refreshRect.Intersect(clientRect); + // GTK doesn't like invalid parameters + wxRect refreshRect = rect; + wxRect clientRect(GetPlotAreaRect()); + refreshRect.Intersect(clientRect); - if ((refreshRect.width == 0) || (refreshRect.height == 0)) return; + if ((refreshRect.width == 0) || (refreshRect.height == 0)) { + return; + } - dc->SetClippingRegion(refreshRect); + dc->SetClippingRegion(refreshRect); - dc->SetBrush( wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID) ); - dc->SetPen( wxPen(GetBorderColour(), m_area_border_width, wxPENSTYLE_SOLID) ); - dc->DrawRectangle(clientRect); + dc->SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); + dc->SetPen(wxPen(GetBorderColour(), m_area_border_width, wxPENSTYLE_SOLID)); + dc->DrawRectangle(clientRect); - DrawTickMarks( dc, refreshRect ); - DrawMarkers( dc, refreshRect ); + DrawTickMarks(dc, refreshRect); + DrawMarkers(dc, refreshRect); - dc->DestroyClippingRegion(); + dc->DestroyClippingRegion(); - int i; - wxPlotCurve *curve; - wxPlotCurve *activeCurve = GetActiveCurve(); - for(i=0; im_plotMarkers.GetCount(); - mdc.SetPen( *wxRED_PEN ); - for (i=0; iGetClientCoordFromPlotX( m_owner->m_plotMarkers.Item(i).m_x ); - int y = m_owner->GetClientCoordFromPlotY( m_owner->m_plotMarkers.Item(i).m_y ); - if (m_owner->GetPlotAreaRect().Inside(x, y)) - { - mdc.DrawLine( x-10, y, x+10, y ); - mdc.DrawLine( x, y-10, x, y+10 ); - } + else { + DrawCurve(dc, activeCurve, GetActiveIndex(), refreshRect); } -*/ - // refresh border - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - dc->SetPen( wxPen(GetBorderColour(), m_area_border_width, wxPENSTYLE_SOLID) ); - dc->DrawRectangle(clientRect); - - dc->SetPen( wxNullPen ); - dc->SetBrush( wxNullBrush ); -} - -void wxPlotCtrl::DrawMouseMarker( wxDC *dc, int type, const wxRect &rect ) -{ - wxCHECK_RET(dc, wxT("invalid window")); - - if ((rect.width == 0) || (rect.height == 0)) - return; + } + + DrawCurveCursor(dc); + DrawKey(dc); + + /* + int count = m_owner->m_plotMarkers.GetCount(); + mdc.SetPen( *wxRED_PEN ); + for (i=0; iGetClientCoordFromPlotX( m_owner->m_plotMarkers.Item(i).m_x ); + int y = m_owner->GetClientCoordFromPlotY( m_owner->m_plotMarkers.Item(i).m_y ); + if (m_owner->GetPlotAreaRect().Inside(x, y)) + { + mdc.DrawLine( x-10, y, x+10, y ); + mdc.DrawLine( x, y-10, x, y+10 ); + } + } + */ + // refresh border + dc->SetBrush(*wxTRANSPARENT_BRUSH); + dc->SetPen(wxPen(GetBorderColour(), m_area_border_width, wxPENSTYLE_SOLID)); + dc->DrawRectangle(clientRect); + + dc->SetPen(wxNullPen); + dc->SetBrush(wxNullBrush); +} + +void wxPlotCtrl::DrawMouseMarker(wxDC *dc, int type, const wxRect &rect) +{ + wxCHECK_RET(dc, wxT("invalid window")); + + if ((rect.width == 0) || (rect.height == 0)) { + return; + } #if wxCHECK_VERSION(2, 9, 0) - wxRasterOperationMode logical_fn = dc->GetLogicalFunction(); + wxRasterOperationMode logical_fn = dc->GetLogicalFunction(); #else - int logical_fn = dc->GetLogicalFunction(); -#endif /* wxCHECK_VERSION */ - dc->SetLogicalFunction( wxINVERT ); - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - dc->SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1, wxPENSTYLE_DOT)); - - switch (type) - { - case wxPLOT_MARKER_NONE : break; - - case wxPLOT_MARKER_RECT : - { - // rects are drawn to width and height - 1, doesn't line up w/ cursor, who cares? - dc->DrawRectangle( rect.x, rect.y, rect.width, rect.height ); - break; - } - case wxPLOT_MARKER_VERT : - { - if (rect.width != 0) - { - int height = GetClientSize().y; - dc->DrawLine(rect.x, 1, rect.x, height-2); - dc->DrawLine(rect.GetRight()+1, 1, rect.GetRight()+1, height-2); - } - break; - } - case wxPLOT_MARKER_HORIZ : - { - if (rect.height != 0) - { - int width = GetClientSize().x; - dc->DrawLine(1, rect.y, width-2, rect.y); - dc->DrawLine(1, rect.GetBottom()+1, width-2, rect.GetBottom()+1); - } - break; - } - default : break; + int logical_fn = dc->GetLogicalFunction(); +#endif /* wxCHECK_VERSION */ + dc->SetLogicalFunction(wxINVERT); + dc->SetBrush(*wxTRANSPARENT_BRUSH); + dc->SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1, wxPENSTYLE_DOT)); + + switch (type) { + case wxPLOT_MARKER_NONE: + break; + + case wxPLOT_MARKER_RECT: { + // rects are drawn to width and height - 1, doesn't line up w/ cursor, who cares? + dc->DrawRectangle(rect.x, rect.y, rect.width, rect.height); + break; + } + case wxPLOT_MARKER_VERT: { + if (rect.width != 0) { + int height = GetClientSize().y; + dc->DrawLine(rect.x, 1, rect.x, height - 2); + dc->DrawLine(rect.GetRight() + 1, 1, rect.GetRight() + 1, height - 2); + } + break; + } + case wxPLOT_MARKER_HORIZ: { + if (rect.height != 0) { + int width = GetClientSize().x; + dc->DrawLine(1, rect.y, width - 2, rect.y); + dc->DrawLine(1, rect.GetBottom() + 1, width - 2, rect.GetBottom() + 1); } + break; + } + default: + break; + } - dc->SetBrush( wxNullBrush ); - dc->SetPen( wxNullPen ); - dc->SetLogicalFunction( logical_fn ); + dc->SetBrush(wxNullBrush); + dc->SetPen(wxNullPen); + dc->SetLogicalFunction(logical_fn); } -void wxPlotCtrl::DrawCrosshairCursor( wxDC *dc, const wxPoint &pos ) +void wxPlotCtrl::DrawCrosshairCursor(wxDC *dc, const wxPoint &pos) { - wxCHECK_RET(dc, wxT("invalid window")); + wxCHECK_RET(dc, wxT("invalid window")); - dc->SetPen(*wxBLACK_PEN); + dc->SetPen(*wxBLACK_PEN); #if wxCHECK_VERSION(2, 9, 0) - wxRasterOperationMode logical_fn = dc->GetLogicalFunction(); + wxRasterOperationMode logical_fn = dc->GetLogicalFunction(); #else - int logical_fn = dc->GetLogicalFunction(); -#endif /* wxCHECK_VERSION */ - dc->SetLogicalFunction( wxINVERT ); + int logical_fn = dc->GetLogicalFunction(); +#endif /* wxCHECK_VERSION */ + dc->SetLogicalFunction(wxINVERT); - dc->CrossHair(pos.x, pos.y); + dc->CrossHair(pos.x, pos.y); - dc->SetPen( wxNullPen ); - dc->SetLogicalFunction( logical_fn ); + dc->SetPen(wxNullPen); + dc->SetLogicalFunction(logical_fn); } -void wxPlotCtrl::DrawDataCurve( wxDC *dc, wxPlotData *curve, int curve_index, const wxRect &rect ) +void wxPlotCtrl::DrawDataCurve(wxDC *dc, wxPlotData *curve, int curve_index, const wxRect &rect) { - wxCHECK_RET(dc && m_dataCurveDrawer && curve && curve->Ok(), wxT("invalid curve")); + wxCHECK_RET(dc && m_dataCurveDrawer && curve && curve->Ok(), wxT("invalid curve")); - m_dataCurveDrawer->SetDCRect(rect); - m_dataCurveDrawer->SetPlotViewRect(m_viewRect); - m_dataCurveDrawer->Draw(dc, curve, curve_index); + m_dataCurveDrawer->SetDCRect(rect); + m_dataCurveDrawer->SetPlotViewRect(m_viewRect); + m_dataCurveDrawer->Draw(dc, curve, curve_index); } -void wxPlotCtrl::DrawCurve( wxDC *dc, wxPlotCurve *curve, int curve_index, const wxRect &rect ) +void wxPlotCtrl::DrawCurve(wxDC *dc, wxPlotCurve *curve, int curve_index, const wxRect &rect) { - wxCHECK_RET(dc && m_curveDrawer && curve && curve->Ok(), wxT("invalid curve")); + wxCHECK_RET(dc && m_curveDrawer && curve && curve->Ok(), wxT("invalid curve")); - m_curveDrawer->SetDCRect(rect); - m_curveDrawer->SetPlotViewRect(m_viewRect); - m_curveDrawer->Draw(dc, curve, curve_index); + m_curveDrawer->SetDCRect(rect); + m_curveDrawer->SetPlotViewRect(m_viewRect); + m_curveDrawer->Draw(dc, curve, curve_index); } void wxPlotCtrl::RedrawDataCurve(int index, int min_index, int max_index) { - if (m_batch_count) return; - - wxCHECK_RET((index>=0)&&(index<(int)m_curves.GetCount()), wxT("invalid curve index")); + if (m_batch_count) { + return; + } - wxPlotData *plotData = GetDataCurve(index); - wxCHECK_RET(plotData, wxT("not a data curve")); + wxCHECK_RET((index >= 0) && (index < (int)m_curves.GetCount()), wxT("invalid curve index")); - int count = plotData->GetCount(); - wxCHECK_RET((min_index<=max_index)&&(min_index>=0)&&(max_index>=0)&&(min_indexGetCount(); + wxCHECK_RET((min_index <= max_index) && (min_index >= 0) && (max_index >= 0) && + (min_index < count) && (max_index < count), + wxT("invalid data index")); - if (plotData->GetIsXOrdered()) - { - double x = plotData->GetXValue(wxMax(min_index-1, 0)); + wxRect rect(m_areaClientRect); + int cursor_size = GetCursorSize(); - if (x > m_viewRect.GetRight()) - return; - else if (x < m_viewRect.m_x) - rect.x = 0; - else - rect.x = GetClientCoordFromPlotX(x) - cursor_size/2 - 1; + if (plotData->GetIsXOrdered()) { + double x = plotData->GetXValue(wxMax(min_index - 1, 0)); - x = plotData->GetXValue(wxMin(max_index+1, (int)plotData->GetCount()-1)); + if (x > m_viewRect.GetRight()) { + return; + } + else if (x < m_viewRect.m_x) { + rect.x = 0; + } + else { + rect.x = GetClientCoordFromPlotX(x) - cursor_size / 2 - 1; + } - if (x < m_viewRect.m_x) - return; - else if (x > m_viewRect.GetRight()) - rect.SetRight(m_areaClientRect.width); - else - rect.SetRight(GetClientCoordFromPlotX(x) + cursor_size/2 + 1); + x = plotData->GetXValue(wxMin(max_index + 1, (int)plotData->GetCount() - 1)); - rect.Intersect(m_areaClientRect); + if (x < m_viewRect.m_x) { + return; + } + else if (x > m_viewRect.GetRight()) { + rect.SetRight(m_areaClientRect.width); + } + else { + rect.SetRight(GetClientCoordFromPlotX(x) + cursor_size / 2 + 1); } - wxMemoryDC mdc; - mdc.SelectObject( m_area->m_bitmap ); - DrawDataCurve( &mdc, plotData, index, rect ); - DrawCurveCursor(&mdc); - wxClientDC dc(m_area); - dc.Blit(rect.x, rect.y, rect.width, rect.height, &mdc, rect.x, rect.y); - mdc.SelectObject( wxNullBitmap ); + rect.Intersect(m_areaClientRect); + } + + wxMemoryDC mdc; + mdc.SelectObject(m_area->m_bitmap); + DrawDataCurve(&mdc, plotData, index, rect); + DrawCurveCursor(&mdc); + wxClientDC dc(m_area); + dc.Blit(rect.x, rect.y, rect.width, rect.height, &mdc, rect.x, rect.y); + mdc.SelectObject(wxNullBitmap); } void wxPlotCtrl::RedrawCurve(int index, double min_x, double max_x) { - if (m_batch_count) return; + if (m_batch_count) { + return; + } - wxCHECK_RET((min_x<=max_x)&&(index>=0)&&(index<(int)m_curves.GetCount()), wxT("invalid curve index")); - wxCHECK_RET(!GetDataCurve(index), wxT("invalid curve")); - wxRect rect(m_areaClientRect); + wxCHECK_RET((min_x <= max_x) && (index >= 0) && (index < (int)m_curves.GetCount()), + wxT("invalid curve index")); + wxCHECK_RET(!GetDataCurve(index), wxT("invalid curve")); + wxRect rect(m_areaClientRect); - if (min_x > m_viewRect.GetRight()) - return; - if (min_x < m_viewRect.m_x) - min_x = m_viewRect.m_x; + if (min_x > m_viewRect.GetRight()) { + return; + } + if (min_x < m_viewRect.m_x) { + min_x = m_viewRect.m_x; + } - rect.x = GetClientCoordFromPlotX(min_x); + rect.x = GetClientCoordFromPlotX(min_x); - if (max_x < m_viewRect.m_x) - return; - if (max_x > m_viewRect.GetRight()) - max_x = m_viewRect.GetRight(); + if (max_x < m_viewRect.m_x) { + return; + } + if (max_x > m_viewRect.GetRight()) { + max_x = m_viewRect.GetRight(); + } - rect.width = GetClientCoordFromPlotX(max_x) - rect.x; + rect.width = GetClientCoordFromPlotX(max_x) - rect.x; - if (rect.width < 1) return; + if (rect.width < 1) { + return; + } - wxMemoryDC mdc; - mdc.SelectObject( m_area->m_bitmap ); - DrawCurve(&mdc, GetCurve(index), index, rect); - DrawCurveCursor(&mdc); - wxClientDC dc(m_area); - dc.Blit(rect.x, rect.y, rect.width, rect.height, &mdc, rect.x, rect.y); - mdc.SelectObject( wxNullBitmap ); + wxMemoryDC mdc; + mdc.SelectObject(m_area->m_bitmap); + DrawCurve(&mdc, GetCurve(index), index, rect); + DrawCurveCursor(&mdc); + wxClientDC dc(m_area); + dc.Blit(rect.x, rect.y, rect.width, rect.height, &mdc, rect.x, rect.y); + mdc.SelectObject(wxNullBitmap); } -void wxPlotCtrl::DrawKey( wxDC *dc ) +void wxPlotCtrl::DrawKey(wxDC *dc) { - wxCHECK_RET(dc && m_keyDrawer, wxT("invalid window")); - if (!GetShowKey() || m_keyString.IsEmpty()) - return; + wxCHECK_RET(dc && m_keyDrawer, wxT("invalid window")); + if (!GetShowKey() || m_keyString.IsEmpty()) { + return; + } - wxRect dcRect(wxPoint(0, 0), GetPlotAreaRect().GetSize()); - m_keyDrawer->SetDCRect(dcRect); - m_keyDrawer->SetPlotViewRect(m_viewRect); - m_keyDrawer->Draw(dc, m_keyString); + wxRect dcRect(wxPoint(0, 0), GetPlotAreaRect().GetSize()); + m_keyDrawer->SetDCRect(dcRect); + m_keyDrawer->SetPlotViewRect(m_viewRect); + m_keyDrawer->Draw(dc, m_keyString); } -void wxPlotCtrl::DrawCurveCursor( wxDC *dc ) +void wxPlotCtrl::DrawCurveCursor(wxDC *dc) { - wxCHECK_RET(dc, wxT("invalid window")); - if (!IsCursorValid()) return; - - m_markerDrawer->SetPlotViewRect(m_viewRect); - m_markerDrawer->SetDCRect(wxRect(wxPoint(0,0), m_area->GetClientSize())); - m_markerDrawer->Draw(dc, m_cursorMarker); - -/* - wxPoint2DDouble cursor = GetCursorPoint(); - - - if ((GetCursorSize() > 0) && - wxPlotRect2DDoubleContains(cursor.m_x, cursor.m_y, m_viewRect)) - { - dc->SetPen( wxPen(GetCursorColour(), 1, wxSOLID) ); - int i = GetClientCoordFromPlotX(cursor.m_x); - int j = GetClientCoordFromPlotY(cursor.m_y); - dc->DrawCircle(i, j, m_cursor_size); - if (m_cursor_size > 2) - { - dc->DrawLine(i - (m_cursor_size - 1), j, i + (m_cursor_size - 1), j); - dc->DrawLine(i, j - (m_cursor_size - 1), i, j + (m_cursor_size - 1)); - } + wxCHECK_RET(dc, wxT("invalid window")); + if (!IsCursorValid()) { + return; + } + + m_markerDrawer->SetPlotViewRect(m_viewRect); + m_markerDrawer->SetDCRect(wxRect(wxPoint(0, 0), m_area->GetClientSize())); + m_markerDrawer->Draw(dc, m_cursorMarker); + + /* + wxPoint2DDouble cursor = GetCursorPoint(); + + + if ((GetCursorSize() > 0) && + wxPlotRect2DDoubleContains(cursor.m_x, cursor.m_y, m_viewRect)) + { + dc->SetPen( wxPen(GetCursorColour(), 1, wxSOLID) ); + int i = GetClientCoordFromPlotX(cursor.m_x); + int j = GetClientCoordFromPlotY(cursor.m_y); + dc->DrawCircle(i, j, m_cursor_size); + if (m_cursor_size > 2) + { + dc->DrawLine(i - (m_cursor_size - 1), j, i + (m_cursor_size - 1), j); + dc->DrawLine(i, j - (m_cursor_size - 1), i, j + (m_cursor_size - 1)); + } + } + */ +} + +void wxPlotCtrl::DrawTickMarks(wxDC *dc, const wxRect &rect) +{ + wxRect clientRect(GetPlotAreaRect()); + dc->SetPen(wxPen(GetGridColour(), 1, wxPENSTYLE_SOLID)); + + int xtick_length = GetDrawGrid() ? clientRect.height : 10; + int ytick_length = GetDrawGrid() ? clientRect.width : 10; + + int tick_pos, i; + // X-axis ticks + int tick_count = m_xAxisTicks.GetCount(); + for (i = 0; i < tick_count; i++) { + tick_pos = m_xAxisTicks[i]; + if (tick_pos < rect.x) { + continue; } -*/ -} - -void wxPlotCtrl::DrawTickMarks( wxDC *dc, const wxRect& rect ) -{ - wxRect clientRect(GetPlotAreaRect()); - dc->SetPen( wxPen(GetGridColour(), 1, wxPENSTYLE_SOLID) ); - - int xtick_length = GetDrawGrid() ? clientRect.height : 10; - int ytick_length = GetDrawGrid() ? clientRect.width : 10; - - int tick_pos, i; - // X-axis ticks - int tick_count = m_xAxisTicks.GetCount(); - for (i=0; i rect.GetRight()) - break; - - dc->DrawLine(tick_pos, clientRect.height, tick_pos, clientRect.height - xtick_length); + else if (tick_pos > rect.GetRight()) { + break; } - // Y-axis ticks - tick_count = m_yAxisTicks.GetCount(); - for (i=0; i rect.GetBottom()) - continue; + dc->DrawLine(tick_pos, clientRect.height, tick_pos, clientRect.height - xtick_length); + } - dc->DrawLine(0, tick_pos, ytick_length, tick_pos); + // Y-axis ticks + tick_count = m_yAxisTicks.GetCount(); + for (i = 0; i < tick_count; i++) { + tick_pos = m_yAxisTicks[i]; + if (tick_pos < rect.y) { + break; + } + else if (tick_pos > rect.GetBottom()) { + continue; } + + dc->DrawLine(0, tick_pos, ytick_length, tick_pos); + } } -void wxPlotCtrl::DrawMarkers( wxDC *dc, const wxRect& rect ) +void wxPlotCtrl::DrawMarkers(wxDC *dc, const wxRect &rect) { - wxCHECK_RET(m_markerDrawer, wxT("Invalid marker drawer")); - m_markerDrawer->SetPlotViewRect(m_viewRect); - m_markerDrawer->SetDCRect(rect); - m_markerDrawer->Draw(dc, m_plotMarkers); + wxCHECK_RET(m_markerDrawer, wxT("Invalid marker drawer")); + m_markerDrawer->SetPlotViewRect(m_viewRect); + m_markerDrawer->SetDCRect(rect); + m_markerDrawer->Draw(dc, m_plotMarkers); } -void wxPlotCtrl::DrawXAxis( wxDC *dc, bool refresh ) +void wxPlotCtrl::DrawXAxis(wxDC *dc, bool refresh) { - wxCHECK_RET(m_xAxisDrawer, wxT("Invalid x axis drawer")); + wxCHECK_RET(m_xAxisDrawer, wxT("Invalid x axis drawer")); - m_xAxisDrawer->SetTickPositions( m_xAxisTicks ); - m_xAxisDrawer->SetTickLabels( m_xAxisTickLabels ); - m_xAxisDrawer->SetPlotViewRect(m_viewRect); - wxSize clientSize = m_xAxisRect.GetSize(); - m_xAxisDrawer->SetDCRect(wxRect(wxPoint(0,0),clientSize)); - m_xAxisDrawer->Draw(dc, refresh); + m_xAxisDrawer->SetTickPositions(m_xAxisTicks); + m_xAxisDrawer->SetTickLabels(m_xAxisTickLabels); + m_xAxisDrawer->SetPlotViewRect(m_viewRect); + wxSize clientSize = m_xAxisRect.GetSize(); + m_xAxisDrawer->SetDCRect(wxRect(wxPoint(0, 0), clientSize)); + m_xAxisDrawer->Draw(dc, refresh); } -void wxPlotCtrl::DrawYAxis( wxDC *dc, bool refresh ) +void wxPlotCtrl::DrawYAxis(wxDC *dc, bool refresh) { - wxCHECK_RET(m_yAxisDrawer, wxT("Invalid y axis drawer")); + wxCHECK_RET(m_yAxisDrawer, wxT("Invalid y axis drawer")); - m_yAxisDrawer->SetTickPositions( m_yAxisTicks ); - m_yAxisDrawer->SetTickLabels( m_yAxisTickLabels ); - m_yAxisDrawer->SetPlotViewRect(m_viewRect); - wxSize clientSize = m_yAxisRect.GetSize(); - m_yAxisDrawer->SetDCRect(wxRect(wxPoint(0,0),clientSize)); - m_yAxisDrawer->Draw(dc, refresh); + m_yAxisDrawer->SetTickPositions(m_yAxisTicks); + m_yAxisDrawer->SetTickLabels(m_yAxisTickLabels); + m_yAxisDrawer->SetPlotViewRect(m_viewRect); + wxSize clientSize = m_yAxisRect.GetSize(); + m_yAxisDrawer->SetDCRect(wxRect(wxPoint(0, 0), clientSize)); + m_yAxisDrawer->Draw(dc, refresh); } -wxRect ScaleRect(const wxRect& rect, double x_scale, double y_scale) +wxRect ScaleRect(const wxRect &rect, double x_scale, double y_scale) { - return wxRect( int(rect.x*x_scale+0.5), int(rect.y*y_scale+0.5), - int(rect.width*x_scale+0.5), int(rect.height*y_scale+0.5) ); + return wxRect(int(rect.x * x_scale + 0.5), int(rect.y * y_scale + 0.5), + int(rect.width * x_scale + 0.5), int(rect.height * y_scale + 0.5)); } -void wxPlotCtrl::DrawWholePlot( wxDC *dc, const wxRect &boundingRect, int dpi ) +void wxPlotCtrl::DrawWholePlot(wxDC *dc, const wxRect &boundingRect, int dpi) { - wxCHECK_RET(dc, wxT("invalid dc")); - wxCHECK_RET(dpi > 0, wxT("Invalid dpi for plot drawing")); + wxCHECK_RET(dc, wxT("invalid dc")); + wxCHECK_RET(dpi > 0, wxT("Invalid dpi for plot drawing")); - wxSize clientSize = GetClientSize(); - int sb_width = m_yAxisScrollbar->GetSize().GetWidth(); - clientSize.x -= sb_width; - clientSize.y -= sb_width; + wxSize clientSize = GetClientSize(); + int sb_width = m_yAxisScrollbar->GetSize().GetWidth(); + clientSize.x -= sb_width; + clientSize.y -= sb_width; - //set font scale so 1pt = 1pixel at 72dpi - double fontScale = (double)dpi / 72.0; - //one pixel wide line equals (m_pen_print_width) millimeters wide - double penScale = (m_pen_print_width / 25.4) * dpi; + // set font scale so 1pt = 1pixel at 72dpi + double fontScale = (double)dpi / 72.0; + // one pixel wide line equals (m_pen_print_width) millimeters wide + double penScale = (m_pen_print_width / 25.4) * dpi; - //save old values - wxFont oldAxisLabelFont = GetAxisLabelFont(); - wxFont oldPlotTitleFont = GetPlotTitleFont(); - int old_area_border_width = m_area_border_width; - int old_border = m_border; - int old_cursor_size = m_cursorMarker.GetSize().x; - wxPoint2DDouble old_zoom = m_zoom; - wxRect2DDouble old_view = m_viewRect; + // save old values + wxFont oldAxisLabelFont = GetAxisLabelFont(); + wxFont oldPlotTitleFont = GetPlotTitleFont(); + int old_area_border_width = m_area_border_width; + int old_border = m_border; + int old_cursor_size = m_cursorMarker.GetSize().x; + wxPoint2DDouble old_zoom = m_zoom; + wxRect2DDouble old_view = m_viewRect; - //resize border and border pen - m_area_border_width = RINT(m_area_border_width * penScale); - m_border = RINT(m_border * penScale); + // resize border and border pen + m_area_border_width = RINT(m_area_border_width * penScale); + m_border = RINT(m_border * penScale); - //resize the curve cursor - m_cursorMarker.SetSize(wxSize(int(old_cursor_size * penScale), int(old_cursor_size * penScale))); + // resize the curve cursor + m_cursorMarker.SetSize(wxSize(int(old_cursor_size * penScale), int(old_cursor_size * penScale))); - //resize the fonts - wxFont axisLabelFont = GetAxisLabelFont(); - axisLabelFont.SetPointSize( wxMax(2, RINT(axisLabelFont.GetPointSize() * fontScale)) ); - SetAxisLabelFont( axisLabelFont ); + // resize the fonts + wxFont axisLabelFont = GetAxisLabelFont(); + axisLabelFont.SetPointSize(wxMax(2, RINT(axisLabelFont.GetPointSize() * fontScale))); + SetAxisLabelFont(axisLabelFont); - wxFont plotTitleFont = GetPlotTitleFont(); - plotTitleFont.SetPointSize( wxMax(2, RINT(plotTitleFont.GetPointSize() * fontScale)) ); - SetPlotTitleFont( plotTitleFont ); + wxFont plotTitleFont = GetPlotTitleFont(); + plotTitleFont.SetPointSize(wxMax(2, RINT(plotTitleFont.GetPointSize() * fontScale))); + SetPlotTitleFont(plotTitleFont); - //reload the original zoom and view rect in case it was changed by any of the font changes - m_zoom = old_zoom; - m_viewRect = old_view; + // reload the original zoom and view rect in case it was changed by any of the font changes + m_zoom = old_zoom; + m_viewRect = old_view; - //resize all window component rects to the bounding rect - DoSize( boundingRect ); - //AutoCalcTicks(); // don't reset ticks since it might not be WYSIWYG + // resize all window component rects to the bounding rect + DoSize(boundingRect); + // AutoCalcTicks(); // don't reset ticks since it might not be WYSIWYG - //draw all components to the provided dc - dc->SetDeviceOrigin(long(boundingRect.x+m_xAxisRect.GetLeft()), - long(boundingRect.y+m_xAxisRect.GetTop())); - CalcXAxisTickPositions(); - DrawXAxis(dc, false); + // draw all components to the provided dc + dc->SetDeviceOrigin(long(boundingRect.x + m_xAxisRect.GetLeft()), + long(boundingRect.y + m_xAxisRect.GetTop())); + CalcXAxisTickPositions(); + DrawXAxis(dc, false); - dc->SetDeviceOrigin(long(boundingRect.x+m_yAxisRect.GetLeft()), - long(boundingRect.y+m_yAxisRect.GetTop())); - CalcYAxisTickPositions(); - DrawYAxis(dc, false); + dc->SetDeviceOrigin(long(boundingRect.x + m_yAxisRect.GetLeft()), + long(boundingRect.y + m_yAxisRect.GetTop())); + CalcYAxisTickPositions(); + DrawYAxis(dc, false); - dc->SetDeviceOrigin(long(boundingRect.x+m_areaRect.GetLeft()), - long(boundingRect.y+m_areaRect.GetTop())); - DrawAreaWindow(dc, m_areaClientRect); + dc->SetDeviceOrigin(long(boundingRect.x + m_areaRect.GetLeft()), + long(boundingRect.y + m_areaRect.GetTop())); + DrawAreaWindow(dc, m_areaClientRect); - dc->SetDeviceOrigin(boundingRect.x, boundingRect.y); - DrawPlotCtrl(dc); + dc->SetDeviceOrigin(boundingRect.x, boundingRect.y); + DrawPlotCtrl(dc); - //restore old values + // restore old values - m_area_border_width = old_area_border_width; - m_border = old_border; - m_cursorMarker.SetSize(wxSize(old_cursor_size, old_cursor_size)); + m_area_border_width = old_area_border_width; + m_border = old_border; + m_cursorMarker.SetSize(wxSize(old_cursor_size, old_cursor_size)); - SetAxisLabelFont( oldAxisLabelFont ); - SetPlotTitleFont( oldPlotTitleFont ); - m_zoom = old_zoom; - m_viewRect = old_view; + SetAxisLabelFont(oldAxisLabelFont); + SetPlotTitleFont(oldPlotTitleFont); + m_zoom = old_zoom; + m_viewRect = old_view; - //update to window instead of printer - UpdateWindowSize(); - Redraw(wxPLOT_REDRAW_WHOLEPLOT); // recalc ticks for this window + // update to window instead of printer + UpdateWindowSize(); + Redraw(wxPLOT_REDRAW_WHOLEPLOT); // recalc ticks for this window } // ---------------------------------------------------------------------------- @@ -3091,1021 +3179,1163 @@ void wxPlotCtrl::DrawWholePlot( wxDC *dc, const wxRect &boundingRect, int dpi ) void wxPlotCtrl::DoAutoCalcTicks(bool x_axis) { - double start = 0.0, end = 1.0; - int i, n, window = 100; - - double *tick_step = NULL; - int *tick_count = NULL; - wxString *tickFormat = NULL; - - if (x_axis) - { - tick_step = &m_xAxisTick_step; - tick_count = &m_xAxisTick_count; - tickFormat = &m_xAxisTickFormat; - - window = GetPlotAreaRect().width; - m_xAxisTicks.Clear(); // kill it in case something goes wrong - start = m_viewRect.GetLeft(); - end = m_viewRect.GetRight(); - *tick_count = window/(m_axisFontSize.x*10); - } - else - { - tick_step = &m_yAxisTick_step; - tick_count = &m_yAxisTick_count; - tickFormat = &m_yAxisTickFormat; + double start = 0.0, end = 1.0; + int i, n, window = 100; + + double *tick_step = NULL; + int *tick_count = NULL; + wxString *tickFormat = NULL; + + if (x_axis) { + tick_step = &m_xAxisTick_step; + tick_count = &m_xAxisTick_count; + tickFormat = &m_xAxisTickFormat; + + window = GetPlotAreaRect().width; + m_xAxisTicks.Clear(); // kill it in case something goes wrong + start = m_viewRect.GetLeft(); + end = m_viewRect.GetRight(); + *tick_count = window / (m_axisFontSize.x * 10); + } + else { + tick_step = &m_yAxisTick_step; + tick_count = &m_yAxisTick_count; + tickFormat = &m_yAxisTickFormat; + + window = GetPlotAreaRect().height; + m_yAxisTicks.Clear(); + start = m_viewRect.GetTop(); + end = m_viewRect.GetBottom(); + double tick_count_scale = window / (m_axisFontSize.y * 2.0) > 2.0 ? 2.0 : 1.5; + *tick_count = int(window / (m_axisFontSize.y * tick_count_scale) + 0.5); + } + + if (window < 5) { + return; // FIXME + } + + if (!IsFinite(start, wxT("axis range is not finite")) || + !IsFinite(end, wxT("axis range is not finite"))) { + *tick_count = 0; + return; + } + + double range = end - start; + double max = fabs(start) > fabs(end) ? fabs(start) : fabs(end); + double min = fabs(start) < fabs(end) ? fabs(start) : fabs(end); + bool exponential = (min >= m_min_exponential) || (max < 1.0 / m_min_exponential) ? true : false; + int places = exponential ? 1 : int(floor(fabs(log10(max)))); + + if (!IsFinite(range, wxT("axis range is not finite")) || + !IsFinite(min, wxT("axis range is not finite")) || + !IsFinite(max, wxT("axis range is not finite"))) { + *tick_count = 0; + return; + } - window = GetPlotAreaRect().height; - m_yAxisTicks.Clear(); - start = m_viewRect.GetTop(); - end = m_viewRect.GetBottom(); - double tick_count_scale = window/(m_axisFontSize.y*2.0) > 2.0 ? 2.0 : 1.5; - *tick_count = int(window/(m_axisFontSize.y*tick_count_scale) + 0.5); + *tick_step = 1.0; + int int_log_range = int(log10(range)); + if (int_log_range > 0) { + for (i = 0; i < int_log_range; i++) { + (*tick_step) *= 10; } - - if (window < 5) return; // FIXME - - if (!IsFinite(start, wxT("axis range is not finite")) || - !IsFinite(end, wxT("axis range is not finite")) ) - { - *tick_count = 0; - return; + } + else if (int_log_range < 0) { + for (i = 0; i < -int_log_range; i++) { + (*tick_step) /= 10; } - - double range = end - start; - double max = fabs(start) > fabs(end) ? fabs(start) : fabs(end); - double min = fabs(start) < fabs(end) ? fabs(start) : fabs(end); - bool exponential = (min >= m_min_exponential) || (max < 1.0/m_min_exponential) ? true : false; - int places = exponential ? 1 : int(floor(fabs(log10(max)))); - - if (!IsFinite(range, wxT("axis range is not finite")) || - !IsFinite(min, wxT("axis range is not finite")) || - !IsFinite(max, wxT("axis range is not finite")) ) - { - *tick_count = 0; - return; + } + + double stepsizes[TIC_STEPS] = {.1, .2, .5}; + double step10 = (*tick_step) / 10.0; + int sigFigs = 0; + int digits = 0; + + for (n = 0; n < 4; n++) { + for (i = 0; i < TIC_STEPS; i++) { + *tick_step = step10 * stepsizes[i]; + + if (exponential) { + sigFigs = labs(int(log10(max)) - int(log10(*tick_step))); + } + else { + sigFigs = (*tick_step) >= 1.0 ? 0 : int(ceil(-log10(*tick_step))); + } + + if (x_axis) { + digits = 1 + places + (sigFigs > 0 ? 1 + sigFigs : 0) + (exponential ? 4 : 0); + *tick_count = int(double(window) / double((digits + 3) * m_axisFontSize.x) + 0.5); + } + + if ((range / (*tick_step)) <= (*tick_count)) { + break; + } } - - *tick_step = 1.0; - int int_log_range = int( log10(range) ); - if (int_log_range > 0) { for (i=0; i < int_log_range; i++) (*tick_step) *= 10; } - else if (int_log_range < 0) { for (i=0; i < -int_log_range; i++) (*tick_step) /= 10; } - - double stepsizes[TIC_STEPS] = { .1, .2, .5 }; - double step10 = (*tick_step) / 10.0; - int sigFigs = 0; - int digits = 0; - - for (n=0; n<4; n++) - { - for (i=0; i= 1.0 ? 0 : int(ceil(-log10(*tick_step))); - - if (x_axis) - { - digits = 1 + places + (sigFigs > 0 ? 1+sigFigs : 0) + (exponential ? 4 : 0); - *tick_count = int(double(window)/double((digits+3)*m_axisFontSize.x) + 0.5); - } - - if ((range/(*tick_step)) <= (*tick_count)) break; - } - if ((range/(*tick_step)) <= (*tick_count)) break; - step10 *= 10.0; + if ((range / (*tick_step)) <= (*tick_count)) { + break; } + step10 *= 10.0; + } - //if (!x_axis) wxPrintf(wxT("Ticks %d %lf, %d\n"), n, *tick_step, *tick_count); + // if (!x_axis) wxPrintf(wxT("Ticks %d %lf, %d\n"), n, *tick_step, *tick_count); - if (sigFigs > 9) sigFigs = 9; // FIXME + if (sigFigs > 9) { + sigFigs = 9; // FIXME + } - if (exponential) tickFormat->Printf( wxT("%%.%dle"), sigFigs ); - else tickFormat->Printf( wxT("%%.%dlf"), sigFigs ); + if (exponential) { + tickFormat->Printf(wxT("%%.%dle"), sigFigs); + } + else { + tickFormat->Printf(wxT("%%.%dlf"), sigFigs); + } - *tick_count = int(ceil(range/(*tick_step))) + 1; + *tick_count = int(ceil(range / (*tick_step))) + 1; -// note : first_tick = ceil(start / tick_step) * tick_step; + // note : first_tick = ceil(start / tick_step) * tick_step; } void wxPlotCtrl::CorrectXAxisTicks() { - double start = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; - wxString label; - label.Printf( m_xAxisTickFormat.c_str(), start); - if (label.ToDouble( &start )) - { - double x = GetClientCoordFromPlotX( start ); - double zoom_x = (GetClientCoordFromPlotX(start+m_xAxisTick_step)-x)/m_xAxisTick_step; - double origin_x = start - x/zoom_x; - BeginBatch(); - if (!SetZoom( zoom_x, m_zoom.m_y, origin_x, m_viewRect.GetTop(), true )) - m_xAxisTick_count = 0; // oops - - EndBatch(false); // don't draw just block + double start = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; + wxString label; + label.Printf(m_xAxisTickFormat.c_str(), start); + if (label.ToDouble(&start)) { + double x = GetClientCoordFromPlotX(start); + double zoom_x = (GetClientCoordFromPlotX(start + m_xAxisTick_step) - x) / m_xAxisTick_step; + double origin_x = start - x / zoom_x; + BeginBatch(); + if (!SetZoom(zoom_x, m_zoom.m_y, origin_x, m_viewRect.GetTop(), true)) { + m_xAxisTick_count = 0; // oops } + + EndBatch(false); // don't draw just block + } } void wxPlotCtrl::CorrectYAxisTicks() { - double start = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; - wxString label; - label.Printf( m_yAxisTickFormat.c_str(), start); - if (label.ToDouble( &start )) - { - double y = GetClientCoordFromPlotY( start ); - double zoom_y = (y-GetClientCoordFromPlotY(start+m_yAxisTick_step))/m_yAxisTick_step; - double origin_y = start - (GetPlotAreaRect().height - y)/zoom_y; - BeginBatch(); - if (!SetZoom( m_zoom.m_x, zoom_y, m_viewRect.GetLeft(), origin_y, true )) - m_yAxisTick_count = 0; // oops - - EndBatch(false); + double start = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; + wxString label; + label.Printf(m_yAxisTickFormat.c_str(), start); + if (label.ToDouble(&start)) { + double y = GetClientCoordFromPlotY(start); + double zoom_y = (y - GetClientCoordFromPlotY(start + m_yAxisTick_step)) / m_yAxisTick_step; + double origin_y = start - (GetPlotAreaRect().height - y) / zoom_y; + BeginBatch(); + if (!SetZoom(m_zoom.m_x, zoom_y, m_viewRect.GetLeft(), origin_y, true)) { + m_yAxisTick_count = 0; // oops } + + EndBatch(false); + } } void wxPlotCtrl::CalcXAxisTickPositions() { - double current = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; - m_xAxisTicks.Clear(); - m_xAxisTickLabels.Clear(); - int i, x, windowWidth = GetPlotAreaRect().width; - for (i=0; i= -1) && (x < windowWidth+2)) - { - m_xAxisTicks.Add(x); - m_xAxisTickLabels.Add(wxString::Format(m_xAxisTickFormat.c_str(), current)); - } + x = GetClientCoordFromPlotX(current); - current += m_xAxisTick_step; + if ((x >= -1) && (x < windowWidth + 2)) { + m_xAxisTicks.Add(x); + m_xAxisTickLabels.Add(wxString::Format(m_xAxisTickFormat.c_str(), current)); } + + current += m_xAxisTick_step; + } } void wxPlotCtrl::CalcYAxisTickPositions() { - double current = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; - m_yAxisTicks.Clear(); - m_yAxisTickLabels.Clear(); - int i, y, windowWidth = GetPlotAreaRect().height; - for (i=0; i= -1) && (y < windowWidth+2)) - { - m_yAxisTicks.Add(y); - m_yAxisTickLabels.Add(wxString::Format(m_yAxisTickFormat.c_str(), current)); - } + y = GetClientCoordFromPlotY(current); - current += m_yAxisTick_step; + if ((y >= -1) && (y < windowWidth + 2)) { + m_yAxisTicks.Add(y); + m_yAxisTickLabels.Add(wxString::Format(m_yAxisTickFormat.c_str(), current)); } + + current += m_yAxisTick_step; + } } // ---------------------------------------------------------------------------- // Event processing // ---------------------------------------------------------------------------- -void wxPlotCtrl::ProcessAreaEVT_MOUSE_EVENTS( wxMouseEvent &event ) +void wxPlotCtrl::ProcessAreaEVT_MOUSE_EVENTS(wxMouseEvent &event) { - wxPoint& m_mousePt = m_area->m_mousePt; - wxRect& m_mouseRect = m_area->m_mouseRect; + wxPoint &m_mousePt = m_area->m_mousePt; + wxRect &m_mouseRect = m_area->m_mouseRect; - wxPoint lastMousePt = m_mousePt; - m_mousePt = event.GetPosition(); + wxPoint lastMousePt = m_mousePt; + m_mousePt = event.GetPosition(); - if (event.ButtonDown() && IsTextCtrlShown()) - { - HideTextCtrl(true, true); - return; + if (event.ButtonDown() && IsTextCtrlShown()) { + HideTextCtrl(true, true); + return; + } + + if (GetGreedyFocus() && (FindFocus() != m_area)) { + m_area->SetFocus(); + } + + double plotX = GetPlotCoordFromClientX(m_mousePt.x), + plotY = GetPlotCoordFromClientY(m_mousePt.y); + + wxClientDC dc(m_area); + + // Mouse motion + if (lastMousePt != m_area->m_mousePt) { + wxPlotEvent evt_motion(wxEVT_PLOT_MOUSE_MOTION, GetId(), this); + evt_motion.SetPosition(plotX, plotY); + (void)DoSendEvent(evt_motion); + + // Draw the crosshair cursor + if (GetCrossHairCursor()) { + if (!event.Entering() || m_area->HasCapture()) { + DrawCrosshairCursor(&dc, lastMousePt); + } + if (!event.Leaving() || m_area->HasCapture()) { + DrawCrosshairCursor(&dc, m_mousePt); + } } + } - if (GetGreedyFocus() && (FindFocus() != m_area)) - m_area->SetFocus(); + // Wheel scrolling up and down + if (event.GetWheelRotation() != 0) { + double dir = event.GetWheelRotation() > 0 ? 0.25 : -0.25; + SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() + dir * m_viewRect.m_height, true); + } - double plotX = GetPlotCoordFromClientX(m_mousePt.x), - plotY = GetPlotCoordFromClientY(m_mousePt.y); + int active_index = GetActiveIndex(); - wxClientDC dc(m_area); - - // Mouse motion - if (lastMousePt != m_area->m_mousePt) - { - wxPlotEvent evt_motion(wxEVT_PLOT_MOUSE_MOTION, GetId(), this); - evt_motion.SetPosition( plotX, plotY ); - (void)DoSendEvent( evt_motion ); - - // Draw the crosshair cursor - if (GetCrossHairCursor()) - { - if (!event.Entering() || m_area->HasCapture()) - DrawCrosshairCursor( &dc, lastMousePt ); - if (!event.Leaving() || m_area->HasCapture()) - DrawCrosshairCursor( &dc, m_mousePt ); - } + // Initial Left down selection + if (event.LeftDown() || event.LeftDClick()) { + if (FindFocus() != m_area) { // fixme MSW focus problems + m_area->SetFocus(); } - // Wheel scrolling up and down - if (event.GetWheelRotation() != 0) - { - double dir = event.GetWheelRotation() > 0 ? 0.25 : -0.25; - SetOrigin( m_viewRect.GetLeft(), - m_viewRect.GetTop() + dir*m_viewRect.m_height, true); + if (m_area_mouse_cursorid == wxCURSOR_HAND) { + SetAreaMouseCursor(CURSOR_GRAB); } - int active_index = GetActiveIndex(); + // send a click or doubleclick event + wxPlotEvent click_event(event.ButtonDClick() ? wxEVT_PLOT_DOUBLECLICKED : wxEVT_PLOT_CLICKED, + GetId(), this); + click_event.SetPosition(plotX, plotY); + (void)DoSendEvent(click_event); - // Initial Left down selection - if (event.LeftDown() || event.LeftDClick()) - { - if (FindFocus() != m_area) // fixme MSW focus problems - m_area->SetFocus(); - - if (m_area_mouse_cursorid == wxCURSOR_HAND) - SetAreaMouseCursor(CURSOR_GRAB); - - // send a click or doubleclick event - wxPlotEvent click_event( event.ButtonDClick() ? wxEVT_PLOT_DOUBLECLICKED : wxEVT_PLOT_CLICKED, - GetId(), this ); - click_event.SetPosition( plotX, plotY ); - (void)DoSendEvent( click_event ); - - if (!event.ButtonDClick()) - m_mouseRect = wxRect(m_mousePt, wxSize(0, 0)); - - int data_index = -1; - int curve_index = -1; - - wxPoint2DDouble dpt(2.0/m_zoom.m_x, 2.0/m_zoom.m_y); - wxPoint2DDouble curvePt; - - if (FindCurve(wxPoint2DDouble(plotX, plotY), dpt, curve_index, data_index, &curvePt)) - { - wxPlotCurve *plotCurve = GetCurve(curve_index); - wxPlotData *plotData = wxDynamicCast(plotCurve, wxPlotData); - - if (plotCurve) - { - wxPlotEvent pt_click_event( event.ButtonDClick() ? wxEVT_PLOT_POINT_DOUBLECLICKED : wxEVT_PLOT_POINT_CLICKED, - GetId(), this ); - pt_click_event.SetPosition( curvePt.m_x, curvePt.m_y ); - pt_click_event.SetCurve( plotCurve, curve_index ); - pt_click_event.SetCurveDataIndex(data_index); - (void)DoSendEvent( pt_click_event ); - - // send curve selection switched event - if (curve_index != GetActiveIndex()) - SetActiveIndex( curve_index, true ); - - if (!event.LeftDClick() && (m_area_mouse_func == wxPLOT_MOUSE_SELECT)) - { - if (plotData) - SelectDataRange(curve_index, wxRangeInt(data_index,data_index), true); - else - SelectXRange(curve_index, wxRangeDouble(curvePt.m_x,curvePt.m_x), true); - } - else if (!event.LeftDClick() && (m_area_mouse_func == wxPLOT_MOUSE_DESELECT)) - { - if (plotData) - DeselectDataRange(curve_index, wxRangeInt(data_index,data_index), true); - else - DeselectXRange(curve_index, wxRangeDouble(curvePt.m_x,curvePt.m_x), true); - } - else - { - if (plotData) - SetCursorDataIndex(curve_index, data_index, true); - else - SetCursorXPoint(curve_index, curvePt.m_x, true); - } - - return; - } - } + if (!event.ButtonDClick()) { + m_mouseRect = wxRect(m_mousePt, wxSize(0, 0)); } - // Finished marking rectangle or scrolling, perhaps - else if (event.LeftUp()) - { - SetCaptureWindow(NULL); - if (m_area_mouse_cursorid == CURSOR_GRAB) - SetAreaMouseCursor(wxCURSOR_HAND); + int data_index = -1; + int curve_index = -1; - StopMouseTimer(); + wxPoint2DDouble dpt(2.0 / m_zoom.m_x, 2.0 / m_zoom.m_y); + wxPoint2DDouble curvePt; - if (m_mouseRect == wxRect(0,0,0,0)) - return; + if (FindCurve(wxPoint2DDouble(plotX, plotY), dpt, curve_index, data_index, &curvePt)) { + wxPlotCurve *plotCurve = GetCurve(curve_index); + wxPlotData *plotData = wxDynamicCast(plotCurve, wxPlotData); - wxRect rightedRect = m_mouseRect; + if (plotCurve) { + wxPlotEvent pt_click_event(event.ButtonDClick() ? wxEVT_PLOT_POINT_DOUBLECLICKED + : wxEVT_PLOT_POINT_CLICKED, + GetId(), this); + pt_click_event.SetPosition(curvePt.m_x, curvePt.m_y); + pt_click_event.SetCurve(plotCurve, curve_index); + pt_click_event.SetCurveDataIndex(data_index); + (void)DoSendEvent(pt_click_event); - // rightedRect always goes from upper-left to lower-right - // don't fix m_mouseRect since redrawing will be off - if (rightedRect.width < 0) - { - rightedRect.x += rightedRect.width; - rightedRect.width = -rightedRect.width; - } - if (rightedRect.height < 0) - { - rightedRect.y += rightedRect.height; - rightedRect.height = -rightedRect.height; + // send curve selection switched event + if (curve_index != GetActiveIndex()) { + SetActiveIndex(curve_index, true); } - // Zoom into image - if (m_area_mouse_func == wxPLOT_MOUSE_ZOOM) - { - if ((m_area_mouse_marker == wxPLOT_MARKER_RECT) && - ((rightedRect.width > 10) && (rightedRect.height > 10))) - SetZoom( rightedRect, true ); - else if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && - (rightedRect.width > 10) ) - SetZoom( wxRect(rightedRect.x, 0, rightedRect.width, m_areaClientRect.height), true ); - else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && - (rightedRect.height > 10) ) - SetZoom( wxRect(0, rightedRect.y, m_areaClientRect.width, rightedRect.height ), true ); - else - DrawMouseMarker( &dc, m_area_mouse_marker, m_mouseRect ); + if (!event.LeftDClick() && (m_area_mouse_func == wxPLOT_MOUSE_SELECT)) { + if (plotData) { + SelectDataRange(curve_index, wxRangeInt(data_index, data_index), true); + } + else { + SelectXRange(curve_index, wxRangeDouble(curvePt.m_x, curvePt.m_x), true); + } } - // Select a range of points - else if ((m_area_mouse_func == wxPLOT_MOUSE_SELECT) && (active_index >= 0)) - { - BeginBatch(); // if you select nothing, you don't get a refresh - - wxRect2DDouble plotRect = GetPlotRectFromClientRect(rightedRect); - - if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (plotRect.m_width > 0)) - SelectXRange(active_index, wxRangeDouble(plotRect.m_x, plotRect.GetRight()), true ); - else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (plotRect.m_height > 0)) - SelectYRange(active_index, wxRangeDouble(plotRect.m_y, plotRect.GetBottom()), true ); - else if ((plotRect.m_width > 0) || (plotRect.m_height > 0)) - SelectRectangle(active_index, plotRect, true ); - - m_mouseRect = wxRect(0,0,0,0); - EndBatch(); + else if (!event.LeftDClick() && (m_area_mouse_func == wxPLOT_MOUSE_DESELECT)) { + if (plotData) { + DeselectDataRange(curve_index, wxRangeInt(data_index, data_index), true); + } + else { + DeselectXRange(curve_index, wxRangeDouble(curvePt.m_x, curvePt.m_x), true); + } } - // Deselect a range of points - else if ((m_area_mouse_func == wxPLOT_MOUSE_DESELECT) && (active_index >= 0)) - { - BeginBatch(); - - wxRect2DDouble plotRect = GetPlotRectFromClientRect(rightedRect); - - if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (plotRect.m_width > 0)) - DeselectXRange(active_index, wxRangeDouble(plotRect.m_x, plotRect.GetRight()), true ); - else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (plotRect.m_height > 0)) - DeselectYRange(active_index, wxRangeDouble(plotRect.m_y, plotRect.GetBottom()), true ); - else if ((plotRect.m_width > 0) || (plotRect.m_height > 0)) - DeselectRectangle(active_index, plotRect, true ); - - m_mouseRect = wxRect(0,0,0,0); - EndBatch(); - } - // Nothing to do - erase the rect - else - { - DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); + else { + if (plotData) { + SetCursorDataIndex(curve_index, data_index, true); + } + else { + SetCursorXPoint(curve_index, curvePt.m_x, true); + } } - m_mouseRect = wxRect(0,0,0,0); return; + } } - // Marking the rectangle or panning around - else if ( event.LeftIsDown() && event.Dragging() ) - { - SetCaptureWindow(m_area); + } + // Finished marking rectangle or scrolling, perhaps + else if (event.LeftUp()) { + SetCaptureWindow(NULL); - if (m_area_mouse_cursorid == wxCURSOR_HAND) - SetAreaMouseCursor(CURSOR_GRAB); - - // Move the origin - if (m_area_mouse_func == wxPLOT_MOUSE_PAN) - { -#if wxCHECK_VERSION(2,7,0) - if (!m_areaClientRect.Contains(event.GetPosition())) -#else - if (!m_areaClientRect.Inside(event.GetPosition())) -#endif - { - StartMouseTimer(ID_AREA_TIMER); - } + if (m_area_mouse_cursorid == CURSOR_GRAB) { + SetAreaMouseCursor(wxCURSOR_HAND); + } - m_mouseRect = wxRect(0,0,0,0); // no marker + StopMouseTimer(); - double dx = m_mousePt.x - lastMousePt.x; - double dy = m_mousePt.y - lastMousePt.y; - SetOrigin(m_viewRect.GetLeft() - dx/m_zoom.m_x, - m_viewRect.GetTop() + dy/m_zoom.m_y, true ); - return; - } - else - { - if (m_mouseRect != wxRect(0,0,0,0)) - DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); - else - m_mouseRect = wxRect(m_mousePt, wxSize(1, 1)); + if (m_mouseRect == wxRect(0, 0, 0, 0)) { + return; + } - m_mouseRect.width = m_mousePt.x - m_mouseRect.x; - m_mouseRect.height = m_mousePt.y - m_mouseRect.y; + wxRect rightedRect = m_mouseRect; - DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); - } + // rightedRect always goes from upper-left to lower-right + // don't fix m_mouseRect since redrawing will be off + if (rightedRect.width < 0) { + rightedRect.x += rightedRect.width; + rightedRect.width = -rightedRect.width; + } + if (rightedRect.height < 0) { + rightedRect.y += rightedRect.height; + rightedRect.height = -rightedRect.height; + } - return; + // Zoom into image + if (m_area_mouse_func == wxPLOT_MOUSE_ZOOM) { + if ((m_area_mouse_marker == wxPLOT_MARKER_RECT) && + ((rightedRect.width > 10) && (rightedRect.height > 10))) { + SetZoom(rightedRect, true); + } + else if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (rightedRect.width > 10)) { + SetZoom(wxRect(rightedRect.x, 0, rightedRect.width, m_areaClientRect.height), true); + } + else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (rightedRect.height > 10)) { + SetZoom(wxRect(0, rightedRect.y, m_areaClientRect.width, rightedRect.height), true); + } + else { + DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); + } + } + // Select a range of points + else if ((m_area_mouse_func == wxPLOT_MOUSE_SELECT) && (active_index >= 0)) { + BeginBatch(); // if you select nothing, you don't get a refresh + + wxRect2DDouble plotRect = GetPlotRectFromClientRect(rightedRect); + + if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (plotRect.m_width > 0)) { + SelectXRange(active_index, wxRangeDouble(plotRect.m_x, plotRect.GetRight()), true); + } + else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (plotRect.m_height > 0)) { + SelectYRange(active_index, wxRangeDouble(plotRect.m_y, plotRect.GetBottom()), true); + } + else if ((plotRect.m_width > 0) || (plotRect.m_height > 0)) { + SelectRectangle(active_index, plotRect, true); + } + + m_mouseRect = wxRect(0, 0, 0, 0); + EndBatch(); + } + // Deselect a range of points + else if ((m_area_mouse_func == wxPLOT_MOUSE_DESELECT) && (active_index >= 0)) { + BeginBatch(); + + wxRect2DDouble plotRect = GetPlotRectFromClientRect(rightedRect); + + if ((m_area_mouse_marker == wxPLOT_MARKER_VERT) && (plotRect.m_width > 0)) { + DeselectXRange(active_index, wxRangeDouble(plotRect.m_x, plotRect.GetRight()), true); + } + else if ((m_area_mouse_marker == wxPLOT_MARKER_HORIZ) && (plotRect.m_height > 0)) { + DeselectYRange(active_index, wxRangeDouble(plotRect.m_y, plotRect.GetBottom()), true); + } + else if ((plotRect.m_width > 0) || (plotRect.m_height > 0)) { + DeselectRectangle(active_index, plotRect, true); + } + + m_mouseRect = wxRect(0, 0, 0, 0); + EndBatch(); + } + // Nothing to do - erase the rect + else { + DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); } + + m_mouseRect = wxRect(0, 0, 0, 0); return; -} + } + // Marking the rectangle or panning around + else if (event.LeftIsDown() && event.Dragging()) { + SetCaptureWindow(m_area); -void wxPlotCtrl::ProcessAxisEVT_MOUSE_EVENTS( wxMouseEvent &event ) -{ - if (event.ButtonDown() && IsTextCtrlShown()) - { - HideTextCtrl(true, true); - return; + if (m_area_mouse_cursorid == wxCURSOR_HAND) { + SetAreaMouseCursor(CURSOR_GRAB); } - wxPoint pos = event.GetPosition(); - wxPlotAxis *axisWin = (wxPlotAxis*)event.GetEventObject(); - wxCHECK_RET(axisWin, wxT("Unknown window")); + // Move the origin + if (m_area_mouse_func == wxPLOT_MOUSE_PAN) { +#if wxCHECK_VERSION(2, 7, 0) + if (!m_areaClientRect.Contains(event.GetPosition())) +#else + if (!m_areaClientRect.Inside(event.GetPosition())) +#endif + { + StartMouseTimer(ID_AREA_TIMER); + } - wxPoint& m_mousePt = axisWin->m_mousePt; + m_mouseRect = wxRect(0, 0, 0, 0); // no marker - if (event.LeftIsDown() && (axisWin != GetCaptureWindow())) - { - SetCaptureWindow(axisWin); - m_mousePt = pos; - return; + double dx = m_mousePt.x - lastMousePt.x; + double dy = m_mousePt.y - lastMousePt.y; + SetOrigin(m_viewRect.GetLeft() - dx / m_zoom.m_x, m_viewRect.GetTop() + dy / m_zoom.m_y, + true); + return; } - else if (!event.LeftIsDown()) - { - SetCaptureWindow(NULL); - StopMouseTimer(); + else { + if (m_mouseRect != wxRect(0, 0, 0, 0)) { + DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); + } + else { + m_mouseRect = wxRect(m_mousePt, wxSize(1, 1)); + } + + m_mouseRect.width = m_mousePt.x - m_mouseRect.x; + m_mouseRect.height = m_mousePt.y - m_mouseRect.y; + + DrawMouseMarker(&dc, m_area_mouse_marker, m_mouseRect); } - else if (event.LeftIsDown()) - { - wxSize winSize = axisWin->GetSize(); - if (( axisWin->IsXAxis() && ((pos.x < 0) || (pos.x > winSize.x))) || - (!axisWin->IsXAxis() && ((pos.y < 0) || (pos.y > winSize.y))) ) - { - m_mousePt = pos; - StartMouseTimer(axisWin->IsXAxis() ? ID_XAXIS_TIMER : ID_YAXIS_TIMER); - } - else if (IsTimerRunning()) - m_mousePt = pos; - } + return; + } + return; +} - int wheel = event.GetWheelRotation(); +void wxPlotCtrl::ProcessAxisEVT_MOUSE_EVENTS(wxMouseEvent &event) +{ + if (event.ButtonDown() && IsTextCtrlShown()) { + HideTextCtrl(true, true); + return; + } - if (wheel != 0) - { - wheel = wheel > 0 ? 1 : wheel < 0 ? -1 : 0; - double dx = 0, dy = 0; + wxPoint pos = event.GetPosition(); + wxPlotAxis *axisWin = (wxPlotAxis *)event.GetEventObject(); + wxCHECK_RET(axisWin, wxT("Unknown window")); - if (axisWin->IsXAxis()) - dx = wheel*m_viewRect.m_width/4.0; - else - dy = wheel*m_viewRect.m_height/4.0; + wxPoint &m_mousePt = axisWin->m_mousePt; - SetOrigin(m_viewRect.GetLeft() + dx, - m_viewRect.GetTop() + dy, true); + if (event.LeftIsDown() && (axisWin != GetCaptureWindow())) { + SetCaptureWindow(axisWin); + m_mousePt = pos; + return; + } + else if (!event.LeftIsDown()) { + SetCaptureWindow(NULL); + StopMouseTimer(); + } + else if (event.LeftIsDown()) { + wxSize winSize = axisWin->GetSize(); + + if ((axisWin->IsXAxis() && ((pos.x < 0) || (pos.x > winSize.x))) || + (!axisWin->IsXAxis() && ((pos.y < 0) || (pos.y > winSize.y)))) { + m_mousePt = pos; + StartMouseTimer(axisWin->IsXAxis() ? ID_XAXIS_TIMER : ID_YAXIS_TIMER); } - - if ((!GetScrollOnThumbRelease() && event.LeftIsDown() && event.Dragging()) || - (GetScrollOnThumbRelease() && event.LeftUp())) - { - double x = m_viewRect.GetLeft(); - double y = m_viewRect.GetTop(); - - if (axisWin->IsXAxis()) - x += (pos.x - m_mousePt.x)/m_zoom.m_x; - else - y += (m_mousePt.y-pos.y)/m_zoom.m_y; - - SetOrigin(x, y, true); + else if (IsTimerRunning()) { + m_mousePt = pos; } + } - if (!GetScrollOnThumbRelease()) - m_mousePt = pos; -} + int wheel = event.GetWheelRotation(); -void wxPlotCtrl::ProcessAreaEVT_KEY_DOWN( wxKeyEvent &event ) -{ - //wxPrintf(wxT("wxPlotCtrl::ProcessAreaEVT_KEY_DOWN %d `%c` S%dC%dA%d\n"), int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), event.AltDown()); - event.Skip(true); + if (wheel != 0) { + wheel = wheel > 0 ? 1 : wheel < 0 ? -1 : 0; + double dx = 0, dy = 0; - int code = event.GetKeyCode(); - bool alt = event.AltDown() || (code == WXK_ALT); - bool ctrl = event.ControlDown() || (code == WXK_CONTROL); - bool shift = event.ShiftDown() || (code == WXK_SHIFT); + if (axisWin->IsXAxis()) { + dx = wheel * m_viewRect.m_width / 4.0; + } + else { + dy = wheel * m_viewRect.m_height / 4.0; + } - if (shift && !alt && !ctrl) - SetAreaMouseFunction(wxPLOT_MOUSE_SELECT, true); - else if (!shift && ctrl && !alt) - SetAreaMouseFunction(wxPLOT_MOUSE_DESELECT, true); - else if (ctrl && shift && alt) - SetAreaMouseFunction(wxPLOT_MOUSE_PAN, true); - else // if (!ctrl || !shift || !alt) - SetAreaMouseFunction(wxPLOT_MOUSE_ZOOM, true); -} + SetOrigin(m_viewRect.GetLeft() + dx, m_viewRect.GetTop() + dy, true); + } -void wxPlotCtrl::ProcessAreaEVT_KEY_UP( wxKeyEvent &event ) -{ - //wxPrintf(wxT("wxPlotCtrl::ProcessAreaEVT_KEY_UP %d `%c` S%dC%dA%d\n"), int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), event.AltDown()); - event.Skip(true); + if ((!GetScrollOnThumbRelease() && event.LeftIsDown() && event.Dragging()) || + (GetScrollOnThumbRelease() && event.LeftUp())) { + double x = m_viewRect.GetLeft(); + double y = m_viewRect.GetTop(); - int code = event.GetKeyCode(); - bool alt = event.AltDown() && (code != WXK_ALT); - bool ctrl = event.ControlDown() && (code != WXK_CONTROL); - bool shift = event.ShiftDown() && (code != WXK_SHIFT); + if (axisWin->IsXAxis()) { + x += (pos.x - m_mousePt.x) / m_zoom.m_x; + } + else { + y += (m_mousePt.y - pos.y) / m_zoom.m_y; + } - if (shift && !ctrl && !alt) - SetAreaMouseFunction(wxPLOT_MOUSE_SELECT, true); - else if (!shift && ctrl && !alt) - SetAreaMouseFunction(wxPLOT_MOUSE_DESELECT, true); - else if (shift && ctrl && alt) - SetAreaMouseFunction(wxPLOT_MOUSE_PAN, true); - else // if (!shift && !ctrl && !alt) - SetAreaMouseFunction(wxPLOT_MOUSE_ZOOM, true); + SetOrigin(x, y, true); + } + + if (!GetScrollOnThumbRelease()) { + m_mousePt = pos; + } +} + +void wxPlotCtrl::ProcessAreaEVT_KEY_DOWN(wxKeyEvent &event) +{ + // wxPrintf(wxT("wxPlotCtrl::ProcessAreaEVT_KEY_DOWN %d `%c` S%dC%dA%d\n"), + // int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), + // event.AltDown()); + event.Skip(true); + + int code = event.GetKeyCode(); + bool alt = event.AltDown() || (code == WXK_ALT); + bool ctrl = event.ControlDown() || (code == WXK_CONTROL); + bool shift = event.ShiftDown() || (code == WXK_SHIFT); + + if (shift && !alt && !ctrl) { + SetAreaMouseFunction(wxPLOT_MOUSE_SELECT, true); + } + else if (!shift && ctrl && !alt) { + SetAreaMouseFunction(wxPLOT_MOUSE_DESELECT, true); + } + else if (ctrl && shift && alt) { + SetAreaMouseFunction(wxPLOT_MOUSE_PAN, true); + } + else { // if (!ctrl || !shift || !alt) + SetAreaMouseFunction(wxPLOT_MOUSE_ZOOM, true); + } +} + +void wxPlotCtrl::ProcessAreaEVT_KEY_UP(wxKeyEvent &event) +{ + // wxPrintf(wxT("wxPlotCtrl::ProcessAreaEVT_KEY_UP %d `%c` S%dC%dA%d\n"), + // int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), + // event.AltDown()); + event.Skip(true); + + int code = event.GetKeyCode(); + bool alt = event.AltDown() && (code != WXK_ALT); + bool ctrl = event.ControlDown() && (code != WXK_CONTROL); + bool shift = event.ShiftDown() && (code != WXK_SHIFT); + + if (shift && !ctrl && !alt) { + SetAreaMouseFunction(wxPLOT_MOUSE_SELECT, true); + } + else if (!shift && ctrl && !alt) { + SetAreaMouseFunction(wxPLOT_MOUSE_DESELECT, true); + } + else if (shift && ctrl && alt) { + SetAreaMouseFunction(wxPLOT_MOUSE_PAN, true); + } + else { // if (!shift && !ctrl && !alt) + SetAreaMouseFunction(wxPLOT_MOUSE_ZOOM, true); + } } void wxPlotCtrl::OnChar(wxKeyEvent &event) { - //wxPrintf(wxT("wxPlotCtrl::OnChar %d `%c` S%dC%dA%d\n"), int(event.GetKeyCode()), (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), event.AltDown()); + // wxPrintf(wxT("wxPlotCtrl::OnChar %d `%c` S%dC%dA%d\n"), int(event.GetKeyCode()), + // (wxChar)event.GetKeyCode(), event.ShiftDown(), event.ControlDown(), event.AltDown()); - // select the next curve if possible, or cursor point like left mouse - if (event.GetKeyCode() == WXK_SPACE) - { - if (event.ShiftDown() || event.ControlDown()) - { - if (IsCursorValid()) - { - if (GetDataCurve(m_cursor_curve)) - DoSelectDataRange(m_cursor_curve, wxRangeInt(m_cursor_index,m_cursor_index), !event.ControlDown(), true); - else - { - wxPoint2DDouble pt(m_cursorMarker.GetPlotPosition()); - DoSelectRectangle(m_cursor_curve, wxRect2DDouble(pt.m_x,0,pt.m_x,0), !event.ControlDown(), true); - } - } + // select the next curve if possible, or cursor point like left mouse + if (event.GetKeyCode() == WXK_SPACE) { + if (event.ShiftDown() || event.ControlDown()) { + if (IsCursorValid()) { + if (GetDataCurve(m_cursor_curve)) { + DoSelectDataRange(m_cursor_curve, wxRangeInt(m_cursor_index, m_cursor_index), + !event.ControlDown(), true); } - else - { - int count = GetCurveCount(); - if ((count < 1) || ((count == 1) && (m_active_index == 0))) return; - int index = (m_active_index + 1 > count - 1) ? 0 : m_active_index + 1; - SetActiveIndex( index, true ); + else { + wxPoint2DDouble pt(m_cursorMarker.GetPlotPosition()); + DoSelectRectangle(m_cursor_curve, wxRect2DDouble(pt.m_x, 0, pt.m_x, 0), + !event.ControlDown(), true); } + } + } + else { + int count = GetCurveCount(); + if ((count < 1) || ((count == 1) && (m_active_index == 0))) { return; + } + int index = (m_active_index + 1 > count - 1) ? 0 : m_active_index + 1; + SetActiveIndex(index, true); } + return; + } - // These are reserved for the program - if (event.ControlDown() || event.AltDown()) - { - event.Skip(true); - return; + // These are reserved for the program + if (event.ControlDown() || event.AltDown()) { + event.Skip(true); + return; + } + + switch (event.GetKeyCode()) { + // cursor keys moves the plot origin around + case WXK_LEFT: + SetOrigin(m_viewRect.GetLeft() - m_viewRect.m_width / 10.0, m_viewRect.GetTop()); + return; + case WXK_RIGHT: + SetOrigin(m_viewRect.GetLeft() + m_viewRect.m_width / 10.0, m_viewRect.GetTop()); + return; + case WXK_UP: + SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() + m_viewRect.m_height / 10.0); + return; + case WXK_DOWN: + SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() - m_viewRect.m_height / 10.0); + return; + case WXK_PAGEUP: + SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() + m_viewRect.m_height / 2.0); + return; + case WXK_PAGEDOWN: + SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() - m_viewRect.m_height / 2.0); + return; + + // Center the plot on the cursor point, or 0,0 + case WXK_HOME: { + if (IsCursorValid()) { + MakeCursorVisible(true, true); + } + else { + SetOrigin(-m_viewRect.m_width / 2.0, -m_viewRect.m_height / 2.0, true); } - switch (event.GetKeyCode()) - { - // cursor keys moves the plot origin around - case WXK_LEFT : SetOrigin(m_viewRect.GetLeft() - m_viewRect.m_width/10.0, m_viewRect.GetTop()); return; - case WXK_RIGHT : SetOrigin(m_viewRect.GetLeft() + m_viewRect.m_width/10.0, m_viewRect.GetTop()); return; - case WXK_UP : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() + m_viewRect.m_height/10.0); return; - case WXK_DOWN : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() - m_viewRect.m_height/10.0); return; - case WXK_PAGEUP : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() + m_viewRect.m_height/2.0); return; - case WXK_PAGEDOWN : SetOrigin(m_viewRect.GetLeft(), m_viewRect.GetTop() - m_viewRect.m_height/2.0); return; - - // Center the plot on the cursor point, or 0,0 - case WXK_HOME : - { - if (IsCursorValid()) - MakeCursorVisible(true, true); - else - SetOrigin(-m_viewRect.m_width/2.0, -m_viewRect.m_height/2.0, true); - - return; + return; + } + // try to make the current curve fully visible + case WXK_END: { + wxPlotData *plotData = GetActiveDataCurve(); + if (plotData) { + wxRect2DDouble bound = plotData->GetBoundingRect(); + bound.Inset(-bound.m_width / 80.0, -bound.m_height / 80.0); + SetViewRect(bound, true); + } + else if (GetActiveCurve()) { + wxPlotCurve *curve = GetActiveCurve(); + double y, min, max; + + y = max = min = curve->GetY(GetPlotCoordFromClientX(0)); + + for (int i = 1; i < m_areaClientRect.width; i++) { + y = curve->GetY(GetPlotCoordFromClientX(i)); + + if (wxFinite(y) != 0) { + if (y > max) { + max = y; + } + if (y < min) { + min = y; + } } - // try to make the current curve fully visible - case WXK_END : - { - wxPlotData *plotData = GetActiveDataCurve(); - if (plotData) - { - wxRect2DDouble bound = plotData->GetBoundingRect(); - bound.Inset(-bound.m_width/80.0, -bound.m_height/80.0); - SetViewRect(bound, true); - } - else if (GetActiveCurve()) - { - wxPlotCurve *curve = GetActiveCurve(); - double y, min, max; - - y = max = min = curve->GetY(GetPlotCoordFromClientX(0)); - - for (int i=1; iGetY(GetPlotCoordFromClientX(i)); - - if (wxFinite(y) != 0) - { - if (y > max) max = y; - if (y < min) min = y; - } - } - - if (max == min) - { - min -= 5; - max += 5; - } - - wxRect2DDouble bound(m_viewRect.m_x, min, m_viewRect.m_width, max-min); - SetViewRect(bound, true); - } + } - return; - } + if (max == min) { + min -= 5; + max += 5; + } - // zoom in and out - case wxT('a'): SetZoom( wxPoint2DDouble(m_zoom.m_x/1.5, m_zoom.m_y ), true ); return; - case wxT('d'): SetZoom( wxPoint2DDouble(m_zoom.m_x*1.5, m_zoom.m_y ), true ); return; - case wxT('w'): SetZoom( wxPoint2DDouble(m_zoom.m_x, m_zoom.m_y*1.5), true ); return; - case wxT('x'): SetZoom( wxPoint2DDouble(m_zoom.m_x, m_zoom.m_y/1.5), true ); return; - - case wxT('q'): SetZoom( wxPoint2DDouble(m_zoom.m_x/1.5, m_zoom.m_y*1.5), true ); return; - case wxT('e'): SetZoom( wxPoint2DDouble(m_zoom.m_x*1.5, m_zoom.m_y*1.5), true ); return; - case wxT('z'): SetZoom( wxPoint2DDouble(m_zoom.m_x/1.5, m_zoom.m_y/1.5), true ); return; - case wxT('c'): SetZoom( wxPoint2DDouble(m_zoom.m_x*1.5, m_zoom.m_y/1.5), true ); return; - - case wxT('s'): MakeCurveVisible(GetActiveIndex(), true); break; - - // Select previous/next point in a curve - case wxT('<'): case wxT(','): - { - double x = GetPlotCoordFromClientX(m_areaClientRect.width-1); - wxPlotData *plotData = GetActiveDataCurve(); - if (plotData) - { - if (!IsCursorValid()) - SetCursorDataIndex(m_active_index, plotData->GetIndexFromX(x, wxPlotData::index_floor), true); - else if (m_cursor_index > 0) - SetCursorDataIndex(m_cursor_curve, m_cursor_index-1, true); - } - else if (m_active_index >= 0) - { - if (!IsCursorValid()) - SetCursorXPoint(m_active_index, x, true); - else - { - x = GetPlotCoordFromClientX((GetClientCoordFromPlotX(m_cursorMarker.GetPlotRect().m_x)-1)); - SetCursorXPoint(m_cursor_curve, x, true); - } - } + wxRect2DDouble bound(m_viewRect.m_x, min, m_viewRect.m_width, max - min); + SetViewRect(bound, true); + } - MakeCursorVisible(false, true); + return; + } - return; - } - case wxT('>'): case wxT('.'): - { - double x = GetPlotCoordFromClientX(0); - wxPlotData *plotData = GetActiveDataCurve(); - if (plotData) - { - int count = plotData->GetCount(); - - if (!IsCursorValid()) - SetCursorDataIndex(m_active_index, plotData->GetIndexFromX(x, wxPlotData::index_ceil), true); - else if (m_cursor_index < count - 1) - SetCursorDataIndex(m_cursor_curve, m_cursor_index+1, true); - } - else if (m_active_index >= 0) - { - if (!IsCursorValid()) - SetCursorXPoint(m_active_index, x, true); - else - { - x = GetPlotCoordFromClientX((GetClientCoordFromPlotX(m_cursorMarker.GetPlotRect().m_x)+1)); - SetCursorXPoint(m_cursor_curve, x, true); - } - } + // zoom in and out + case wxT('a'): + SetZoom(wxPoint2DDouble(m_zoom.m_x / 1.5, m_zoom.m_y), true); + return; + case wxT('d'): + SetZoom(wxPoint2DDouble(m_zoom.m_x * 1.5, m_zoom.m_y), true); + return; + case wxT('w'): + SetZoom(wxPoint2DDouble(m_zoom.m_x, m_zoom.m_y * 1.5), true); + return; + case wxT('x'): + SetZoom(wxPoint2DDouble(m_zoom.m_x, m_zoom.m_y / 1.5), true); + return; - MakeCursorVisible(false, true); + case wxT('q'): + SetZoom(wxPoint2DDouble(m_zoom.m_x / 1.5, m_zoom.m_y * 1.5), true); + return; + case wxT('e'): + SetZoom(wxPoint2DDouble(m_zoom.m_x * 1.5, m_zoom.m_y * 1.5), true); + return; + case wxT('z'): + SetZoom(wxPoint2DDouble(m_zoom.m_x / 1.5, m_zoom.m_y / 1.5), true); + return; + case wxT('c'): + SetZoom(wxPoint2DDouble(m_zoom.m_x * 1.5, m_zoom.m_y / 1.5), true); + return; - return; - } + case wxT('s'): + MakeCurveVisible(GetActiveIndex(), true); + break; + + // Select previous/next point in a curve + case wxT('<'): + case wxT(','): { + double x = GetPlotCoordFromClientX(m_areaClientRect.width - 1); + wxPlotData *plotData = GetActiveDataCurve(); + if (plotData) { + if (!IsCursorValid()) { + SetCursorDataIndex(m_active_index, plotData->GetIndexFromX(x, wxPlotData::index_floor), + true); + } + else if (m_cursor_index > 0) { + SetCursorDataIndex(m_cursor_curve, m_cursor_index - 1, true); + } + } + else if (m_active_index >= 0) { + if (!IsCursorValid()) { + SetCursorXPoint(m_active_index, x, true); + } + else { + x = GetPlotCoordFromClientX( + (GetClientCoordFromPlotX(m_cursorMarker.GetPlotRect().m_x) - 1)); + SetCursorXPoint(m_cursor_curve, x, true); + } + } - // go to the last or next zoom - case wxT('[') : NextHistoryView(false, true); return; - case wxT(']') : NextHistoryView(true, true); return; + MakeCursorVisible(false, true); - // delete the selected curve - case WXK_DELETE: - { - if (m_activeCurve) DeleteCurve(m_activeCurve, true); - return; - } - // delete current selection or go to next curve and delete it's selection - // finally invalidate cursor - case WXK_ESCAPE : - { - BeginBatch(); - if ((m_active_index >= 0) && (GetSelectedRangeCount(m_active_index) > 0)) - { - ClearSelectedRanges(m_active_index, true); - } - else - { - bool has_cleared = false; - - for (int i=0; i 0) - { - ClearSelectedRanges(i, true); - has_cleared = true; - break; - } - } - - if (!has_cleared) - { - if (IsCursorValid()) - InvalidateCursor(true); - else if (m_active_index > -1) - SetActiveIndex( -1, true ); - } - } - EndBatch(); // ESC is also a generic clean up routine too! - break; + return; + } + case wxT('>'): + case wxT('.'): { + double x = GetPlotCoordFromClientX(0); + wxPlotData *plotData = GetActiveDataCurve(); + if (plotData) { + int count = plotData->GetCount(); + + if (!IsCursorValid()) { + SetCursorDataIndex(m_active_index, plotData->GetIndexFromX(x, wxPlotData::index_ceil), + true); + } + else if (m_cursor_index < count - 1) { + SetCursorDataIndex(m_cursor_curve, m_cursor_index + 1, true); + } + } + else if (m_active_index >= 0) { + if (!IsCursorValid()) { + SetCursorXPoint(m_active_index, x, true); + } + else { + x = GetPlotCoordFromClientX( + (GetClientCoordFromPlotX(m_cursorMarker.GetPlotRect().m_x) + 1)); + SetCursorXPoint(m_cursor_curve, x, true); + } + } + + MakeCursorVisible(false, true); + + return; + } + + // go to the last or next zoom + case wxT('['): + NextHistoryView(false, true); + return; + case wxT(']'): + NextHistoryView(true, true); + return; + + // delete the selected curve + case WXK_DELETE: { + if (m_activeCurve) { + DeleteCurve(m_activeCurve, true); + } + return; + } + // delete current selection or go to next curve and delete it's selection + // finally invalidate cursor + case WXK_ESCAPE: { + BeginBatch(); + if ((m_active_index >= 0) && (GetSelectedRangeCount(m_active_index) > 0)) { + ClearSelectedRanges(m_active_index, true); + } + else { + bool has_cleared = false; + + for (int i = 0; i < GetCurveCount(); i++) { + if (GetSelectedRangeCount(i) > 0) { + ClearSelectedRanges(i, true); + has_cleared = true; + break; } + } - default: event.Skip(true); break; + if (!has_cleared) { + if (IsCursorValid()) { + InvalidateCursor(true); + } + else if (m_active_index > -1) { + SetActiveIndex(-1, true); + } + } } + EndBatch(); // ESC is also a generic clean up routine too! + break; + } + + default: + event.Skip(true); + break; + } } void wxPlotCtrl::UpdateWindowSize() { - m_areaClientRect = wxRect(wxPoint(0,0), m_area->GetClientSize()); - // If something happens to make these true, there's a problem - if (m_areaClientRect.width < 10) m_areaClientRect.width = 10; - if (m_areaClientRect.height < 10) m_areaClientRect.height = 10; + m_areaClientRect = wxRect(wxPoint(0, 0), m_area->GetClientSize()); + // If something happens to make these true, there's a problem + if (m_areaClientRect.width < 10) { + m_areaClientRect.width = 10; + } + if (m_areaClientRect.height < 10) { + m_areaClientRect.height = 10; + } } void wxPlotCtrl::AdjustScrollBars() { - double range, thumbsize, position; - double pagesize; - - range = (m_curveBoundingRect.m_width * m_zoom.m_x); - if (!IsFinite(range, wxT("plot's x range is NaN"))) return; - if (range > 32000) range = 32000; else if (range < 1) range = 1; - - thumbsize = (range * (m_viewRect.m_width/m_curveBoundingRect.m_width)); - if (!IsFinite(thumbsize, wxT("plot's x range is NaN"))) return; - if (thumbsize > range) thumbsize = range; else if (thumbsize < 1) thumbsize = 1; - - position = (range * ((m_viewRect.GetLeft() - m_curveBoundingRect.GetLeft())/m_curveBoundingRect.m_width)); - if (!IsFinite(position, wxT("plot's x range is NaN"))) return; - if (position > range - thumbsize) position = range - thumbsize; else if (position < 0) position = 0; - pagesize = thumbsize; - - m_xAxisScrollbar->SetScrollbar( int(position), int(thumbsize), int(range), int(pagesize) ); - - range = (m_curveBoundingRect.m_height * m_zoom.m_y); - if (!IsFinite(range, wxT("plot's y range is NaN"))) return; - if (range > 32000) range = 32000; else if (range < 1) range = 1; + double range, thumbsize, position; + double pagesize; - thumbsize = (range * (m_viewRect.m_height/m_curveBoundingRect.m_height)); - if (!IsFinite(thumbsize, wxT("plot's x range is NaN"))) return; - if (thumbsize > range) thumbsize = range; else if (thumbsize < 1) thumbsize = 1; - - position = (range - range * ((m_viewRect.GetTop() - m_curveBoundingRect.GetTop())/m_curveBoundingRect.m_height) - thumbsize); - if (!IsFinite(position, wxT("plot's x range is NaN"))) return; - if (position > range - thumbsize) position = range - thumbsize; else if (position < 0) position = 0; - pagesize = thumbsize; + range = (m_curveBoundingRect.m_width * m_zoom.m_x); + if (!IsFinite(range, wxT("plot's x range is NaN"))) { + return; + } + if (range > 32000) { + range = 32000; + } + else if (range < 1) { + range = 1; + } + + thumbsize = (range * (m_viewRect.m_width / m_curveBoundingRect.m_width)); + if (!IsFinite(thumbsize, wxT("plot's x range is NaN"))) { + return; + } + if (thumbsize > range) { + thumbsize = range; + } + else if (thumbsize < 1) { + thumbsize = 1; + } + + position = (range * ((m_viewRect.GetLeft() - m_curveBoundingRect.GetLeft()) / + m_curveBoundingRect.m_width)); + if (!IsFinite(position, wxT("plot's x range is NaN"))) { + return; + } + if (position > range - thumbsize) { + position = range - thumbsize; + } + else if (position < 0) { + position = 0; + } + pagesize = thumbsize; + + m_xAxisScrollbar->SetScrollbar(int(position), int(thumbsize), int(range), int(pagesize)); + + range = (m_curveBoundingRect.m_height * m_zoom.m_y); + if (!IsFinite(range, wxT("plot's y range is NaN"))) { + return; + } + if (range > 32000) { + range = 32000; + } + else if (range < 1) { + range = 1; + } + + thumbsize = (range * (m_viewRect.m_height / m_curveBoundingRect.m_height)); + if (!IsFinite(thumbsize, wxT("plot's x range is NaN"))) { + return; + } + if (thumbsize > range) { + thumbsize = range; + } + else if (thumbsize < 1) { + thumbsize = 1; + } + + position = (range - + range * ((m_viewRect.GetTop() - m_curveBoundingRect.GetTop()) / + m_curveBoundingRect.m_height) - + thumbsize); + if (!IsFinite(position, wxT("plot's x range is NaN"))) { + return; + } + if (position > range - thumbsize) { + position = range - thumbsize; + } + else if (position < 0) { + position = 0; + } + pagesize = thumbsize; - m_yAxisScrollbar->SetScrollbar( int(position), int(thumbsize), int(range), int(pagesize) ); + m_yAxisScrollbar->SetScrollbar(int(position), int(thumbsize), int(range), int(pagesize)); } -void wxPlotCtrl::OnScroll(wxScrollEvent& event) +void wxPlotCtrl::OnScroll(wxScrollEvent &event) { - if (m_scroll_on_thumb_release && (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)) - return; + if (m_scroll_on_thumb_release && (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)) { + return; + } - if (event.GetId() == wxPlotCtrl::ID_PLOTCTRL_X_SCROLLBAR) - { - double range = m_xAxisScrollbar->GetRange(); - if (range < 1) return; - double position = m_xAxisScrollbar->GetThumbPosition(); - double origin_x = m_curveBoundingRect.GetLeft() + m_curveBoundingRect.m_width*(position/range); - if (!IsFinite(origin_x, wxT("plot's x-origin is NaN"))) return; - m_viewRect.m_x = origin_x; - Redraw(wxPLOT_REDRAW_PLOT|wxPLOT_REDRAW_XAXIS); - } - else if (event.GetId() == wxPlotCtrl::ID_PLOTCTRL_Y_SCROLLBAR) - { - double range = m_yAxisScrollbar->GetRange(); - if (range < 1) return; - double position = m_yAxisScrollbar->GetThumbPosition(); - double thumbsize = m_yAxisScrollbar->GetThumbSize(); - double origin_y = m_curveBoundingRect.GetTop() + m_curveBoundingRect.m_height*((range-position-thumbsize)/range); - if (!IsFinite(origin_y, wxT("plot's y-origin is NaN"))) return; - m_viewRect.m_y = origin_y; - Redraw(wxPLOT_REDRAW_PLOT|wxPLOT_REDRAW_YAXIS); + if (event.GetId() == wxPlotCtrl::ID_PLOTCTRL_X_SCROLLBAR) { + double range = m_xAxisScrollbar->GetRange(); + if (range < 1) { + return; + } + double position = m_xAxisScrollbar->GetThumbPosition(); + double origin_x = + m_curveBoundingRect.GetLeft() + m_curveBoundingRect.m_width * (position / range); + if (!IsFinite(origin_x, wxT("plot's x-origin is NaN"))) { + return; + } + m_viewRect.m_x = origin_x; + Redraw(wxPLOT_REDRAW_PLOT | wxPLOT_REDRAW_XAXIS); + } + else if (event.GetId() == wxPlotCtrl::ID_PLOTCTRL_Y_SCROLLBAR) { + double range = m_yAxisScrollbar->GetRange(); + if (range < 1) { + return; + } + double position = m_yAxisScrollbar->GetThumbPosition(); + double thumbsize = m_yAxisScrollbar->GetThumbSize(); + double origin_y = m_curveBoundingRect.GetTop() + + m_curveBoundingRect.m_height * ((range - position - thumbsize) / range); + if (!IsFinite(origin_y, wxT("plot's y-origin is NaN"))) { + return; } + m_viewRect.m_y = origin_y; + Redraw(wxPLOT_REDRAW_PLOT | wxPLOT_REDRAW_YAXIS); + } } bool wxPlotCtrl::IsFinite(double n, const wxString &msg) const { - if (!wxFinite(n)) - { - if (!msg.IsEmpty()) - { - wxPlotEvent event(wxEVT_PLOT_ERROR, GetId(), (wxPlotCtrl*)this); - event.SetString(msg); - (void)DoSendEvent( event ); - } - - return false; + if (!wxFinite(n)) { + if (!msg.IsEmpty()) { + wxPlotEvent event(wxEVT_PLOT_ERROR, GetId(), (wxPlotCtrl *)this); + event.SetString(msg); + (void)DoSendEvent(event); } - return true; + return false; + } + + return true; } -bool wxPlotCtrl::FindCurve(const wxPoint2DDouble &pt, const wxPoint2DDouble &dpt, - int &curve_index, int &data_index, wxPoint2DDouble *curvePt) const +bool wxPlotCtrl::FindCurve(const wxPoint2DDouble &pt, const wxPoint2DDouble &dpt, int &curve_index, + int &data_index, wxPoint2DDouble *curvePt) const { - curve_index = data_index = -1; + curve_index = data_index = -1; - if (!IsFinite(pt.m_x, wxT("point is not finite"))) return false; - if (!IsFinite(pt.m_y, wxT("point is not finite"))) return false; - if (!IsFinite(dpt.m_x, wxT("point is not finite"))) return false; - if (!IsFinite(dpt.m_y, wxT("point is not finite"))) return false; + if (!IsFinite(pt.m_x, wxT("point is not finite"))) { + return false; + } + if (!IsFinite(pt.m_y, wxT("point is not finite"))) { + return false; + } + if (!IsFinite(dpt.m_x, wxT("point is not finite"))) { + return false; + } + if (!IsFinite(dpt.m_y, wxT("point is not finite"))) { + return false; + } - int curve_count = GetCurveCount(); - if (curve_count < 1) return false; + int curve_count = GetCurveCount(); + if (curve_count < 1) { + return false; + } + + for (int n = -1; n < curve_count; n++) { + // find the point in the selected curve first + if (n == -1) { + if (m_active_index >= 0) { + n = m_active_index; + } + else { + n = 0; + } + } + else if (n == m_active_index) { + continue; + } - for (int n=-1; n= 0) - n = m_active_index; - else - n = 0; + wxPlotCurve *plotCurve = GetCurve(n); + wxPlotData *plotData = wxDynamicCast(plotCurve, wxPlotData); + + // find the index of the closest point in a wxPlotData curve + if (plotData) { + // check if curve has BoundingRect + wxRect2DDouble rect = plotData->GetBoundingRect(); + if (((rect.m_width > 0) && + ((pt.m_x + dpt.m_x < rect.GetLeft()) || (pt.m_x - dpt.m_x > rect.GetRight()))) || + ((rect.m_height > 0) && + ((pt.m_y + dpt.m_y < rect.GetTop()) || (pt.m_y - dpt.m_y > rect.GetBottom())))) { + if ((n == m_active_index) && (n > 0)) { + n = -1; // start back at 0 } - else if (n == m_active_index) - continue; - - wxPlotCurve *plotCurve = GetCurve(n); - wxPlotData *plotData = wxDynamicCast(plotCurve, wxPlotData); - - // find the index of the closest point in a wxPlotData curve - if (plotData) - { - // check if curve has BoundingRect - wxRect2DDouble rect = plotData->GetBoundingRect(); - if ( ((rect.m_width > 0) && - ((pt.m_x+dpt.m_x < rect.GetLeft()) || (pt.m_x-dpt.m_x > rect.GetRight()))) || - ((rect.m_height > 0) && - ((pt.m_y+dpt.m_y < rect.GetTop()) || (pt.m_y-dpt.m_y > rect.GetBottom()))) ) - { - if ((n == m_active_index) && (n > 0)) n = -1; // start back at 0 - continue; - } + continue; + } - int index = plotData->GetIndexFromXY(pt.m_x, pt.m_y, dpt.m_x); + int index = plotData->GetIndexFromXY(pt.m_x, pt.m_y, dpt.m_x); - double x = plotData->GetXValue(index); - double y = plotData->GetYValue(index); + double x = plotData->GetXValue(index); + double y = plotData->GetYValue(index); - if ((fabs(x-pt.m_x) <= dpt.m_x) && (fabs(y-pt.m_y) <= dpt.m_y)) - { - curve_index = n; - data_index = index; - if (curvePt) *curvePt = wxPoint2DDouble(x, y); - return true; - } + if ((fabs(x - pt.m_x) <= dpt.m_x) && (fabs(y - pt.m_y) <= dpt.m_y)) { + curve_index = n; + data_index = index; + if (curvePt) { + *curvePt = wxPoint2DDouble(x, y); } - else // not a data curve, just find y at this x pos - { - wxRect2DDouble rect = plotCurve->GetBoundingRect(); - if ((rect.m_width <= 0) || ((pt.m_x+dpt.m_x >= rect.GetLeft()) && (pt.m_x-dpt.m_x <= rect.GetRight()))) - { - if ((rect.m_height <= 0) || ((pt.m_y >= rect.GetTop()) && (pt.m_y-dpt.m_y <= rect.GetBottom()))) - { - double y = plotCurve->GetY(pt.m_x); - if (fabs(y - pt.m_y) <= dpt.m_y) - { - curve_index = n; - if (curvePt) *curvePt = wxPoint2DDouble(pt.m_x, y); - return true; - } - } + return true; + } + } + else // not a data curve, just find y at this x pos + { + wxRect2DDouble rect = plotCurve->GetBoundingRect(); + if ((rect.m_width <= 0) || + ((pt.m_x + dpt.m_x >= rect.GetLeft()) && (pt.m_x - dpt.m_x <= rect.GetRight()))) { + if ((rect.m_height <= 0) || + ((pt.m_y >= rect.GetTop()) && (pt.m_y - dpt.m_y <= rect.GetBottom()))) { + double y = plotCurve->GetY(pt.m_x); + if (fabs(y - pt.m_y) <= dpt.m_y) { + curve_index = n; + if (curvePt) { + *curvePt = wxPoint2DDouble(pt.m_x, y); } + return true; + } } + } + } - // continue searching through curves - // if on the current then start back at the beginning if not already at 0 - if ((n == m_active_index) && (n > 0)) n = -1; + // continue searching through curves + // if on the current then start back at the beginning if not already at 0 + if ((n == m_active_index) && (n > 0)) { + n = -1; } - return false; + } + return false; } bool wxPlotCtrl::DoSendEvent(wxPlotEvent &event) const { -/* - if (event.GetEventType() != wxEVT_PLOT_MOUSE_MOTION) - { - wxLogDebug(wxT("wxPlotEvent '%s' CurveIndex: %d, DataIndex: %d, Pos: %lf %lf, MouseFn %d"), - GetEventName(event).c_str(), - event.GetCurveIndex(), event.GetCurveDataIndex(), - event.GetX(), event.GetY(), event.GetMouseFunction()); - } -*/ - return !GetEventHandler()->ProcessEvent(event) || event.IsAllowed(); + /* + if (event.GetEventType() != wxEVT_PLOT_MOUSE_MOTION) + { + wxLogDebug(wxT("wxPlotEvent '%s' CurveIndex: %d, DataIndex: %d, Pos: %lf %lf, MouseFn + %d"), GetEventName(event).c_str(), event.GetCurveIndex(), event.GetCurveDataIndex(), + event.GetX(), event.GetY(), event.GetMouseFunction()); + } + */ + return !GetEventHandler()->ProcessEvent(event) || event.IsAllowed(); } void wxPlotCtrl::StartMouseTimer(wxWindowID win_id) { -#if wxCHECK_VERSION(2,5,0) - if (m_timer && (m_timer->GetId() != win_id)) - StopMouseTimer(); +#if wxCHECK_VERSION(2, 5, 0) + if (m_timer && (m_timer->GetId() != win_id)) { + StopMouseTimer(); + } #else - StopMouseTimer(); // always stop it I guess + StopMouseTimer(); // always stop it I guess #endif // wxCHECK_VERSION(2,5,0) - if (!m_timer) - m_timer = new wxTimer(this, win_id); + if (!m_timer) { + m_timer = new wxTimer(this, win_id); + } - if (!m_timer->IsRunning()) - m_timer->Start(200, true); // one shot timer + if (!m_timer->IsRunning()) { + m_timer->Start(200, true); // one shot timer + } } void wxPlotCtrl::StopMouseTimer() { - if (m_timer) - { - if (m_timer->IsRunning()) - m_timer->Stop(); - - delete m_timer; - m_timer = NULL; + if (m_timer) { + if (m_timer->IsRunning()) { + m_timer->Stop(); } -} -bool wxPlotCtrl::IsTimerRunning() -{ - return (m_timer && m_timer->IsRunning()); + delete m_timer; + m_timer = NULL; + } } -void wxPlotCtrl::OnTimer( wxTimerEvent &event ) +bool wxPlotCtrl::IsTimerRunning() { return (m_timer && m_timer->IsRunning()); } + +void wxPlotCtrl::OnTimer(wxTimerEvent &event) { - wxPoint mousePt; + wxPoint mousePt; - switch (event.GetId()) - { - case ID_AREA_TIMER : mousePt = m_area->m_mousePt; break; - case ID_XAXIS_TIMER : mousePt = m_xAxis->m_mousePt; break; - case ID_YAXIS_TIMER : mousePt = m_yAxis->m_mousePt; break; - default : - { - event.Skip(); // someone else's timer? - return; - } - } + switch (event.GetId()) { + case ID_AREA_TIMER: + mousePt = m_area->m_mousePt; + break; + case ID_XAXIS_TIMER: + mousePt = m_xAxis->m_mousePt; + break; + case ID_YAXIS_TIMER: + mousePt = m_yAxis->m_mousePt; + break; + default: { + event.Skip(); // someone else's timer? + return; + } + } - double dx = (mousePt.x<0) ? -20 : (mousePt.x>GetPlotAreaRect().width ) ? 20 : 0; - double dy = (mousePt.y<0) ? 20 : (mousePt.y>GetPlotAreaRect().height) ? -20 : 0; - dx /= m_zoom.m_x; - dy /= m_zoom.m_y; + double dx = (mousePt.x < 0) ? -20 : (mousePt.x > GetPlotAreaRect().width) ? 20 : 0; + double dy = (mousePt.y < 0) ? 20 : (mousePt.y > GetPlotAreaRect().height) ? -20 : 0; + dx /= m_zoom.m_x; + dy /= m_zoom.m_y; - if (((dx == 0) && (dy == 0)) || - !SetOrigin(GetViewRect().GetLeft() + dx, GetViewRect().GetTop() + dy, true) ) - { - StopMouseTimer(); - } - else - StartMouseTimer(event.GetId()); // restart timer for another round + if (((dx == 0) && (dy == 0)) || + !SetOrigin(GetViewRect().GetLeft() + dx, GetViewRect().GetTop() + dy, true)) { + StopMouseTimer(); + } + else { + StartMouseTimer(event.GetId()); // restart timer for another round + } } void wxPlotCtrl::SetCaptureWindow(wxWindow *win) { - if (m_winCapture && (m_winCapture != win) && m_winCapture->HasCapture()) - m_winCapture->ReleaseMouse(); + if (m_winCapture && (m_winCapture != win) && m_winCapture->HasCapture()) { + m_winCapture->ReleaseMouse(); + } - m_winCapture = win; + m_winCapture = win; - if (m_winCapture && (!m_winCapture->HasCapture())) - m_winCapture->CaptureMouse(); + if (m_winCapture && (!m_winCapture->HasCapture())) { + m_winCapture->CaptureMouse(); + } } diff --git a/src/labenski/src/plotcurv.cpp b/src/labenski/src/plotcurv.cpp index 094ac1959..8371453a8 100644 --- a/src/labenski/src/plotcurv.cpp +++ b/src/labenski/src/plotcurv.cpp @@ -12,12 +12,12 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/bitmap.h" - #include "wx/dcmemory.h" +#include "wx/bitmap.h" +#include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/plotctrl/plotcurv.h" @@ -28,43 +28,22 @@ const wxRect2DDouble wxNullPlotBounds(0, 0, 0, 0); /* XPM */ static const char *normal_symbol_xpm_data[] = { -/* columns rows colors chars-per-pixel */ -"5 5 2 1", -" c None", -"b c #000000", -/* pixels */ -" bbb ", -"b b", -"b b", -"b b", -" bbb " -}; + /* columns rows colors chars-per-pixel */ + "5 5 2 1", " c None", "b c #000000", + /* pixels */ + " bbb ", "b b", "b b", "b b", " bbb "}; static const char *active_symbol_xpm_data[] = { -/* columns rows colors chars-per-pixel */ -"5 5 2 1", -" c None", -"b c #0000FF", -/* pixels */ -" bbb ", -"b b", -"b b", -"b b", -" bbb " -}; + /* columns rows colors chars-per-pixel */ + "5 5 2 1", " c None", "b c #0000FF", + /* pixels */ + " bbb ", "b b", "b b", "b b", " bbb "}; static const char *selected_symbol_xpm_data[] = { -/* columns rows colors chars-per-pixel */ -"5 5 2 1", -" c None", -"b c #FF0000", -/* pixels */ -" bbb ", -"b b", -"b b", -"b b", -" bbb " -}; + /* columns rows colors chars-per-pixel */ + "5 5 2 1", " c None", "b c #FF0000", + /* pixels */ + " bbb ", "b b", "b b", "b b", " bbb "}; #endif // USE_BITMAPS_FOR DRAWING @@ -78,15 +57,15 @@ wxBitmap wxPlotSymbolSelected; //---------------------------------------------------------------------------- double LinearInterpolateX(double x0, double y0, double x1, double y1, double y) { - //wxCHECK_MSG( (y1 - y0) != 0.0, 0.0, wxT("Divide by zero, LinearInterpolateX()") ); - return ( (y - y0)*(x1 - x0)/(y1 - y0) + x0 ); + // wxCHECK_MSG( (y1 - y0) != 0.0, 0.0, wxT("Divide by zero, LinearInterpolateX()") ); + return ((y - y0) * (x1 - x0) / (y1 - y0) + x0); } double LinearInterpolateY(double x0, double y0, double x1, double y1, double x) { - //wxCHECK_MSG( (x1 - x0) != 0.0, 0.0, wxT("Divide by zero, LinearInterpolateY()") ); - double m = (y1 - y0) / (x1 - x0); - return (m*x + (y0 - m*x0)); + // wxCHECK_MSG( (x1 - x0) != 0.0, 0.0, wxT("Divide by zero, LinearInterpolateY()") ); + double m = (y1 - y0) / (x1 - x0); + return (m * x + (y0 - m * x0)); } //---------------------------------------------------------------------------- @@ -97,72 +76,67 @@ wxArrayGenericPen wxPlotCurveRefData::sm_defaultPens; void InitPlotCurveDefaultPens() { - static bool s_init_default_pens = false; - if (!s_init_default_pens) - { - s_init_default_pens = true; - wxPlotCurveRefData::sm_defaultPens.Add(wxGenericPen( wxGenericColour( 0, 0, 0), 1, wxPENSTYLE_SOLID )); - wxPlotCurveRefData::sm_defaultPens.Add(wxGenericPen( wxGenericColour( 0, 0, 255), 1, wxPENSTYLE_SOLID )); - wxPlotCurveRefData::sm_defaultPens.Add(wxGenericPen( wxGenericColour(255, 0, 0), 1, wxPENSTYLE_SOLID )); - } + static bool s_init_default_pens = false; + if (!s_init_default_pens) { + s_init_default_pens = true; + wxPlotCurveRefData::sm_defaultPens.Add( + wxGenericPen(wxGenericColour(0, 0, 0), 1, wxPENSTYLE_SOLID)); + wxPlotCurveRefData::sm_defaultPens.Add( + wxGenericPen(wxGenericColour(0, 0, 255), 1, wxPENSTYLE_SOLID)); + wxPlotCurveRefData::sm_defaultPens.Add( + wxGenericPen(wxGenericColour(255, 0, 0), 1, wxPENSTYLE_SOLID)); + } } wxPlotCurveRefData::wxPlotCurveRefData() : wxObjectRefData() { - InitPlotCurveDefaultPens(); - m_pens = sm_defaultPens; + InitPlotCurveDefaultPens(); + m_pens = sm_defaultPens; } -wxPlotCurveRefData::wxPlotCurveRefData(const wxPlotCurveRefData& data) - :wxObjectRefData() +wxPlotCurveRefData::wxPlotCurveRefData(const wxPlotCurveRefData &data) : wxObjectRefData() { - Copy(data); + Copy(data); } void wxPlotCurveRefData::Copy(const wxPlotCurveRefData &source) { - m_boundingRect = source.m_boundingRect; - m_pens = source.m_pens; - m_optionNames = source.m_optionNames; - m_optionValues = source.m_optionValues; + m_boundingRect = source.m_boundingRect; + m_pens = source.m_pens; + m_optionNames = source.m_optionNames; + m_optionValues = source.m_optionValues; } -#define M_PLOTCURVEDATA ((wxPlotCurveRefData*)m_refData) +#define M_PLOTCURVEDATA ((wxPlotCurveRefData *)m_refData) //----------------------------------------------------------------------------- // wxPlotCurve //----------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPlotCurve, wxObject); -wxObjectRefData *wxPlotCurve::CreateRefData() const -{ - return new wxPlotCurveRefData; -} +wxObjectRefData *wxPlotCurve::CreateRefData() const { return new wxPlotCurveRefData; } wxObjectRefData *wxPlotCurve::CloneRefData(const wxObjectRefData *data) const { - return new wxPlotCurveRefData(*(const wxPlotCurveRefData *)data); + return new wxPlotCurveRefData(*(const wxPlotCurveRefData *)data); } wxPlotCurve::wxPlotCurve() : wxObject() { - // Note: You must do this in your constructor in order to use the the curve - // m_refData = new wxPlotCurveRefData (or wxMySubclassedPlotCurveRefData) + // Note: You must do this in your constructor in order to use the the curve + // m_refData = new wxPlotCurveRefData (or wxMySubclassedPlotCurveRefData) } -bool wxPlotCurve::Ok() const -{ - return (M_PLOTCURVEDATA != NULL); -} +bool wxPlotCurve::Ok() const { return (M_PLOTCURVEDATA != NULL); } wxRect2DDouble wxPlotCurve::GetBoundingRect() const { - wxCHECK_MSG(Ok(), wxRect2DDouble(0,0,0,0), wxT("invalid plotcurve")); - return M_PLOTCURVEDATA->m_boundingRect; + wxCHECK_MSG(Ok(), wxRect2DDouble(0, 0, 0, 0), wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->m_boundingRect; } -void wxPlotCurve::SetBoundingRect( const wxRect2DDouble &rect ) +void wxPlotCurve::SetBoundingRect(const wxRect2DDouble &rect) { - wxCHECK_RET(Ok(), wxT("invalid plotcurve")); - M_PLOTCURVEDATA->m_boundingRect = rect; + wxCHECK_RET(Ok(), wxT("invalid plotcurve")); + M_PLOTCURVEDATA->m_boundingRect = rect; } //---------------------------------------------------------------------------- @@ -171,30 +145,36 @@ void wxPlotCurve::SetBoundingRect( const wxRect2DDouble &rect ) wxGenericPen wxPlotCurve::GetPen(wxPlotPen_Type colour_type) const { - wxCHECK_MSG(Ok(), wxGenericPen(), wxT("invalid plotcurve")); - wxCHECK_MSG((colour_type >= 0) && (colour_type < (int)M_PLOTCURVEDATA->m_pens.GetCount()), wxGenericPen(), wxT("invalid plot colour")); + wxCHECK_MSG(Ok(), wxGenericPen(), wxT("invalid plotcurve")); + wxCHECK_MSG((colour_type >= 0) && (colour_type < (int)M_PLOTCURVEDATA->m_pens.GetCount()), + wxGenericPen(), wxT("invalid plot colour")); - return M_PLOTCURVEDATA->m_pens[colour_type]; + return M_PLOTCURVEDATA->m_pens[colour_type]; } -void wxPlotCurve::SetPen(wxPlotPen_Type colour_type, const wxGenericPen &pen ) +void wxPlotCurve::SetPen(wxPlotPen_Type colour_type, const wxGenericPen &pen) { - wxCHECK_RET(Ok(), wxT("invalid plotcurve")); - wxCHECK_RET((colour_type >= 0) && (colour_type < (int)M_PLOTCURVEDATA->m_pens.GetCount()), wxT("invalid plot colour")); + wxCHECK_RET(Ok(), wxT("invalid plotcurve")); + wxCHECK_RET((colour_type >= 0) && (colour_type < (int)M_PLOTCURVEDATA->m_pens.GetCount()), + wxT("invalid plot colour")); - M_PLOTCURVEDATA->m_pens[colour_type] = pen; + M_PLOTCURVEDATA->m_pens[colour_type] = pen; } wxGenericPen wxPlotCurve::GetDefaultPen(wxPlotPen_Type colour_type) { - InitPlotCurveDefaultPens(); - wxCHECK_MSG((colour_type >= 0) && (colour_type < int(wxPlotCurveRefData::sm_defaultPens.GetCount())), wxGenericPen(), wxT("invalid plot colour")); - return wxPlotCurveRefData::sm_defaultPens[colour_type]; + InitPlotCurveDefaultPens(); + wxCHECK_MSG((colour_type >= 0) && + (colour_type < int(wxPlotCurveRefData::sm_defaultPens.GetCount())), + wxGenericPen(), wxT("invalid plot colour")); + return wxPlotCurveRefData::sm_defaultPens[colour_type]; } -void wxPlotCurve::SetDefaultPen(wxPlotPen_Type colour_type, const wxGenericPen &pen ) +void wxPlotCurve::SetDefaultPen(wxPlotPen_Type colour_type, const wxGenericPen &pen) { - InitPlotCurveDefaultPens(); - wxCHECK_RET((colour_type >= 0) && (colour_type < int(wxPlotCurveRefData::sm_defaultPens.GetCount())), wxT("invalid plot colour")); - wxPlotCurveRefData::sm_defaultPens[colour_type] = pen; + InitPlotCurveDefaultPens(); + wxCHECK_RET((colour_type >= 0) && + (colour_type < int(wxPlotCurveRefData::sm_defaultPens.GetCount())), + wxT("invalid plot colour")); + wxPlotCurveRefData::sm_defaultPens[colour_type] = pen; } // ---------------------------------------------------------------------------- @@ -203,104 +183,105 @@ void wxPlotCurve::SetDefaultPen(wxPlotPen_Type colour_type, const wxGenericPen & size_t wxPlotCurve::GetOptionCount() const { - wxCHECK_MSG(M_PLOTCURVEDATA, 0, wxT("invalid plotcurve")); - return M_PLOTCURVEDATA->m_optionNames.GetCount(); + wxCHECK_MSG(M_PLOTCURVEDATA, 0, wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->m_optionNames.GetCount(); } -int wxPlotCurve::HasOption(const wxString& name) const +int wxPlotCurve::HasOption(const wxString &name) const { - wxCHECK_MSG(M_PLOTCURVEDATA, wxNOT_FOUND, wxT("invalid plotcurve")); - return M_PLOTCURVEDATA->m_optionNames.Index(name); + wxCHECK_MSG(M_PLOTCURVEDATA, wxNOT_FOUND, wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->m_optionNames.Index(name); } -wxString wxPlotCurve::GetOptionName( size_t i ) const +wxString wxPlotCurve::GetOptionName(size_t i) const { - wxCHECK_MSG(M_PLOTCURVEDATA&&(im_optionNames[i]; + wxCHECK_MSG(M_PLOTCURVEDATA && (i < GetOptionCount()), wxEmptyString, wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->m_optionNames[i]; } -wxString wxPlotCurve::GetOptionValue( size_t i ) const +wxString wxPlotCurve::GetOptionValue(size_t i) const { - wxCHECK_MSG(M_PLOTCURVEDATA&&(im_optionValues[i]; + wxCHECK_MSG(M_PLOTCURVEDATA && (i < GetOptionCount()), wxEmptyString, wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->m_optionValues[i]; } -int wxPlotCurve::SetOption(const wxString& name, const wxString& value, bool update) +int wxPlotCurve::SetOption(const wxString &name, const wxString &value, bool update) { - wxCHECK_MSG(M_PLOTCURVEDATA, -1, wxT("invalid plotcurve")); - int n = M_PLOTCURVEDATA->m_optionNames.Index(name); - if (n == wxNOT_FOUND) - { - n = M_PLOTCURVEDATA->m_optionNames.Add(name); - M_PLOTCURVEDATA->m_optionValues.Insert(value, n); - } - else if (update) - { - M_PLOTCURVEDATA->m_optionNames[n] = name; - M_PLOTCURVEDATA->m_optionValues[n] = value; - } - return n; + wxCHECK_MSG(M_PLOTCURVEDATA, -1, wxT("invalid plotcurve")); + int n = M_PLOTCURVEDATA->m_optionNames.Index(name); + if (n == wxNOT_FOUND) { + n = M_PLOTCURVEDATA->m_optionNames.Add(name); + M_PLOTCURVEDATA->m_optionValues.Insert(value, n); + } + else if (update) { + M_PLOTCURVEDATA->m_optionNames[n] = name; + M_PLOTCURVEDATA->m_optionValues[n] = value; + } + return n; } int wxPlotCurve::SetOption(const wxString &name, int option, bool update) { - return SetOption(name, wxString::Format(wxT("%d"), option), update); + return SetOption(name, wxString::Format(wxT("%d"), option), update); } -wxString wxPlotCurve::GetOption(const wxString& name) const +wxString wxPlotCurve::GetOption(const wxString &name) const { - wxCHECK_MSG(M_PLOTCURVEDATA, wxEmptyString, wxT("invalid plotcurve")); - int n = M_PLOTCURVEDATA->m_optionNames.Index(name); + wxCHECK_MSG(M_PLOTCURVEDATA, wxEmptyString, wxT("invalid plotcurve")); + int n = M_PLOTCURVEDATA->m_optionNames.Index(name); - if (n == wxNOT_FOUND) - return wxEmptyString; + if (n == wxNOT_FOUND) { + return wxEmptyString; + } - return M_PLOTCURVEDATA->m_optionValues[n]; + return M_PLOTCURVEDATA->m_optionValues[n]; } -int wxPlotCurve::GetOption(const wxString& name, wxString &value ) const +int wxPlotCurve::GetOption(const wxString &name, wxString &value) const { - wxCHECK_MSG(M_PLOTCURVEDATA, wxNOT_FOUND, wxT("invalid plotcurve")); + wxCHECK_MSG(M_PLOTCURVEDATA, wxNOT_FOUND, wxT("invalid plotcurve")); - int n = M_PLOTCURVEDATA->m_optionNames.Index(name); + int n = M_PLOTCURVEDATA->m_optionNames.Index(name); - if (n == wxNOT_FOUND) return wxNOT_FOUND; + if (n == wxNOT_FOUND) { + return wxNOT_FOUND; + } - value = M_PLOTCURVEDATA->m_optionValues[n]; - return n; + value = M_PLOTCURVEDATA->m_optionValues[n]; + return n; } -int wxPlotCurve::GetOptionInt(const wxString& name) const +int wxPlotCurve::GetOptionInt(const wxString &name) const { - wxCHECK_MSG(M_PLOTCURVEDATA, 0, wxT("invalid plotcurve")); - return wxAtoi(GetOption(name)); + wxCHECK_MSG(M_PLOTCURVEDATA, 0, wxT("invalid plotcurve")); + return wxAtoi(GetOption(name)); } wxSortedArrayString wxPlotCurve::GetOptionNames() const { - wxCHECK_MSG(M_PLOTCURVEDATA, wxArrayString(), wxT("invalid plotcurve")); - return M_PLOTCURVEDATA->m_optionNames; + wxCHECK_MSG(M_PLOTCURVEDATA, wxArrayString(), wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->m_optionNames; } wxArrayString wxPlotCurve::GetOptionValues() const { - wxCHECK_MSG(M_PLOTCURVEDATA, wxArrayString(), wxT("invalid plotcurve")); - return M_PLOTCURVEDATA->m_optionValues; + wxCHECK_MSG(M_PLOTCURVEDATA, wxArrayString(), wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->m_optionValues; } //------------------------------------------------------------------------- -void wxPlotCurve::SetClientObject( wxClientData *data ) +void wxPlotCurve::SetClientObject(wxClientData *data) { - wxCHECK_RET(M_PLOTCURVEDATA, wxT("invalid plotcurve")); - M_PLOTCURVEDATA->SetClientObject(data); + wxCHECK_RET(M_PLOTCURVEDATA, wxT("invalid plotcurve")); + M_PLOTCURVEDATA->SetClientObject(data); } wxClientData *wxPlotCurve::GetClientObject() const { - wxCHECK_MSG(M_PLOTCURVEDATA, NULL, wxT("invalid plotcurve")); - return M_PLOTCURVEDATA->GetClientObject(); + wxCHECK_MSG(M_PLOTCURVEDATA, NULL, wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->GetClientObject(); } -void wxPlotCurve::SetClientData( void *data ) +void wxPlotCurve::SetClientData(void *data) { - wxCHECK_RET(M_PLOTCURVEDATA, wxT("invalid plotcurve")); - M_PLOTCURVEDATA->SetClientData(data); + wxCHECK_RET(M_PLOTCURVEDATA, wxT("invalid plotcurve")); + M_PLOTCURVEDATA->SetClientData(data); } void *wxPlotCurve::GetClientData() const { - wxCHECK_MSG(M_PLOTCURVEDATA, NULL, wxT("invalid plotcurve")); - return M_PLOTCURVEDATA->GetClientData(); + wxCHECK_MSG(M_PLOTCURVEDATA, NULL, wxT("invalid plotcurve")); + return M_PLOTCURVEDATA->GetClientData(); } diff --git a/src/labenski/src/plotdata.cpp b/src/labenski/src/plotdata.cpp index dd0801aa5..cfad21bf1 100644 --- a/src/labenski/src/plotdata.cpp +++ b/src/labenski/src/plotdata.cpp @@ -12,14 +12,14 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/bitmap.h" - #include "wx/textdlg.h" - #include "wx/msgdlg.h" - #include "wx/dcmemory.h" +#include "wx/bitmap.h" +#include "wx/textdlg.h" +#include "wx/msgdlg.h" +#include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/file.h" @@ -35,967 +35,1004 @@ #ifdef wxFinite #undef wxFinite #define wxFinite(x) std::isfinite(x) -#endif // wxFinite +#endif // wxFinite #define wxPLOT_MAX_DATA_COLUMNS 64 -#define CHECK_INDEX_COUNT_MSG(index, count, max_count, ret) \ - wxCHECK_MSG((int(index) >= 0) && (int(index)+int(count) <= int(max_count)), ret, wxT("invalid index or count")) -#define CHECK_INDEX_COUNT_RET(index, count, max_count) \ - wxCHECK_RET((int(index) >= 0) && (int(index)+int(count) <= int(max_count)), wxT("invalid index or count")) - -#define CHECK_START_END_INDEX_MSG(start_index, end_index, max_count, ret) \ - wxCHECK_MSG((int(start_index)>=0)&&(int(start_index)int(start_index))&&(int(end_index)=0)&&(int(start_index)int(start_index))&&(int(end_index)= 0) && (int(index) + int(count) <= int(max_count)), ret, \ + wxT("invalid index or count")) +#define CHECK_INDEX_COUNT_RET(index, count, max_count) \ + wxCHECK_RET((int(index) >= 0) && (int(index) + int(count) <= int(max_count)), \ + wxT("invalid index or count")) + +#define CHECK_START_END_INDEX_MSG(start_index, end_index, max_count, ret) \ + wxCHECK_MSG((int(start_index) >= 0) && (int(start_index) < int(max_count)) && \ + (int(end_index) > int(start_index)) && (int(end_index) < int(max_count)), \ + ret, wxT("Invalid data index")) +#define CHECK_START_END_INDEX_RET(start_index, end_index, max_count) \ + wxCHECK_RET((int(start_index) >= 0) && (int(start_index) < int(max_count)) && \ + (int(end_index) > int(start_index)) && (int(end_index) < int(max_count)), \ + wxT("Invalid data index")) //---------------------------------------------------------------------------- // wxPlotDataRefData //---------------------------------------------------------------------------- -class wxPlotDataRefData: public wxPlotCurveRefData -{ +class wxPlotDataRefData : public wxPlotCurveRefData { public: - wxPlotDataRefData(); - wxPlotDataRefData(const wxPlotDataRefData& data); - virtual ~wxPlotDataRefData(); + wxPlotDataRefData(); + wxPlotDataRefData(const wxPlotDataRefData &data); + virtual ~wxPlotDataRefData(); - void Destroy(); - void CopyData(const wxPlotDataRefData &source); - void CopyExtra(const wxPlotDataRefData &source); + void Destroy(); + void CopyData(const wxPlotDataRefData &source); + void CopyExtra(const wxPlotDataRefData &source); - int m_count; + int m_count; - double *m_Xdata; - double *m_Ydata; - double *m_Yidata; // imaginary component, not normally used (see FFT) - bool m_static; + double *m_Xdata; + double *m_Ydata; + double *m_Yidata; // imaginary component, not normally used (see FFT) + bool m_static; - bool m_Xordered; + bool m_Xordered; - wxBitmap m_normalSymbol, - m_activeSymbol, - m_selectedSymbol; + wxBitmap m_normalSymbol, m_activeSymbol, m_selectedSymbol; }; wxPlotDataRefData::wxPlotDataRefData() : wxPlotCurveRefData() { - m_count = 0; + m_count = 0; - m_Xdata = (double*)NULL; - m_Ydata = (double*)NULL; - m_Yidata = (double*)NULL; + m_Xdata = (double *)NULL; + m_Ydata = (double *)NULL; + m_Yidata = (double *)NULL; - m_static = false; + m_static = false; - m_Xordered = false; + m_Xordered = false; - m_normalSymbol = wxPlotSymbolNormal; - m_activeSymbol = wxPlotSymbolActive; - m_selectedSymbol = wxPlotSymbolSelected; + m_normalSymbol = wxPlotSymbolNormal; + m_activeSymbol = wxPlotSymbolActive; + m_selectedSymbol = wxPlotSymbolSelected; } -wxPlotDataRefData::wxPlotDataRefData(const wxPlotDataRefData& data) - :wxPlotCurveRefData() +wxPlotDataRefData::wxPlotDataRefData(const wxPlotDataRefData &data) : wxPlotCurveRefData() { - CopyData(data); - CopyExtra(data); + CopyData(data); + CopyExtra(data); } -wxPlotDataRefData::~wxPlotDataRefData() -{ - Destroy(); -} +wxPlotDataRefData::~wxPlotDataRefData() { Destroy(); } void wxPlotDataRefData::Destroy() { - if (!m_static) - { - if ( m_Xdata ) free( m_Xdata ); - if ( m_Ydata ) free( m_Ydata ); - if ( m_Yidata ) free( m_Yidata ); + if (!m_static) { + if (m_Xdata) { + free(m_Xdata); + } + if (m_Ydata) { + free(m_Ydata); } + if (m_Yidata) { + free(m_Yidata); + } + } - m_count = 0; - m_Xdata = NULL; - m_Ydata = NULL; - m_Yidata = NULL; - m_Xordered = false; + m_count = 0; + m_Xdata = NULL; + m_Ydata = NULL; + m_Yidata = NULL; + m_Xordered = false; } void wxPlotDataRefData::CopyData(const wxPlotDataRefData &source) { - Destroy(); + Destroy(); - m_count = source.m_count; - m_static = false; // we're creating our own copy - m_Xordered = source.m_Xordered; + m_count = source.m_count; + m_static = false; // we're creating our own copy + m_Xordered = source.m_Xordered; - if (m_count && source.m_Xdata) - { - m_Xdata = (double*)malloc( m_count*sizeof(double) ); - memcpy( m_Xdata, source.m_Xdata, m_count*sizeof(double) ); - } - if (m_count && source.m_Ydata) - { - m_Ydata = (double*)malloc( m_count*sizeof(double) ); - memcpy( m_Ydata, source.m_Ydata, m_count*sizeof(double) ); - } - if (m_count && source.m_Yidata) - { - m_Yidata = (double*)malloc( m_count*sizeof(double) ); - memcpy( m_Ydata, source.m_Yidata, m_count*sizeof(double) ); - } + if (m_count && source.m_Xdata) { + m_Xdata = (double *)malloc(m_count * sizeof(double)); + memcpy(m_Xdata, source.m_Xdata, m_count * sizeof(double)); + } + if (m_count && source.m_Ydata) { + m_Ydata = (double *)malloc(m_count * sizeof(double)); + memcpy(m_Ydata, source.m_Ydata, m_count * sizeof(double)); + } + if (m_count && source.m_Yidata) { + m_Yidata = (double *)malloc(m_count * sizeof(double)); + memcpy(m_Ydata, source.m_Yidata, m_count * sizeof(double)); + } } void wxPlotDataRefData::CopyExtra(const wxPlotDataRefData &source) { - wxPlotCurveRefData::Copy(source); + wxPlotCurveRefData::Copy(source); - m_normalSymbol = source.m_normalSymbol; - m_activeSymbol = source.m_activeSymbol; - m_selectedSymbol = source.m_selectedSymbol; + m_normalSymbol = source.m_normalSymbol; + m_activeSymbol = source.m_activeSymbol; + m_selectedSymbol = source.m_selectedSymbol; } -#define M_PLOTDATA ((wxPlotDataRefData*)m_refData) +#define M_PLOTDATA ((wxPlotDataRefData *)m_refData) //----------------------------------------------------------------------------- // wxPlotData //----------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPlotData, wxPlotCurve) -wxObjectRefData *wxPlotData::CreateRefData() const -{ - return new wxPlotDataRefData; -} +wxObjectRefData *wxPlotData::CreateRefData() const { return new wxPlotDataRefData; } wxObjectRefData *wxPlotData::CloneRefData(const wxObjectRefData *data) const { - return new wxPlotDataRefData(*(const wxPlotDataRefData *)data); + return new wxPlotDataRefData(*(const wxPlotDataRefData *)data); } -bool wxPlotData::Ok() const -{ - return m_refData && (M_PLOTDATA->m_count > 0); -} +bool wxPlotData::Ok() const { return m_refData && (M_PLOTDATA->m_count > 0); } -void wxPlotData::Destroy() -{ - UnRef(); -} +void wxPlotData::Destroy() { UnRef(); } int wxPlotData::GetCount() const { - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); - return M_PLOTDATA->m_count; + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxPlotData")); + return M_PLOTDATA->m_count; } -bool wxPlotData::Create( const wxPlotData& plotData ) +bool wxPlotData::Create(const wxPlotData &plotData) { - wxCHECK_MSG(plotData.Ok(), false, wxT("Invalid wxPlotData")); + wxCHECK_MSG(plotData.Ok(), false, wxT("Invalid wxPlotData")); - Ref(plotData); - CalcBoundingRect(); // just to be sure we're ok - return true; + Ref(plotData); + CalcBoundingRect(); // just to be sure we're ok + return true; } -bool wxPlotData::Create( const wxPlotFunction &plotFunc, double x_start, double dx, int points ) +bool wxPlotData::Create(const wxPlotFunction &plotFunc, double x_start, double dx, int points) { - wxCHECK_MSG(plotFunc.Ok(), false, wxT("Invalid wxPlotFunction")); - wxCHECK_MSG(wxFinite(x_start) && wxFinite(dx), false, wxT("values are NaN")); + wxCHECK_MSG(plotFunc.Ok(), false, wxT("Invalid wxPlotFunction")); + wxCHECK_MSG(wxFinite(x_start) && wxFinite(dx), false, wxT("values are NaN")); - if (!Create(points, false)) return false; // this checks points + if (!Create(points, false)) { + return false; // this checks points + } - double x = x_start, y = 0; - double *x_data = M_PLOTDATA->m_Xdata; - double *y_data = M_PLOTDATA->m_Ydata; + double x = x_start, y = 0; + double *x_data = M_PLOTDATA->m_Xdata; + double *y_data = M_PLOTDATA->m_Ydata; - wxPlotFunction pf = plotFunc; // since it's passed as const + wxPlotFunction pf = plotFunc; // since it's passed as const - for (int i = 0; i < points; i++, x += dx, x_data++, y_data++) - { - if (wxFinite(x)) - { - y = pf.GetY(x); - *x_data = x; - *y_data = wxFinite(y) ? y : 0; - } - else - { - *x_data = 0; - *y_data = 0; - } + for (int i = 0; i < points; i++, x += dx, x_data++, y_data++) { + if (wxFinite(x)) { + y = pf.GetY(x); + *x_data = x; + *y_data = wxFinite(y) ? y : 0; } + else { + *x_data = 0; + *y_data = 0; + } + } - CalcBoundingRect(); - return true; + CalcBoundingRect(); + return true; } -bool wxPlotData::Create( int points, bool zero ) +bool wxPlotData::Create(int points, bool zero) { - wxCHECK_MSG( points > 0, false, wxT("Can't create wxPlotData with < 1 points") ); + wxCHECK_MSG(points > 0, false, wxT("Can't create wxPlotData with < 1 points")); - UnRef(); - m_refData = new wxPlotDataRefData(); + UnRef(); + m_refData = new wxPlotDataRefData(); - if ( !M_PLOTDATA ) - { - wxFAIL_MSG(wxT("memory allocation error creating plot")); - return false; - } + if (!M_PLOTDATA) { + wxFAIL_MSG(wxT("memory allocation error creating plot")); + return false; + } - M_PLOTDATA->m_count = points; - M_PLOTDATA->m_Xdata = (double*)malloc( points*sizeof(double) ); - M_PLOTDATA->m_Ydata = (double*)malloc( points*sizeof(double) ); - if (!M_PLOTDATA->m_Xdata || !M_PLOTDATA->m_Ydata) - { - UnRef(); - wxFAIL_MSG(wxT("memory allocation error creating plot")); - return false; - } + M_PLOTDATA->m_count = points; + M_PLOTDATA->m_Xdata = (double *)malloc(points * sizeof(double)); + M_PLOTDATA->m_Ydata = (double *)malloc(points * sizeof(double)); + if (!M_PLOTDATA->m_Xdata || !M_PLOTDATA->m_Ydata) { + UnRef(); + wxFAIL_MSG(wxT("memory allocation error creating plot")); + return false; + } - if (zero) - { - memset(M_PLOTDATA->m_Xdata, 0, points*sizeof(double)); - memset(M_PLOTDATA->m_Ydata, 0, points*sizeof(double)); - } + if (zero) { + memset(M_PLOTDATA->m_Xdata, 0, points * sizeof(double)); + memset(M_PLOTDATA->m_Ydata, 0, points * sizeof(double)); + } - return true; + return true; } -bool wxPlotData::Create( double *x_data, double *y_data, int points, bool static_data ) +bool wxPlotData::Create(double *x_data, double *y_data, int points, bool static_data) { - wxCHECK_MSG((points > 0) && x_data && y_data, false, - wxT("Can't create wxPlotData with < 1 points or invalid data") ); + wxCHECK_MSG((points > 0) && x_data && y_data, false, + wxT("Can't create wxPlotData with < 1 points or invalid data")); - UnRef(); - m_refData = new wxPlotDataRefData(); + UnRef(); + m_refData = new wxPlotDataRefData(); - if ( !M_PLOTDATA ) - { - wxFAIL_MSG(wxT("memory allocation error creating plot")); - return false; - } + if (!M_PLOTDATA) { + wxFAIL_MSG(wxT("memory allocation error creating plot")); + return false; + } - M_PLOTDATA->m_Xdata = x_data; - M_PLOTDATA->m_Ydata = y_data; - M_PLOTDATA->m_count = points; - M_PLOTDATA->m_static = static_data; + M_PLOTDATA->m_Xdata = x_data; + M_PLOTDATA->m_Ydata = y_data; + M_PLOTDATA->m_count = points; + M_PLOTDATA->m_static = static_data; - CalcBoundingRect(); - return true; + CalcBoundingRect(); + return true; } -bool wxPlotData::Copy( const wxPlotData &source, bool copy_all ) +bool wxPlotData::Copy(const wxPlotData &source, bool copy_all) { - wxCHECK_MSG( source.Ok(), false, wxT("Invalid wxPlotData") ); + wxCHECK_MSG(source.Ok(), false, wxT("Invalid wxPlotData")); - int count = source.GetCount(); + int count = source.GetCount(); - if (!Create(count, false)) return false; + if (!Create(count, false)) { + return false; + } - memcpy( M_PLOTDATA->m_Xdata, source.GetXData(), count*sizeof(double) ); - memcpy( M_PLOTDATA->m_Ydata, source.GetYData(), count*sizeof(double) ); + memcpy(M_PLOTDATA->m_Xdata, source.GetXData(), count * sizeof(double)); + memcpy(M_PLOTDATA->m_Ydata, source.GetYData(), count * sizeof(double)); - if (source.GetYiData()) - { - M_PLOTDATA->m_Yidata = (double*)malloc(count*sizeof(double)); - if (!M_PLOTDATA->m_Yidata) - { - UnRef(); - return false; - } - memcpy( M_PLOTDATA->m_Yidata, source.GetYiData(), count*sizeof(double) ); + if (source.GetYiData()) { + M_PLOTDATA->m_Yidata = (double *)malloc(count * sizeof(double)); + if (!M_PLOTDATA->m_Yidata) { + UnRef(); + return false; } + memcpy(M_PLOTDATA->m_Yidata, source.GetYiData(), count * sizeof(double)); + } - if (copy_all) - CopyExtra(source); + if (copy_all) { + CopyExtra(source); + } - CalcBoundingRect(); - return true; + CalcBoundingRect(); + return true; } -bool wxPlotData::CopyExtra( const wxPlotData &source ) +bool wxPlotData::CopyExtra(const wxPlotData &source) { - wxCHECK_MSG( Ok() && source.Ok(), false, wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok() && source.Ok(), false, wxT("Invalid wxPlotData")); - M_PLOTDATA->Copy(*((wxPlotDataRefData*)source.GetRefData())); + M_PLOTDATA->Copy(*((wxPlotDataRefData *)source.GetRefData())); - return true; + return true; } -bool wxPlotData::Resize( int new_size, bool zero ) +bool wxPlotData::Resize(int new_size, bool zero) { - wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); - wxCHECK_MSG(new_size > 0, false, wxT("Can't create wxPlotData with < 1 points")); - if (M_PLOTDATA->m_count == new_size) - return true; + wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); + wxCHECK_MSG(new_size > 0, false, wxT("Can't create wxPlotData with < 1 points")); + if (M_PLOTDATA->m_count == new_size) { + return true; + } - M_PLOTDATA->m_Xdata = (double*)realloc( M_PLOTDATA->m_Xdata, new_size*sizeof(double) ); - M_PLOTDATA->m_Ydata = (double*)realloc( M_PLOTDATA->m_Ydata, new_size*sizeof(double) ); + M_PLOTDATA->m_Xdata = (double *)realloc(M_PLOTDATA->m_Xdata, new_size * sizeof(double)); + M_PLOTDATA->m_Ydata = (double *)realloc(M_PLOTDATA->m_Ydata, new_size * sizeof(double)); - bool has_yi = false; - if (M_PLOTDATA->m_Yidata) - { - has_yi = true; - M_PLOTDATA->m_Yidata = (double*)realloc( M_PLOTDATA->m_Yidata, new_size*sizeof(double) ); - } + bool has_yi = false; + if (M_PLOTDATA->m_Yidata) { + has_yi = true; + M_PLOTDATA->m_Yidata = (double *)realloc(M_PLOTDATA->m_Yidata, new_size * sizeof(double)); + } - // realloc failed - if (!M_PLOTDATA->m_Xdata || !M_PLOTDATA->m_Ydata || (has_yi && (!M_PLOTDATA->m_Yidata))) - { - UnRef(); - return false; - } + // realloc failed + if (!M_PLOTDATA->m_Xdata || !M_PLOTDATA->m_Ydata || (has_yi && (!M_PLOTDATA->m_Yidata))) { + UnRef(); + return false; + } - if (zero && (M_PLOTDATA->m_count < new_size )) - { - int old_count = M_PLOTDATA->m_count; - int points = new_size - M_PLOTDATA->m_count; - memset(M_PLOTDATA->m_Xdata + old_count, 0, points*sizeof(double)); - memset(M_PLOTDATA->m_Ydata + old_count, 0, points*sizeof(double)); - if (M_PLOTDATA->m_Yidata) - memset(M_PLOTDATA->m_Yidata + old_count, 0, points*sizeof(double)); + if (zero && (M_PLOTDATA->m_count < new_size)) { + int old_count = M_PLOTDATA->m_count; + int points = new_size - M_PLOTDATA->m_count; + memset(M_PLOTDATA->m_Xdata + old_count, 0, points * sizeof(double)); + memset(M_PLOTDATA->m_Ydata + old_count, 0, points * sizeof(double)); + if (M_PLOTDATA->m_Yidata) { + memset(M_PLOTDATA->m_Yidata + old_count, 0, points * sizeof(double)); } + } - M_PLOTDATA->m_count = new_size; - CalcBoundingRect(); - return true; + M_PLOTDATA->m_count = new_size; + CalcBoundingRect(); + return true; } -bool wxPlotData::Resize( int new_size, double dx, double y ) +bool wxPlotData::Resize(int new_size, double dx, double y) { - wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); - int orig_count = GetCount(); - if (!Resize(new_size, false)) return false; + wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); + int orig_count = GetCount(); + if (!Resize(new_size, false)) { + return false; + } - SetYValues(orig_count, -1, y); - SetXStepValues(orig_count, -1, M_PLOTDATA->m_Xdata[orig_count - 1], dx); - return true; + SetYValues(orig_count, -1, y); + SetXStepValues(orig_count, -1, M_PLOTDATA->m_Xdata[orig_count - 1], dx); + return true; } -wxPlotData wxPlotData::Append( const wxPlotData &source ) const +wxPlotData wxPlotData::Append(const wxPlotData &source) const { - wxCHECK_MSG( Ok() && source.Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok() && source.Ok(), wxPlotData(), wxT("Invalid wxPlotData")); - int count = M_PLOTDATA->m_count; - int src_count = source.GetCount(); + int count = M_PLOTDATA->m_count; + int src_count = source.GetCount(); - wxPlotData newCurve(count + src_count, false); - if (!newCurve.Ok()) return newCurve; + wxPlotData newCurve(count + src_count, false); + if (!newCurve.Ok()) { + return newCurve; + } - bool has_yi = false; - if (M_PLOTDATA->m_Yidata && source.GetYiData()) - { - has_yi = true; - double *yi = (double*)malloc((count+src_count)*sizeof(double)); - if (!yi) - { - newCurve.Destroy(); - return newCurve; - } - newCurve.SetYiData(yi); + bool has_yi = false; + if (M_PLOTDATA->m_Yidata && source.GetYiData()) { + has_yi = true; + double *yi = (double *)malloc((count + src_count) * sizeof(double)); + if (!yi) { + newCurve.Destroy(); + return newCurve; } + newCurve.SetYiData(yi); + } - memcpy(newCurve.GetXData(), M_PLOTDATA->m_Xdata, count*sizeof(double)); - memcpy(newCurve.GetYData(), M_PLOTDATA->m_Ydata, count*sizeof(double)); - if (has_yi) - memcpy(newCurve.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); + memcpy(newCurve.GetXData(), M_PLOTDATA->m_Xdata, count * sizeof(double)); + memcpy(newCurve.GetYData(), M_PLOTDATA->m_Ydata, count * sizeof(double)); + if (has_yi) { + memcpy(newCurve.GetYiData(), M_PLOTDATA->m_Yidata, count * sizeof(double)); + } - memcpy(newCurve.GetXData()+count, source.GetXData(), src_count*sizeof(double)); - memcpy(newCurve.GetYData()+count, source.GetYData(), src_count*sizeof(double)); - if (has_yi) - memcpy(newCurve.GetYiData(), source.GetYiData(), src_count*sizeof(double)); + memcpy(newCurve.GetXData() + count, source.GetXData(), src_count * sizeof(double)); + memcpy(newCurve.GetYData() + count, source.GetYData(), src_count * sizeof(double)); + if (has_yi) { + memcpy(newCurve.GetYiData(), source.GetYiData(), src_count * sizeof(double)); + } - newCurve.CalcBoundingRect(); - newCurve.CopyExtra( *this ); - return newCurve; + newCurve.CalcBoundingRect(); + newCurve.CopyExtra(*this); + return newCurve; } -wxPlotData wxPlotData::Insert( const wxPlotData &source, int index ) const +wxPlotData wxPlotData::Insert(const wxPlotData &source, int index) const { - wxCHECK_MSG( Ok() && source.Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); - wxPCHECK_MINMAX_MSG(index, 0, M_PLOTDATA->m_count, wxPlotData(), wxT("invalid index")); - - int count = M_PLOTDATA->m_count; - int src_count = source.GetCount(); - - wxPlotData newCurve(count + src_count, false); - if (!newCurve.Ok()) return newCurve; - - double *src_x_data = source.GetXData(); - double *src_y_data = source.GetYData(); - double *src_yi_data = source.GetYiData(); - - double *x_data = M_PLOTDATA->m_Xdata; - double *y_data = M_PLOTDATA->m_Ydata; - double *yi_data = M_PLOTDATA->m_Yidata; + wxCHECK_MSG(Ok() && source.Ok(), wxPlotData(), wxT("Invalid wxPlotData")); + wxPCHECK_MINMAX_MSG(index, 0, M_PLOTDATA->m_count, wxPlotData(), wxT("invalid index")); - bool has_yi = false; - if (yi_data && src_yi_data) - { - has_yi = true; - double *yi = (double*)malloc((count+src_count)*sizeof(double)); - if (!yi) - { - newCurve.Destroy(); - return newCurve; - } - newCurve.SetYiData(yi); - } + int count = M_PLOTDATA->m_count; + int src_count = source.GetCount(); - double *new_Xdata = newCurve.GetXData(); - double *new_Ydata = newCurve.GetYData(); - double *new_Yidata = newCurve.GetYiData(); - - if (index > 0) - { - memcpy(new_Xdata, x_data, index*sizeof(double)); - memcpy(new_Ydata, y_data, index*sizeof(double)); - if (has_yi) - memcpy(new_Yidata, yi_data, index*sizeof(double)); - } - memcpy(new_Xdata+index, src_x_data, src_count*sizeof(double)); - memcpy(new_Ydata+index, src_y_data, src_count*sizeof(double)); - if (has_yi) - memcpy(new_Yidata+index, src_yi_data, src_count*sizeof(double)); - - memcpy(new_Xdata+index+src_count, x_data+index, (count-index)*sizeof(double)); - memcpy(new_Ydata+index+src_count, y_data+index, (count-index)*sizeof(double)); - if (has_yi) - memcpy(new_Yidata+index+src_count, yi_data+index, (count-index)*sizeof(double)); - - newCurve.CalcBoundingRect(); - newCurve.CopyExtra( *this ); + wxPlotData newCurve(count + src_count, false); + if (!newCurve.Ok()) { return newCurve; + } + + double *src_x_data = source.GetXData(); + double *src_y_data = source.GetYData(); + double *src_yi_data = source.GetYiData(); + + double *x_data = M_PLOTDATA->m_Xdata; + double *y_data = M_PLOTDATA->m_Ydata; + double *yi_data = M_PLOTDATA->m_Yidata; + + bool has_yi = false; + if (yi_data && src_yi_data) { + has_yi = true; + double *yi = (double *)malloc((count + src_count) * sizeof(double)); + if (!yi) { + newCurve.Destroy(); + return newCurve; + } + newCurve.SetYiData(yi); + } + + double *new_Xdata = newCurve.GetXData(); + double *new_Ydata = newCurve.GetYData(); + double *new_Yidata = newCurve.GetYiData(); + + if (index > 0) { + memcpy(new_Xdata, x_data, index * sizeof(double)); + memcpy(new_Ydata, y_data, index * sizeof(double)); + if (has_yi) { + memcpy(new_Yidata, yi_data, index * sizeof(double)); + } + } + memcpy(new_Xdata + index, src_x_data, src_count * sizeof(double)); + memcpy(new_Ydata + index, src_y_data, src_count * sizeof(double)); + if (has_yi) { + memcpy(new_Yidata + index, src_yi_data, src_count * sizeof(double)); + } + + memcpy(new_Xdata + index + src_count, x_data + index, (count - index) * sizeof(double)); + memcpy(new_Ydata + index + src_count, y_data + index, (count - index) * sizeof(double)); + if (has_yi) { + memcpy(new_Yidata + index + src_count, yi_data + index, (count - index) * sizeof(double)); + } + + newCurve.CalcBoundingRect(); + newCurve.CopyExtra(*this); + return newCurve; } wxPlotData wxPlotData::Remove(int index, int count) const { - wxPlotData newCurve; - wxCHECK_MSG( Ok(), newCurve, wxT("Invalid wxPlotData") ); - if (count <= 0) count = M_PLOTDATA->m_count - index; - wxCHECK_MSG((index >= 0) && (index+count <= M_PLOTDATA->m_count), newCurve, wxT("invalid index")); + wxPlotData newCurve; + wxCHECK_MSG(Ok(), newCurve, wxT("Invalid wxPlotData")); + if (count <= 0) { + count = M_PLOTDATA->m_count - index; + } + wxCHECK_MSG((index >= 0) && (index + count <= M_PLOTDATA->m_count), newCurve, + wxT("invalid index")); - // should probably give an error here? - if ((index == 0) && (count < 0)) return newCurve; + // should probably give an error here? + if ((index == 0) && (count < 0)) { + return newCurve; + } - if (count < 0) // return first part - { - newCurve = GetSubPlotData(0, index); - } - else if (index == 0) // return last part - { - newCurve = GetSubPlotData(index+count, -1); - } - else // return first and last, removing middle - { - newCurve = GetSubPlotData(0, index); - if (index+count < M_PLOTDATA->m_count - 1) - newCurve = newCurve.Append(GetSubPlotData(index+count, -1)); + if (count < 0) // return first part + { + newCurve = GetSubPlotData(0, index); + } + else if (index == 0) // return last part + { + newCurve = GetSubPlotData(index + count, -1); + } + else // return first and last, removing middle + { + newCurve = GetSubPlotData(0, index); + if (index + count < M_PLOTDATA->m_count - 1) { + newCurve = newCurve.Append(GetSubPlotData(index + count, -1)); } + } - newCurve.CopyExtra( *this ); - return newCurve; + newCurve.CopyExtra(*this); + return newCurve; } wxPlotData wxPlotData::GetSubPlotData(int index, int count) const { - wxCHECK_MSG( Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); - if (count <= 0) count = M_PLOTDATA->m_count - index; - wxCHECK_MSG((index >= 0) && (index+count <= M_PLOTDATA->m_count), wxPlotData(), wxT("invalid index")); + wxCHECK_MSG(Ok(), wxPlotData(), wxT("Invalid wxPlotData")); + if (count <= 0) { + count = M_PLOTDATA->m_count - index; + } + wxCHECK_MSG((index >= 0) && (index + count <= M_PLOTDATA->m_count), wxPlotData(), + wxT("invalid index")); - wxPlotData newCurve(count, false); - if (!newCurve.Ok()) return newCurve; + wxPlotData newCurve(count, false); + if (!newCurve.Ok()) { + return newCurve; + } - bool has_yi = false; - if (M_PLOTDATA->m_Yidata) - { - has_yi = true; - double *yi = (double*)malloc(count*sizeof(double)); - newCurve.SetYiData(yi); - } + bool has_yi = false; + if (M_PLOTDATA->m_Yidata) { + has_yi = true; + double *yi = (double *)malloc(count * sizeof(double)); + newCurve.SetYiData(yi); + } - memcpy(newCurve.GetXData(), M_PLOTDATA->m_Xdata+index, count*sizeof(double)); - memcpy(newCurve.GetYData(), M_PLOTDATA->m_Ydata+index, count*sizeof(double)); - if (has_yi) - memcpy(newCurve.GetYiData(), M_PLOTDATA->m_Yidata+index, count*sizeof(double)); + memcpy(newCurve.GetXData(), M_PLOTDATA->m_Xdata + index, count * sizeof(double)); + memcpy(newCurve.GetYData(), M_PLOTDATA->m_Ydata + index, count * sizeof(double)); + if (has_yi) { + memcpy(newCurve.GetYiData(), M_PLOTDATA->m_Yidata + index, count * sizeof(double)); + } - newCurve.CalcBoundingRect(); - newCurve.CopyExtra( *this ); - return newCurve; + newCurve.CalcBoundingRect(); + newCurve.CopyExtra(*this); + return newCurve; } void wxPlotData::CalcBoundingRect() { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); - M_PLOTDATA->m_boundingRect = wxRect2DDouble(0, 0, 0, 0); + M_PLOTDATA->m_boundingRect = wxRect2DDouble(0, 0, 0, 0); - double *x_data = M_PLOTDATA->m_Xdata, - *y_data = M_PLOTDATA->m_Ydata; + double *x_data = M_PLOTDATA->m_Xdata, *y_data = M_PLOTDATA->m_Ydata; - double x = *x_data, - y = *y_data, - xmin = x, - xmax = x, - ymin = y, - ymax = y, - xlast = x; + double x = *x_data, y = *y_data, xmin = x, xmax = x, ymin = y, ymax = y, xlast = x; - bool xordered = true, valid = false; + bool xordered = true, valid = false; - int i, count = M_PLOTDATA->m_count; + int i, count = M_PLOTDATA->m_count; - for (i=0; i xmax ) xmax = x; + if (x < xmin) { + xmin = x; + } + else if (x > xmax) { + xmax = x; + } - if ( y < ymin ) ymin = y; - else if ( y > ymax ) ymax = y; + if (y < ymin) { + ymin = y; + } + else if (y > ymax) { + ymax = y; + } - if ( xlast > x ) xordered = false; - else xlast = x; + if (xlast > x) { + xordered = false; + } + else { + xlast = x; } + } - if (valid) - M_PLOTDATA->m_boundingRect = wxRect2DDouble(xmin, ymin, xmax-xmin, ymax-ymin); - else - M_PLOTDATA->m_boundingRect = wxRect2DDouble(0, 0, 0, 0); + if (valid) { + M_PLOTDATA->m_boundingRect = wxRect2DDouble(xmin, ymin, xmax - xmin, ymax - ymin); + } + else { + M_PLOTDATA->m_boundingRect = wxRect2DDouble(0, 0, 0, 0); + } - M_PLOTDATA->m_Xordered = xordered; + M_PLOTDATA->m_Xordered = xordered; } bool wxPlotData::GetIsXOrdered() const { - wxCHECK_MSG( Ok(), false, wxT("Invalid wxPlotData") ); - return M_PLOTDATA->m_Xordered; + wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); + return M_PLOTDATA->m_Xordered; } //---------------------------------------------------------------------------- // Load/Save Get/Set Filename, Header //---------------------------------------------------------------------------- -int NumberParse (double *nums, const wxString &string) +int NumberParse(double *nums, const wxString &string) { - const wxChar d1 = wxT(','); // 44; // comma - const wxChar d2 = wxT('\t'); // 9; // tab - const wxChar d3 = wxT(' '); // 32; // space - const wxChar d4 = wxT('\n'); // 13; // carrage return - const wxChar d5 = wxT('\r'); // 10; // line feed + const wxChar d1 = wxT(','); // 44; // comma + const wxChar d2 = wxT('\t'); // 9; // tab + const wxChar d3 = wxT(' '); // 32; // space + const wxChar d4 = wxT('\n'); // 13; // carrage return + const wxChar d5 = wxT('\r'); // 10; // line feed -// char *D = "D"; // for Quick Basic, uses 1D3 not 1E3 -// char *E = "E"; + // char *D = "D"; // for Quick Basic, uses 1D3 not 1E3 + // char *E = "E"; - const wxChar *s = string.GetData(); + const wxChar *s = string.GetData(); - int i, count = string.Length(); - double number; + int i, count = string.Length(); + double number; - int n = 0; - int start_word = -1; + int n = 0; + int start_word = -1; - for (i=0; i<=count; i++) - { - if ((*s == d1 || *s == d2 || *s == d2 || *s == d3 || *s == d4 || *s == d5) || (i >= count)) - { - if (start_word != -1) - { - if ( string.Mid(start_word, i - start_word).ToDouble(&number) ) - { - nums[n] = number; - n++; - if (n >= wxPLOT_MAX_DATA_COLUMNS) return n; - start_word = -1; - } - else - return n; - } + for (i = 0; i <= count; i++) { + if ((*s == d1 || *s == d2 || *s == d2 || *s == d3 || *s == d4 || *s == d5) || (i >= count)) { + if (start_word != -1) { + if (string.Mid(start_word, i - start_word).ToDouble(&number)) { + nums[n] = number; + n++; + if (n >= wxPLOT_MAX_DATA_COLUMNS) { + return n; + } + start_word = -1; } - else if (start_word == -1) start_word = i; - - if (*s == d4 || *s == d5) return n; + else { + return n; + } + } + } + else if (start_word == -1) { + start_word = i; + } - s++; + if (*s == d4 || *s == d5) { + return n; } - return n; + + s++; + } + return n; } -static char GetNextFileStreamChar( wxFileInputStream &fs ) +static char GetNextFileStreamChar(wxFileInputStream &fs) { - return fs.Eof() ? '\0' : fs.GetC(); + return fs.Eof() ? '\0' : fs.GetC(); -/* - if (fs.Eof()) return wxT('\0'); - // see txtstream.cpp, ReadLine() -#if wxUSE_UNICODE - // FIXME: this is only works for single byte encodings - // How-to read a single char in an unkown encoding??? - char buf[10] = {0}; - memset(buf, 0, 10*sizeof(char)); - buf[0] = fs.GetC(); - - wxChar wbuf[10] = {0}; - memset(wbuf, 0, 10*sizeof(wxChar)); - wxConvUTF8.MB2WC( wbuf, buf, 2 ); - wxChar c = wbuf[0]; -#else - wxChar c = fs.GetC(); -#endif - return c; -*/ + /* + if (fs.Eof()) return wxT('\0'); + // see txtstream.cpp, ReadLine() + #if wxUSE_UNICODE + // FIXME: this is only works for single byte encodings + // How-to read a single char in an unkown encoding??? + char buf[10] = {0}; + memset(buf, 0, 10*sizeof(char)); + buf[0] = fs.GetC(); + + wxChar wbuf[10] = {0}; + memset(wbuf, 0, 10*sizeof(wxChar)); + wxConvUTF8.MB2WC( wbuf, buf, 2 ); + wxChar c = wbuf[0]; + #else + wxChar c = fs.GetC(); + #endif + return c; + */ } -bool wxPlotData::LoadFile( const wxString &filename, int x_col, int y_col, int options ) +bool wxPlotData::LoadFile(const wxString &filename, int x_col, int y_col, int options) { - if (filename.IsEmpty()) return false; + if (filename.IsEmpty()) { + return false; + } - wxFile loadfile; - loadfile.Open( filename, wxFile::read ); - if (!loadfile.IsOpened()) return false; + wxFile loadfile; + loadfile.Open(filename, wxFile::read); + if (!loadfile.IsOpened()) { + return false; + } - wxFileInputStream fileStream( loadfile ); - if (!fileStream.Ok()) - { - loadfile.Close(); - return false; - } + wxFileInputStream fileStream(loadfile); + if (!fileStream.Ok()) { + loadfile.Close(); + return false; + } - wxEOL eol = wxEOL_NATIVE; - if (1) - { - while ((eol == wxEOL_NATIVE) && !fileStream.Eof()) - { - const char c = GetNextFileStreamChar(fileStream); + wxEOL eol = wxEOL_NATIVE; + if (1) { + while ((eol == wxEOL_NATIVE) && !fileStream.Eof()) { + const char c = GetNextFileStreamChar(fileStream); - if (c == '\n') - { - eol = wxEOL_UNIX; - } - else if (c == '\r') - { - const char cc = GetNextFileStreamChar(fileStream); + if (c == '\n') { + eol = wxEOL_UNIX; + } + else if (c == '\r') { + const char cc = GetNextFileStreamChar(fileStream); - if (cc == '\n') - eol = wxEOL_DOS; - else - eol = wxEOL_MAC; - } + if (cc == '\n') { + eol = wxEOL_DOS; } + else { + eol = wxEOL_MAC; + } + } } + } - // Rewind file - fileStream.SeekI(off_t(0)); + // Rewind file + fileStream.SeekI(off_t(0)); - wxTextInputStream textstream( fileStream ); + wxTextInputStream textstream(fileStream); - int allocated_data = 400; - double *x_data = (double*)malloc(allocated_data*sizeof(double)); - double *y_data = (double*)malloc(allocated_data*sizeof(double)); + int allocated_data = 400; + double *x_data = (double *)malloc(allocated_data * sizeof(double)); + double *y_data = (double *)malloc(allocated_data * sizeof(double)); - if (!x_data || !y_data) - { - if (x_data) free(x_data); - if (y_data) free(y_data); - return false; + if (!x_data || !y_data) { + if (x_data) { + free(x_data); } + if (y_data) { + free(y_data); + } + return false; + } - int points = 0, line_number = 0; - wxString wxstr; - wxString header; - wxString separator; - bool stop_load = false; + int points = 0, line_number = 0; + wxString wxstr; + wxString header; + wxString separator; + bool stop_load = false; - double nums[wxPLOT_MAX_DATA_COLUMNS]; - int n; + double nums[wxPLOT_MAX_DATA_COLUMNS]; + int n; - bool select_cols = (x_col < 0) || (y_col < 0); + bool select_cols = (x_col < 0) || (y_col < 0); - while ( !fileStream.Eof() && !stop_load ) - { - wxstr = textstream.ReadLine().Strip(wxString::both); - line_number++; + while (!fileStream.Eof() && !stop_load) { + wxstr = textstream.ReadLine().Strip(wxString::both); + line_number++; + + if (wxstr.IsEmpty()) { + if ((points > 0) && (options & wxPLOTDATA_LOAD_BREAKONBLANKLINE)) { + stop_load = true; + } + } + else if (wxstr.Left(1) == wxT("#")) { + if ((points == 0) && (options & wxPLOTDATA_LOAD_HEADER)) { + header += (wxstr + wxT("\n")); + } + } + else { + n = NumberParse(nums, wxstr); - if (wxstr.IsEmpty()) + if (select_cols) { + if (n == 0) // FAIL { - if ((points > 0) && (options & wxPLOTDATA_LOAD_BREAKONBLANKLINE)) - stop_load = true; + x_col = y_col = 1; + select_cols = false; } - else if (wxstr.Left(1) == wxT("#")) - { - if ((points == 0) && (options & wxPLOTDATA_LOAD_HEADER)) - header += (wxstr + wxT("\n")); + else if (n == 1) { + x_col = y_col = 0; + select_cols = false; + } + else if (n == 2) { + x_col = 0; + y_col = 1; + select_cols = false; } - else - { - n = NumberParse( nums, wxstr ); - if (select_cols) - { - if (n == 0) // FAIL - { - x_col = y_col = 1; - select_cols = false; - } - else if (n == 1) - { - x_col = y_col = 0; - select_cols = false; - } - else if (n == 2) - { - x_col = 0; - y_col = 1; - select_cols = false; - } - - while (select_cols && !stop_load ) - { - wxString colStr = wxGetTextFromUser( - wxString::Format(wxT("%d columns found.\n") - wxT("Enter x and y cols separated by a space starting from 1.\n") - wxT("If x = y then x values are 0,1,2... and y is that col."), n), - wxT("Enter columns of data file to use")); - - if (colStr.IsEmpty()) - { - stop_load = true; - } - else - { - colStr.Trim(true).Trim(false); - - wxString leftStr = colStr.BeforeFirst(wxT(' ')); - wxString rightStr = colStr.AfterFirst(wxT(' ')); - if (rightStr.IsEmpty()) rightStr = leftStr; - - long xcol=0, ycol=0; - if ((!leftStr.IsEmpty()) && - leftStr.ToLong(&xcol) && rightStr.ToLong(&ycol)) - { - xcol--; - ycol--; - if ((xcol>=0) && (ycol>=0) && (xcol= n) || (y_col >= n)) && (!stop_load || select_cols)) - { - // FIXME - wxEOL_MAC - and end of file filestream.Eof() == 1, last line is a '@' - if (fileStream.Eof() && (eol==wxEOL_MAC) && (wxstr == wxT("@"))) - { - printf("MAC EOF @"); fflush(stdout); - break; - } - - wxMessageBox( - wxString::Format(wxT("Loading cols (%d,%d) aborted after %d points\n\n") - wxT("First 100 characters of offending line number: %d\n") - wxT("\"%s\"\n\n") - wxT("# for comments, blank lines Ok, comma, tab, space for separators\n") - wxT("7 4\n33 2.5e-2\n...\n"), - x_col, y_col, points, line_number, wxstr.Left(100).c_str()), - wxT("Error loading ")+filename, wxOK|wxICON_ERROR); - stop_load = true; - break; + long xcol = 0, ycol = 0; + if ((!leftStr.IsEmpty()) && leftStr.ToLong(&xcol) && rightStr.ToLong(&ycol)) { + xcol--; + ycol--; + if ((xcol >= 0) && (ycol >= 0) && (xcol < n) && (ycol < n)) { + x_col = int(xcol); + y_col = int(ycol); + select_cols = false; + } } - else if (!stop_load) - { - // figure out what the separator is for the first line only - if (points == 0) - { - if (wxstr.Find(wxT(',')) != wxNOT_FOUND) - separator = wxPLOTCURVE_DATASEPARATOR_COMMA; - else if (wxstr.Find(wxT('\t')) != wxNOT_FOUND) - separator = wxPLOTCURVE_DATASEPARATOR_TAB; - } - // reallocate data if necessary - if ( points >= allocated_data - 1) - { - allocated_data += 400; - x_data = (double*)realloc( x_data, allocated_data*sizeof(double) ); - y_data = (double*)realloc( y_data, allocated_data*sizeof(double) ); - - if (!x_data || !y_data) - { - if (x_data) free(x_data); - if (y_data) free(y_data); - loadfile.Close(); - return false; - } - } - - if (x_col == y_col) - x_data[points] = points; - else - x_data[points] = nums[x_col]; - - y_data[points] = nums[y_col]; - - points++; + } + } + } + + if (((x_col >= n) || (y_col >= n)) && (!stop_load || select_cols)) { + // FIXME - wxEOL_MAC - and end of file filestream.Eof() == 1, last line is a '@' + if (fileStream.Eof() && (eol == wxEOL_MAC) && (wxstr == wxT("@"))) { + printf("MAC EOF @"); + fflush(stdout); + break; + } + + wxMessageBox( + wxString::Format( + wxT("Loading cols (%d,%d) aborted after %d points\n\n") + wxT("First 100 characters of offending line number: %d\n") wxT("\"%s\"\n\n") + wxT("# for comments, blank lines Ok, comma, tab, space for separators\n") + wxT("7 4\n33 2.5e-2\n...\n"), + x_col, y_col, points, line_number, wxstr.Left(100).c_str()), + wxT("Error loading ") + filename, wxOK | wxICON_ERROR); + stop_load = true; + break; + } + else if (!stop_load) { + // figure out what the separator is for the first line only + if (points == 0) { + if (wxstr.Find(wxT(',')) != wxNOT_FOUND) { + separator = wxPLOTCURVE_DATASEPARATOR_COMMA; + } + else if (wxstr.Find(wxT('\t')) != wxNOT_FOUND) { + separator = wxPLOTCURVE_DATASEPARATOR_TAB; + } + } + // reallocate data if necessary + if (points >= allocated_data - 1) { + allocated_data += 400; + x_data = (double *)realloc(x_data, allocated_data * sizeof(double)); + y_data = (double *)realloc(y_data, allocated_data * sizeof(double)); + + if (!x_data || !y_data) { + if (x_data) { + free(x_data); } + if (y_data) { + free(y_data); + } + loadfile.Close(); + return false; + } } + + if (x_col == y_col) { + x_data[points] = points; + } + else { + x_data[points] = nums[x_col]; + } + + y_data[points] = nums[y_col]; + + points++; + } } - loadfile.Close(); + } + loadfile.Close(); - if (points > 0) - { - x_data = (double*)realloc( x_data, points*sizeof(double) ); - y_data = (double*)realloc( y_data, points*sizeof(double) ); + if (points > 0) { + x_data = (double *)realloc(x_data, points * sizeof(double)); + y_data = (double *)realloc(y_data, points * sizeof(double)); - bool ok = Create( x_data, y_data, points, false ); - if (ok) - { - SetFilename( filename ); - SetEOLMode( eol ); - if (!separator.IsEmpty()) - SetDataColumnSeparator(separator); - if (header.Len() > 0u) - SetHeader(header); - } - return ok; + bool ok = Create(x_data, y_data, points, false); + if (ok) { + SetFilename(filename); + SetEOLMode(eol); + if (!separator.IsEmpty()) { + SetDataColumnSeparator(separator); + } + if (header.Len() > 0u) { + SetHeader(header); + } } + return ok; + } - if (x_data) free(x_data); - if (y_data) free(y_data); + if (x_data) { + free(x_data); + } + if (y_data) { + free(y_data); + } - return false; + return false; } -bool wxPlotData::SaveFile( const wxString &filename, bool save_header, const wxString &format ) +bool wxPlotData::SaveFile(const wxString &filename, bool save_header, const wxString &format) { - wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); - wxCHECK_MSG((!format.IsEmpty()) && (format.Find(wxT('%')) != wxNOT_FOUND), false, wxT("invalid format")); + wxCHECK_MSG((!format.IsEmpty()) && (format.Find(wxT('%')) != wxNOT_FOUND), false, + wxT("invalid format")); - if (filename.IsEmpty()) return false; + if (filename.IsEmpty()) { + return false; + } - wxFile savefile; - savefile.Open( filename, wxFile::write ); - if (!savefile.IsOpened()) return false; + wxFile savefile; + savefile.Open(filename, wxFile::write); + if (!savefile.IsOpened()) { + return false; + } - wxFileOutputStream filestream( savefile ); - wxTextOutputStream textstream( filestream ); + wxFileOutputStream filestream(savefile); + wxTextOutputStream textstream(filestream); - textstream.SetMode( GetEOLMode() ); - int i; + textstream.SetMode(GetEOLMode()); + int i; - wxString header = GetOption(wxPLOTCURVE_OPTION_HEADER); - if (save_header && (header.Len() > 0u)) - { - textstream.WriteString(header); - const wxChar lastChar = header[header.Len()-1]; - if ((lastChar != wxT('\r')) || (lastChar != wxT('\n'))) - textstream.WriteString(wxT("\n")); + wxString header = GetOption(wxPLOTCURVE_OPTION_HEADER); + if (save_header && (header.Len() > 0u)) { + textstream.WriteString(header); + const wxChar lastChar = header[header.Len() - 1]; + if ((lastChar != wxT('\r')) || (lastChar != wxT('\n'))) { + textstream.WriteString(wxT("\n")); } + } - wxString s; - wxString sep = GetDataColumnSeparator(); - wxString f(wxT("%g")); - if (!format.IsEmpty()) f = format; + wxString s; + wxString sep = GetDataColumnSeparator(); + wxString f(wxT("%g")); + if (!format.IsEmpty()) { + f = format; + } - double x, y; - - for (i=0; im_count; i++) - { - x = M_PLOTDATA->m_Xdata[i]; - y = M_PLOTDATA->m_Ydata[i]; + double x, y; - if (wxFinite(x)) s = wxString::Format(f.c_str(), x); - else s = wxT("nan"); + for (i = 0; i < M_PLOTDATA->m_count; i++) { + x = M_PLOTDATA->m_Xdata[i]; + y = M_PLOTDATA->m_Ydata[i]; - s += sep; + if (wxFinite(x)) { + s = wxString::Format(f.c_str(), x); + } + else { + s = wxT("nan"); + } - if (wxFinite(y)) s += wxString::Format(f.c_str(), y); - else s += wxT("nan"); + s += sep; - s += wxT("\n"); - textstream.WriteString( s ); + if (wxFinite(y)) { + s += wxString::Format(f.c_str(), y); + } + else { + s += wxT("nan"); } - savefile.Close(); + s += wxT("\n"); + textstream.WriteString(s); + } - SetFilename(filename); + savefile.Close(); - return true; + SetFilename(filename); + + return true; } wxString wxPlotData::GetFilename() const { - wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxPlotData") ); - return GetOption(wxPLOTCURVE_OPTION_FILENAME); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxPlotData")); + return GetOption(wxPLOTCURVE_OPTION_FILENAME); } -void wxPlotData::SetFilename( const wxString &filename ) +void wxPlotData::SetFilename(const wxString &filename) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - SetOption(wxPLOTCURVE_OPTION_FILENAME, filename, true); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + SetOption(wxPLOTCURVE_OPTION_FILENAME, filename, true); } wxString wxPlotData::GetHeader() const { - wxCHECK_MSG( Ok(), wxEmptyString, wxT("Invalid wxPlotData") ); - return GetOption(wxPLOTCURVE_OPTION_HEADER); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("Invalid wxPlotData")); + return GetOption(wxPLOTCURVE_OPTION_HEADER); } -void wxPlotData::SetHeader( const wxString &header ) +void wxPlotData::SetHeader(const wxString &header) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - SetOption(wxPLOTCURVE_OPTION_HEADER, header); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + SetOption(wxPLOTCURVE_OPTION_HEADER, header); } wxEOL wxPlotData::GetEOLMode() const { - wxCHECK_MSG( Ok(), wxEOL_NATIVE, wxT("Invalid wxPlotData") ); - int eol = HasOption(wxPLOTCURVE_OPTION_EOLMODE) ? GetOptionInt(wxPLOTCURVE_OPTION_EOLMODE) : wxEOL_NATIVE; - switch (eol) - { - case wxEOL_NATIVE : return wxEOL_NATIVE; - case wxEOL_UNIX : return wxEOL_UNIX; - case wxEOL_MAC : return wxEOL_MAC; - case wxEOL_DOS : return wxEOL_DOS; - default : break; - } - + wxCHECK_MSG(Ok(), wxEOL_NATIVE, wxT("Invalid wxPlotData")); + int eol = HasOption(wxPLOTCURVE_OPTION_EOLMODE) ? GetOptionInt(wxPLOTCURVE_OPTION_EOLMODE) + : wxEOL_NATIVE; + switch (eol) { + case wxEOL_NATIVE: return wxEOL_NATIVE; + case wxEOL_UNIX: + return wxEOL_UNIX; + case wxEOL_MAC: + return wxEOL_MAC; + case wxEOL_DOS: + return wxEOL_DOS; + default: + break; + } + + return wxEOL_NATIVE; } -void wxPlotData::SetEOLMode( wxEOL eol ) +void wxPlotData::SetEOLMode(wxEOL eol) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - SetOption(wxPLOTCURVE_OPTION_EOLMODE, (int)eol); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + SetOption(wxPLOTCURVE_OPTION_EOLMODE, (int)eol); } wxString wxPlotData::GetDataColumnSeparator() const { - wxCHECK_MSG( Ok(), wxPLOTCURVE_DATASEPARATOR_SPACE, wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok(), wxPLOTCURVE_DATASEPARATOR_SPACE, wxT("Invalid wxPlotData")); - wxString s = wxPLOTCURVE_DATASEPARATOR_SPACE; - GetOption(wxPLOTCURVE_OPTION_DATASEPARATOR, s); - return s; + wxString s = wxPLOTCURVE_DATASEPARATOR_SPACE; + GetOption(wxPLOTCURVE_OPTION_DATASEPARATOR, s); + return s; } -void wxPlotData::SetDataColumnSeparator( const wxString &separator ) +void wxPlotData::SetDataColumnSeparator(const wxString &separator) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - SetOption(wxPLOTCURVE_OPTION_DATASEPARATOR, separator, true); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + SetOption(wxPLOTCURVE_OPTION_DATASEPARATOR, separator, true); } //---------------------------------------------------------------------------- @@ -1004,1047 +1041,1141 @@ void wxPlotData::SetDataColumnSeparator( const wxString &separator ) double *wxPlotData::GetXData() const { - wxCHECK_MSG( Ok(), (double*)NULL, wxT("Invalid wxPlotData") ); - return M_PLOTDATA->m_Xdata; + wxCHECK_MSG(Ok(), (double *)NULL, wxT("Invalid wxPlotData")); + return M_PLOTDATA->m_Xdata; } double *wxPlotData::GetYData() const { - wxCHECK_MSG( Ok(), (double*)NULL, wxT("Invalid wxPlotData") ); - return M_PLOTDATA->m_Ydata; + wxCHECK_MSG(Ok(), (double *)NULL, wxT("Invalid wxPlotData")); + return M_PLOTDATA->m_Ydata; } double *wxPlotData::GetYiData() const { - wxCHECK_MSG( Ok(), (double*)NULL, wxT("Invalid wxPlotData") ); - return M_PLOTDATA->m_Yidata; + wxCHECK_MSG(Ok(), (double *)NULL, wxT("Invalid wxPlotData")); + return M_PLOTDATA->m_Yidata; } -void wxPlotData::SetYiData( double *yi_data ) +void wxPlotData::SetYiData(double *yi_data) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); - if (M_PLOTDATA->m_Yidata) free(M_PLOTDATA->m_Yidata); - M_PLOTDATA->m_Yidata = yi_data; + if (M_PLOTDATA->m_Yidata) { + free(M_PLOTDATA->m_Yidata); + } + M_PLOTDATA->m_Yidata = yi_data; } -double wxPlotData::GetXValue( int index ) const +double wxPlotData::GetXValue(int index) const { - wxCHECK_MSG( Ok() && (index < M_PLOTDATA->m_count), 0.0, wxT("Invalid wxPlotData") ); - return M_PLOTDATA->m_Xdata[index]; + wxCHECK_MSG(Ok() && (index < M_PLOTDATA->m_count), 0.0, wxT("Invalid wxPlotData")); + return M_PLOTDATA->m_Xdata[index]; } -double wxPlotData::GetYValue( int index ) const +double wxPlotData::GetYValue(int index) const { - wxCHECK_MSG( Ok() && (index < M_PLOTDATA->m_count), 0.0, wxT("Invalid wxPlotData") ); - return M_PLOTDATA->m_Ydata[index]; + wxCHECK_MSG(Ok() && (index < M_PLOTDATA->m_count), 0.0, wxT("Invalid wxPlotData")); + return M_PLOTDATA->m_Ydata[index]; } -wxPoint2DDouble wxPlotData::GetPoint( int index ) const +wxPoint2DDouble wxPlotData::GetPoint(int index) const { - wxCHECK_MSG( Ok() && (index < M_PLOTDATA->m_count), wxPoint2DDouble(0,0), wxT("Invalid wxPlotData") ); - return wxPoint2DDouble(M_PLOTDATA->m_Xdata[index], M_PLOTDATA->m_Ydata[index]); + wxCHECK_MSG(Ok() && (index < M_PLOTDATA->m_count), wxPoint2DDouble(0, 0), + wxT("Invalid wxPlotData")); + return wxPoint2DDouble(M_PLOTDATA->m_Xdata[index], M_PLOTDATA->m_Ydata[index]); } -double wxPlotData::GetY( double x ) +double wxPlotData::GetY(double x) { - wxCHECK_MSG(Ok(), 0, wxT("invalid wxPlotData")); + wxCHECK_MSG(Ok(), 0, wxT("invalid wxPlotData")); - int i = GetIndexFromX( x, index_floor ); + int i = GetIndexFromX(x, index_floor); - if (M_PLOTDATA->m_Xdata[i] == x) - return M_PLOTDATA->m_Ydata[i]; + if (M_PLOTDATA->m_Xdata[i] == x) { + return M_PLOTDATA->m_Ydata[i]; + } - if (i >= M_PLOTDATA->m_count - 1) - return M_PLOTDATA->m_Ydata[i]; + if (i >= M_PLOTDATA->m_count - 1) { + return M_PLOTDATA->m_Ydata[i]; + } - int i1 = GetIndexFromX( x, index_ceil ); + int i1 = GetIndexFromX(x, index_ceil); - double y0 = M_PLOTDATA->m_Ydata[i]; - double y1 = M_PLOTDATA->m_Ydata[i1]; + double y0 = M_PLOTDATA->m_Ydata[i]; + double y1 = M_PLOTDATA->m_Ydata[i1]; - if ( y0 == y1 ) - return y0; + if (y0 == y1) { + return y0; + } - return LinearInterpolateY( M_PLOTDATA->m_Xdata[i], y0, - M_PLOTDATA->m_Xdata[i1], y1, x ); + return LinearInterpolateY(M_PLOTDATA->m_Xdata[i], y0, M_PLOTDATA->m_Xdata[i1], y1, x); } -void wxPlotData::SetXValue( int index, double x ) +void wxPlotData::SetXValue(int index, double x) { - wxCHECK_RET( Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData") ); + wxCHECK_RET(Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData")); - if (M_PLOTDATA->m_count == 1) - M_PLOTDATA->m_boundingRect.m_x = x; - else - { - if (x < M_PLOTDATA->m_boundingRect.m_x) - M_PLOTDATA->m_boundingRect.SetLeft(x); - else if (x > M_PLOTDATA->m_boundingRect.GetRight()) - M_PLOTDATA->m_boundingRect.SetRight(x); - else - CalcBoundingRect(); // don't know recalc it all + if (M_PLOTDATA->m_count == 1) { + M_PLOTDATA->m_boundingRect.m_x = x; + } + else { + if (x < M_PLOTDATA->m_boundingRect.m_x) { + M_PLOTDATA->m_boundingRect.SetLeft(x); } - - M_PLOTDATA->m_Xdata[index] = x; - -} -void wxPlotData::SetYValue( int index, double y ) -{ - wxCHECK_RET( Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData") ); - - if (M_PLOTDATA->m_count == 1) - M_PLOTDATA->m_boundingRect.m_y = y; - else - { - if (y < M_PLOTDATA->m_boundingRect.m_y) - M_PLOTDATA->m_boundingRect.SetTop(y); - else if (y > M_PLOTDATA->m_boundingRect.GetBottom()) - M_PLOTDATA->m_boundingRect.SetBottom(y); - else - CalcBoundingRect(); // don't know recalc it all + else if (x > M_PLOTDATA->m_boundingRect.GetRight()) { + M_PLOTDATA->m_boundingRect.SetRight(x); } + else { + CalcBoundingRect(); // don't know recalc it all + } + } - M_PLOTDATA->m_Ydata[index] = y; + M_PLOTDATA->m_Xdata[index] = x; } - -void wxPlotData::SetValue(int index, double x, double y) +void wxPlotData::SetYValue(int index, double y) { - wxCHECK_RET( Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData") ); - - double x_old = M_PLOTDATA->m_Xdata[index]; - double y_old = M_PLOTDATA->m_Ydata[index]; + wxCHECK_RET(Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData")); - M_PLOTDATA->m_Xdata[index] = x; - M_PLOTDATA->m_Ydata[index] = y; - - if (M_PLOTDATA->m_count == 1) - { - M_PLOTDATA->m_boundingRect.m_x = x; - M_PLOTDATA->m_boundingRect.m_y = y; + if (M_PLOTDATA->m_count == 1) { + M_PLOTDATA->m_boundingRect.m_y = y; + } + else { + if (y < M_PLOTDATA->m_boundingRect.m_y) { + M_PLOTDATA->m_boundingRect.SetTop(y); } - else - { - if ( (x_old <= M_PLOTDATA->m_boundingRect.m_x) || - (x_old >= M_PLOTDATA->m_boundingRect.GetRight()) || - (y_old >= M_PLOTDATA->m_boundingRect.m_y) || - (y_old <= M_PLOTDATA->m_boundingRect.GetBottom()) ) - CalcBoundingRect(); // don't know recalc it all - else - { - if (x < M_PLOTDATA->m_boundingRect.m_x) - M_PLOTDATA->m_boundingRect.m_x = x; - if (x > M_PLOTDATA->m_boundingRect.GetRight()) - M_PLOTDATA->m_boundingRect.SetRight(x); - - if (y > M_PLOTDATA->m_boundingRect.m_y) - M_PLOTDATA->m_boundingRect.m_y = y; - if (y < M_PLOTDATA->m_boundingRect.GetBottom()) - M_PLOTDATA->m_boundingRect.SetBottom(y); - } + else if (y > M_PLOTDATA->m_boundingRect.GetBottom()) { + M_PLOTDATA->m_boundingRect.SetBottom(y); } -} + else { + CalcBoundingRect(); // don't know recalc it all + } + } -void wxPlotData::SetXValues( int start_index, int count, double x ) -{ - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - if (count == 0) return; - if (count < 0) count = M_PLOTDATA->m_count-start_index; - int end_index = start_index + count - 1; - wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); - wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); - double *x_data = M_PLOTDATA->m_Xdata; - for (int n = start_index; n <= end_index; n++) - *x_data++ = x; + M_PLOTDATA->m_Ydata[index] = y; } -void wxPlotData::SetYValues( int start_index, int count, double y ) -{ - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - if (count == 0) return; - if (count < 0) count = M_PLOTDATA->m_count-start_index; - int end_index = start_index + count - 1; - wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); - wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); - double *y_data = M_PLOTDATA->m_Ydata; - for (int n = start_index; n <= end_index; n++) - *y_data++ = y; -} - -void wxPlotData::SetXStepValues( int start_index, int count, double x_start, double dx ) -{ - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - if (count == 0) return; - if (count < 0) count = M_PLOTDATA->m_count-start_index; - int end_index = start_index + count - 1; - wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); - wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); - double *x_data = M_PLOTDATA->m_Xdata + start_index; - for (int i = 0; i < count; i++, x_data++) - *x_data = x_start + (i * dx); -} -void wxPlotData::SetYStepValues( int start_index, int count, double y_start, double dy ) +void wxPlotData::SetValue(int index, double x, double y) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - if (count == 0) return; - if (count < 0) count = M_PLOTDATA->m_count-start_index; - int end_index = start_index + count - 1; - wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid starting index")); - wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count-1, wxT("Invalid ending index")); + wxCHECK_RET(Ok() && (index < M_PLOTDATA->m_count), wxT("Invalid wxPlotData")); - double *y_data = M_PLOTDATA->m_Ydata + start_index; - for (int i = 0; i < count; i++, y_data++) - *y_data = y_start + (i * dy); -} + double x_old = M_PLOTDATA->m_Xdata[index]; + double y_old = M_PLOTDATA->m_Ydata[index]; -int wxPlotData::GetIndexFromX( double x, wxPlotData::Index_Type type ) const -{ - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); + M_PLOTDATA->m_Xdata[index] = x; + M_PLOTDATA->m_Ydata[index] = y; - int count = M_PLOTDATA->m_count; - double *x_data = M_PLOTDATA->m_Xdata; + if (M_PLOTDATA->m_count == 1) { + M_PLOTDATA->m_boundingRect.m_x = x; + M_PLOTDATA->m_boundingRect.m_y = y; + } + else { + if ((x_old <= M_PLOTDATA->m_boundingRect.m_x) || + (x_old >= M_PLOTDATA->m_boundingRect.GetRight()) || + (y_old >= M_PLOTDATA->m_boundingRect.m_y) || + (y_old <= M_PLOTDATA->m_boundingRect.GetBottom())) { + CalcBoundingRect(); // don't know recalc it all + } + else { + if (x < M_PLOTDATA->m_boundingRect.m_x) { + M_PLOTDATA->m_boundingRect.m_x = x; + } + if (x > M_PLOTDATA->m_boundingRect.GetRight()) { + M_PLOTDATA->m_boundingRect.SetRight(x); + } - if ( !M_PLOTDATA->m_Xordered ) - { - int i; - int index = 0, index_lower = 0, index_higher = 0; - double closest = fabs( x - *x_data++ ); + if (y > M_PLOTDATA->m_boundingRect.m_y) { + M_PLOTDATA->m_boundingRect.m_y = y; + } + if (y < M_PLOTDATA->m_boundingRect.GetBottom()) { + M_PLOTDATA->m_boundingRect.SetBottom(y); + } + } + } +} + +void wxPlotData::SetXValues(int start_index, int count, double x) +{ + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + if (count == 0) { + return; + } + if (count < 0) { + count = M_PLOTDATA->m_count - start_index; + } + int end_index = start_index + count - 1; + wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid starting index")); + wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid ending index")); + double *x_data = M_PLOTDATA->m_Xdata; + for (int n = start_index; n <= end_index; n++) { + *x_data++ = x; + } +} +void wxPlotData::SetYValues(int start_index, int count, double y) +{ + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + if (count == 0) { + return; + } + if (count < 0) { + count = M_PLOTDATA->m_count - start_index; + } + int end_index = start_index + count - 1; + wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid starting index")); + wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid ending index")); + double *y_data = M_PLOTDATA->m_Ydata; + for (int n = start_index; n <= end_index; n++) { + *y_data++ = y; + } +} + +void wxPlotData::SetXStepValues(int start_index, int count, double x_start, double dx) +{ + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + if (count == 0) { + return; + } + if (count < 0) { + count = M_PLOTDATA->m_count - start_index; + } + int end_index = start_index + count - 1; + wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid starting index")); + wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid ending index")); + + double *x_data = M_PLOTDATA->m_Xdata + start_index; + for (int i = 0; i < count; i++, x_data++) { + *x_data = x_start + (i * dx); + } +} +void wxPlotData::SetYStepValues(int start_index, int count, double y_start, double dy) +{ + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + if (count == 0) { + return; + } + if (count < 0) { + count = M_PLOTDATA->m_count - start_index; + } + int end_index = start_index + count - 1; + wxPCHECK_MINMAX_RET(start_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid starting index")); + wxPCHECK_MINMAX_RET(end_index, 0, M_PLOTDATA->m_count - 1, wxT("Invalid ending index")); + + double *y_data = M_PLOTDATA->m_Ydata + start_index; + for (int i = 0; i < count; i++, y_data++) { + *y_data = y_start + (i * dy); + } +} + +int wxPlotData::GetIndexFromX(double x, wxPlotData::Index_Type type) const +{ + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxPlotData")); + + int count = M_PLOTDATA->m_count; + double *x_data = M_PLOTDATA->m_Xdata; + + if (!M_PLOTDATA->m_Xordered) { + int i; + int index = 0, index_lower = 0, index_higher = 0; + double closest = fabs(x - *x_data++); - for (i=1; i *x_data) - index_lower = i; - else - index_higher = i; - } - x_data++; + if (x > *x_data) { + index_lower = i; } + else { + index_higher = i; + } + } + x_data++; + } - // out of bounds so just return the closest - if ((x < M_PLOTDATA->m_boundingRect.GetLeft()) || - (x > M_PLOTDATA->m_boundingRect.GetRight()) ) - return index; + // out of bounds so just return the closest + if ((x < M_PLOTDATA->m_boundingRect.GetLeft()) || + (x > M_PLOTDATA->m_boundingRect.GetRight())) { + return index; + } - if (type == index_floor) return index_lower; - if (type == index_ceil) return index_higher; - return index; + if (type == index_floor) { + return index_lower; } + if (type == index_ceil) { + return index_higher; + } + return index; + } - // if the data is ordered use a faster search - if (x < M_PLOTDATA->m_boundingRect.GetLeft()) - return 0; - if (x > M_PLOTDATA->m_boundingRect.GetRight()) - return M_PLOTDATA->m_count - 1; + // if the data is ordered use a faster search + if (x < M_PLOTDATA->m_boundingRect.GetLeft()) { + return 0; + } + if (x > M_PLOTDATA->m_boundingRect.GetRight()) { + return M_PLOTDATA->m_count - 1; + } - if (x <= x_data[0]) return 0; - if (x >= x_data[count-1]) return count-1; + if (x <= x_data[0]) { + return 0; + } + if (x >= x_data[count - 1]) { + return count - 1; + } - int i, lo = 0, hi = count; - double res; + int i, lo = 0, hi = count; + double res; - while ( lo < hi ) - { - i = (lo + hi)/2; - res = x - x_data[i]; - if ( res < 0 ) hi = i; - else if ( res > 0 ) lo = i + 1; - else { lo = i; break; } + while (lo < hi) { + i = (lo + hi) / 2; + res = x - x_data[i]; + if (res < 0) { + hi = i; + } + else if (res > 0) { + lo = i + 1; } + else { + lo = i; + break; + } + } - if (type == index_floor) - { - if ((lo > 0) && (x < x_data[lo])) lo--; - return lo; + if (type == index_floor) { + if ((lo > 0) && (x < x_data[lo])) { + lo--; } - if (type == index_ceil) - { - if ((lo < count - 1) && (x > x_data[lo])) lo++; - return lo; + return lo; + } + if (type == index_ceil) { + if ((lo < count - 1) && (x > x_data[lo])) { + lo++; } + return lo; + } - if ((lo > 0) && (fabs(x - x_data[lo-1]) < fabs(x - x_data[lo]))) lo--; - if ((lo < count-1) && (fabs(x - x_data[lo+1]) < fabs(x - x_data[lo]))) lo++; + if ((lo > 0) && (fabs(x - x_data[lo - 1]) < fabs(x - x_data[lo]))) { + lo--; + } + if ((lo < count - 1) && (fabs(x - x_data[lo + 1]) < fabs(x - x_data[lo]))) { + lo++; + } - return lo; + return lo; } -int wxPlotData::GetIndexFromY( double y, wxPlotData::Index_Type type ) const +int wxPlotData::GetIndexFromY(double y, wxPlotData::Index_Type type) const { - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxPlotData")); - int i; - int index = 0, index_lower = 0, index_higher = 0; - int count = M_PLOTDATA->m_count; - double *y_data = M_PLOTDATA->m_Ydata; - double closest = fabs( y - *y_data++ ); + int i; + int index = 0, index_lower = 0, index_higher = 0; + int count = M_PLOTDATA->m_count; + double *y_data = M_PLOTDATA->m_Ydata; + double closest = fabs(y - *y_data++); - for (i=1; i *y_data) - index_lower = i; - else - index_higher = i; - } - y_data++; + if (y > *y_data) { + index_lower = i; + } + else { + index_higher = i; + } } + y_data++; + } - // out of bounds so just return the closest - if ((y < M_PLOTDATA->m_boundingRect.GetLeft()) || - (y > M_PLOTDATA->m_boundingRect.GetRight()) ) - return index; - - if (type == index_floor) return index_lower; - if (type == index_ceil) return index_higher; + // out of bounds so just return the closest + if ((y < M_PLOTDATA->m_boundingRect.GetLeft()) || (y > M_PLOTDATA->m_boundingRect.GetRight())) { return index; + } + + if (type == index_floor) { + return index_lower; + } + if (type == index_ceil) { + return index_higher; + } + return index; } -int wxPlotData::GetIndexFromXY( double x, double y, double x_range ) const +int wxPlotData::GetIndexFromXY(double x, double y, double x_range) const { - wxCHECK_MSG( Ok() && (x_range >= 0), 0, wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok() && (x_range >= 0), 0, wxT("Invalid wxPlotData")); - int start = 1, end = M_PLOTDATA->m_count - 1; + int start = 1, end = M_PLOTDATA->m_count - 1; - // find bounding indexes for range - if (M_PLOTDATA->m_Xordered && (x_range != 0)) - { - start = GetIndexFromX(x - x_range, wxPlotData::index_floor) + 1; - end = GetIndexFromX(x + x_range, wxPlotData::index_ceil); - } + // find bounding indexes for range + if (M_PLOTDATA->m_Xordered && (x_range != 0)) { + start = GetIndexFromX(x - x_range, wxPlotData::index_floor) + 1; + end = GetIndexFromX(x + x_range, wxPlotData::index_ceil); + } - int i, index = start - 1; + int i, index = start - 1; - double *x_data = &M_PLOTDATA->m_Xdata[index]; - double *y_data = &M_PLOTDATA->m_Ydata[index]; + double *x_data = &M_PLOTDATA->m_Xdata[index]; + double *y_data = &M_PLOTDATA->m_Ydata[index]; - double xdiff = (*x_data++) - x; - double ydiff = (*y_data++) - y; - double diff = xdiff*xdiff + ydiff*ydiff; - double min_diff = diff; + double xdiff = (*x_data++) - x; + double ydiff = (*y_data++) - y; + double diff = xdiff * xdiff + ydiff * ydiff; + double min_diff = diff; - double x_lower = x - x_range, x_higher = x + x_range; + double x_lower = x - x_range, x_higher = x + x_range; - for (i=start; i<=end; i++) - { - if ((x_range != 0) && ((*x_data < x_lower) || (*x_data > x_higher))) - { - x_data++; - y_data++; - continue; - } + for (i = start; i <= end; i++) { + if ((x_range != 0) && ((*x_data < x_lower) || (*x_data > x_higher))) { + x_data++; + y_data++; + continue; + } - xdiff = (*x_data++) - x; - ydiff = (*y_data++) - y; - diff = xdiff*xdiff + ydiff*ydiff; + xdiff = (*x_data++) - x; + ydiff = (*y_data++) - y; + diff = xdiff * xdiff + ydiff * ydiff; - if (diff < min_diff) - { - min_diff = diff; - index = i; - } + if (diff < min_diff) { + min_diff = diff; + index = i; } + } + + return index; +} + +double wxPlotData::GetAverage(int start_index, int count) const +{ + wxCHECK_MSG(Ok(), 0.0, wxT("Invalid wxPlotData")); + if (count < 0) { + count = M_PLOTDATA->m_count - start_index; + } + int end_index = start_index + count - 1; + wxCHECK_MSG((start_index < M_PLOTDATA->m_count) && (end_index < M_PLOTDATA->m_count), 0.0, + wxT("invalid input")); + + double ave = 0.0; + double *y_data = M_PLOTDATA->m_Ydata + start_index; + for (int i = start_index; i <= end_index; i++) { + ave += *y_data++; + } - return index; + ave /= double(count); + return ave; } -double wxPlotData::GetAverage( int start_index, int count ) const +int wxPlotData::GetMinMaxAve(const wxRangeIntSelection &rangeSel, wxPoint2DDouble *minXY_, + wxPoint2DDouble *maxXY_, wxPoint2DDouble *ave_, int *x_min_index_, + int *x_max_index_, int *y_min_index_, int *y_max_index_) const { - wxCHECK_MSG( Ok(), 0.0, wxT("Invalid wxPlotData") ); - if (count < 0) count = M_PLOTDATA->m_count-start_index; - int end_index = start_index + count - 1; - wxCHECK_MSG((start_indexm_count) && (end_indexm_count), 0.0, wxT("invalid input")); + wxCHECK_MSG(Ok(), 0, wxT("Invalid data curve")); + wxCHECK_MSG(rangeSel.GetCount() != 0, 0, wxT("Invalid range selection")); + + int min_index = rangeSel.GetRange(0).m_min; + // int max_index = rangeSel.GetRange(sel_count-1).m_max; + + wxCHECK_MSG((min_index >= 0) && (min_index < (int)M_PLOTDATA->m_count), 0, + wxT("Invalid range selection index in data curve")); + + double *x_data = M_PLOTDATA->m_Xdata; + double *y_data = M_PLOTDATA->m_Ydata; + + double x = x_data[min_index]; + double y = y_data[min_index]; + + // Find the X and Y min/max/ave values of the selection + int x_min_index = min_index, x_max_index = min_index; + int y_min_index = min_index, y_max_index = min_index; + double x_min_x = x, x_max_x = x; + double y_min_y = y, y_max_y = y; + double ave_x = 0, ave_y = 0; + int i, j, sel_count = rangeSel.GetCount(), sel_point_count = 0; - double ave = 0.0; - double *y_data = M_PLOTDATA->m_Ydata + start_index; - for (int i=start_index; i<=end_index; i++) ave += *y_data++; + for (i = 0; i < sel_count; i++) { + wxRangeInt r = rangeSel.GetRange(i); + wxCHECK_MSG((r.m_min >= 0) && (r.m_min < (int)M_PLOTDATA->m_count) && (r.m_max >= 0) && + (r.m_max < (int)M_PLOTDATA->m_count), + 0, wxT("Invalid range selection index in data curve")); - ave /= double(count); - return ave; + for (j = r.m_min; j <= r.m_max; j++) // yes we duplicate first point + { + sel_point_count++; + x = x_data[j]; + y = y_data[j]; + + if (x < x_min_x) { + x_min_x = x; + x_min_index = j; + } + if (x > x_max_x) { + x_max_x = x; + x_max_index = j; + } + if (y < y_min_y) { + y_min_y = y; + y_min_index = j; + } + if (y > y_max_y) { + y_max_y = y; + y_max_index = j; + } + + ave_x += x; + ave_y += y; + } + } + + ave_x /= double(sel_point_count); + ave_y /= double(sel_point_count); + + if (ave_) { + *ave_ = wxPoint2DDouble(ave_x, ave_y); + } + if (minXY_) { + *minXY_ = wxPoint2DDouble(x_min_x, y_min_y); + } + if (maxXY_) { + *maxXY_ = wxPoint2DDouble(x_max_x, y_max_y); + } + if (x_min_index_) { + *x_min_index_ = x_min_index; + } + if (x_max_index_) { + *x_max_index_ = x_max_index; + } + if (y_min_index_) { + *y_min_index_ = y_min_index; + } + if (y_max_index_) { + *y_max_index_ = y_max_index; + } + + return sel_point_count; +} + +wxArrayInt wxPlotData::GetCrossing(double y_value) const +{ + wxArrayInt points; + wxCHECK_MSG(Ok(), points, wxT("Invalid wxPlotData")); + + int i; + double *y_data = M_PLOTDATA->m_Ydata; + double y, last_y = M_PLOTDATA->m_Ydata[0]; + + for (i = 1; i < M_PLOTDATA->m_count; i++) { + y = y_data[i]; + + if (((last_y >= y_value) && (y <= y_value)) || ((last_y <= y_value) && (y >= y_value))) { + if (fabs(last_y - y_value) < fabs(y - y_value)) { + points.Add(i - 1); + } + else { + points.Add(i); + } + } + last_y = y; + } + + return points; } -int wxPlotData::GetMinMaxAve( const wxRangeIntSelection& rangeSel, - wxPoint2DDouble* minXY_, wxPoint2DDouble* maxXY_, - wxPoint2DDouble* ave_, - int *x_min_index_, int *x_max_index_, - int *y_min_index_, int *y_max_index_ ) const +int wxPlotData::GetMinYIndex(int start_index, int end_index) const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid data curve")); - wxCHECK_MSG(rangeSel.GetCount() != 0, 0, wxT("Invalid range selection")); + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_MSG(start_index, end_index, count, 0); - int min_index = rangeSel.GetRange(0).m_min; - //int max_index = rangeSel.GetRange(sel_count-1).m_max; + double *y_data = &M_PLOTDATA->m_Ydata[start_index]; + double min_y = *y_data; + int min_y_index = start_index; - wxCHECK_MSG((min_index >= 0) && (min_index < (int)M_PLOTDATA->m_count), 0, - wxT("Invalid range selection index in data curve")); + for (int i = start_index + 1; i < end_index; i++) { + if (*y_data < min_y) { + min_y = *y_data; + min_y_index = i; + } - double *x_data = M_PLOTDATA->m_Xdata; - double *y_data = M_PLOTDATA->m_Ydata; + y_data++; + } + return min_y_index; +} - double x = x_data[min_index]; - double y = y_data[min_index]; +int wxPlotData::GetMaxYIndex(int start_index, int end_index) const +{ + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_MSG(start_index, end_index, count, 0); - // Find the X and Y min/max/ave values of the selection - int x_min_index = min_index, x_max_index = min_index; - int y_min_index = min_index, y_max_index = min_index; - double x_min_x = x, x_max_x = x; - double y_min_y = y, y_max_y = y; - double ave_x = 0, ave_y = 0; - int i, j, sel_count = rangeSel.GetCount(), sel_point_count = 0; + double *y_data = &M_PLOTDATA->m_Ydata[start_index]; + double max_y = *y_data; + int max_y_index = start_index; - for (i=0; i= 0) && (r.m_min < (int)M_PLOTDATA->m_count) && - (r.m_max >= 0) && (r.m_max < (int)M_PLOTDATA->m_count), 0, - wxT("Invalid range selection index in data curve")); - - for (j=r.m_min; j<=r.m_max; j++) // yes we duplicate first point - { - sel_point_count++; - x = x_data[j]; - y = y_data[j]; - - if (x < x_min_x) { x_min_x = x; x_min_index = j; } - if (x > x_max_x) { x_max_x = x; x_max_index = j; } - if (y < y_min_y) { y_min_y = y; y_min_index = j; } - if (y > y_max_y) { y_max_y = y; y_max_index = j; } - - ave_x += x; - ave_y += y; - } - } - - ave_x /= double(sel_point_count); - ave_y /= double(sel_point_count); - - if (ave_) *ave_ = wxPoint2DDouble(ave_x, ave_y); - if (minXY_) *minXY_ = wxPoint2DDouble(x_min_x, y_min_y); - if (maxXY_) *maxXY_ = wxPoint2DDouble(x_max_x, y_max_y); - if (x_min_index_) *x_min_index_ = x_min_index; - if (x_max_index_) *x_max_index_ = x_max_index; - if (y_min_index_) *y_min_index_ = y_min_index; - if (y_max_index_) *y_max_index_ = y_max_index; - - return sel_point_count; -} - -wxArrayInt wxPlotData::GetCrossing( double y_value ) const -{ - wxArrayInt points; - wxCHECK_MSG( Ok(), points, wxT("Invalid wxPlotData") ); - - int i; - double *y_data = M_PLOTDATA->m_Ydata; - double y, last_y = M_PLOTDATA->m_Ydata[0]; - - for (i=1; im_count; i++) - { - y = y_data[i]; - - if (((last_y >= y_value) && (y <= y_value)) || - ((last_y <= y_value) && (y >= y_value))) - { - if (fabs(last_y - y_value) < fabs(y - y_value)) - points.Add(i-1); - else - points.Add(i); - } - last_y = y; - } - - return points; -} - -int wxPlotData::GetMinYIndex(int start_index, int end_index) const -{ - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_MSG(start_index, end_index, count, 0); - - double *y_data = &M_PLOTDATA->m_Ydata[start_index]; - double min_y = *y_data; - int min_y_index = start_index; - - for (int i=start_index+1; i max_y) { + max_y = *y_data; + max_y_index = i; } - return min_y_index; -} -int wxPlotData::GetMaxYIndex(int start_index, int end_index) const -{ - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_MSG(start_index, end_index, count, 0); - - double *y_data = &M_PLOTDATA->m_Ydata[start_index]; - double max_y = *y_data; - int max_y_index = start_index; - - for (int i=start_index+1; i max_y) - { - max_y = *y_data; - max_y_index = i; - } - - y_data++; - } - return max_y_index; + y_data++; + } + return max_y_index; } //---------------------------------------------------------------------------- // Data processing functions //---------------------------------------------------------------------------- -void wxPlotData::OffsetX( double offset, int start_index, int end_index ) +void wxPlotData::OffsetX(double offset, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *x = M_PLOTDATA->m_Xdata + start_index; + int i; + double *x = M_PLOTDATA->m_Xdata + start_index; - for (i = start_index; i <= end_index; i++) - *x++ += offset; + for (i = start_index; i <= end_index; i++) { + *x++ += offset; + } - CalcBoundingRect(); + CalcBoundingRect(); } -void wxPlotData::OffsetY( double offset, int start_index, int end_index ) +void wxPlotData::OffsetY(double offset, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *y = M_PLOTDATA->m_Ydata + start_index; + int i; + double *y = M_PLOTDATA->m_Ydata + start_index; - for (i = start_index; i <= end_index; i++) - *y++ += offset; + for (i = start_index; i <= end_index; i++) { + *y++ += offset; + } - CalcBoundingRect(); + CalcBoundingRect(); } -void wxPlotData::OffsetXY( double offsetX, double offsetY, int start_index, int end_index ) +void wxPlotData::OffsetXY(double offsetX, double offsetY, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *x = M_PLOTDATA->m_Xdata + start_index; - double *y = M_PLOTDATA->m_Ydata + start_index; + int i; + double *x = M_PLOTDATA->m_Xdata + start_index; + double *y = M_PLOTDATA->m_Ydata + start_index; - for (i = start_index; i <= end_index; i++) - { - *x++ += offsetX; - *y++ += offsetY; - } + for (i = start_index; i <= end_index; i++) { + *x++ += offsetX; + *y++ += offsetY; + } - CalcBoundingRect(); + CalcBoundingRect(); } -void wxPlotData::ScaleX( double scale, double offset, int start_index, int end_index ) +void wxPlotData::ScaleX(double scale, double offset, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *x = M_PLOTDATA->m_Xdata + start_index; + int i; + double *x = M_PLOTDATA->m_Xdata + start_index; - for (i = start_index; i <= end_index; i++) - { - *x = ((*x) - offset)*scale + offset; - x++; - } + for (i = start_index; i <= end_index; i++) { + *x = ((*x) - offset) * scale + offset; + x++; + } - CalcBoundingRect(); + CalcBoundingRect(); } -void wxPlotData::ScaleY( double scale, double offset, int start_index, int end_index ) +void wxPlotData::ScaleY(double scale, double offset, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *y = M_PLOTDATA->m_Ydata + start_index; + int i; + double *y = M_PLOTDATA->m_Ydata + start_index; - for (i = start_index; i <= end_index; i++) - { - *y = ((*y) - offset)*scale + offset; - y++; - } + for (i = start_index; i <= end_index; i++) { + *y = ((*y) - offset) * scale + offset; + y++; + } - CalcBoundingRect(); + CalcBoundingRect(); } void wxPlotData::ScaleXY(double scaleX, double scaleY, double offsetX, double offsetY, - int start_index, int end_index ) + int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - double *x = M_PLOTDATA->m_Xdata + start_index; - double *y = M_PLOTDATA->m_Ydata + start_index; + double *x = M_PLOTDATA->m_Xdata + start_index; + double *y = M_PLOTDATA->m_Ydata + start_index; - for (int i = start_index; i < end_index; i++) - { - *x = ((*x) - offsetX)*scaleX + offsetX; - x++; - *y = ((*y) - offsetY)*scaleY + offsetY; - y++; - } + for (int i = start_index; i < end_index; i++) { + *x = ((*x) - offsetX) * scaleX + offsetX; + x++; + *y = ((*y) - offsetY) * scaleY + offsetY; + y++; + } - CalcBoundingRect(); + CalcBoundingRect(); } -void wxPlotData::PowerX( double power, int start_index, int end_index ) +void wxPlotData::PowerX(double power, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *x = M_PLOTDATA->m_Xdata + start_index; - for (i = start_index; i <= end_index; i++, x++) - *x = pow(*x, power); + int i; + double *x = M_PLOTDATA->m_Xdata + start_index; + for (i = start_index; i <= end_index; i++, x++) { + *x = pow(*x, power); + } - CalcBoundingRect(); + CalcBoundingRect(); } -void wxPlotData::PowerY( double power, int start_index, int end_index ) +void wxPlotData::PowerY(double power, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *y = M_PLOTDATA->m_Ydata + start_index; - for (i = start_index; i <= end_index; i++, y++) - *y = pow(*y, power); + int i; + double *y = M_PLOTDATA->m_Ydata + start_index; + for (i = start_index; i <= end_index; i++, y++) { + *y = pow(*y, power); + } - CalcBoundingRect(); + CalcBoundingRect(); } -void wxPlotData::PowerXY( double powerX, double powerY, int start_index, int end_index ) +void wxPlotData::PowerXY(double powerX, double powerY, int start_index, int end_index) { - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - const int count = M_PLOTDATA->m_count; - if (end_index < 0) end_index = count - 1; - CHECK_START_END_INDEX_RET(start_index, end_index, count); + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + const int count = M_PLOTDATA->m_count; + if (end_index < 0) { + end_index = count - 1; + } + CHECK_START_END_INDEX_RET(start_index, end_index, count); - int i; - double *x = M_PLOTDATA->m_Xdata + start_index; - double *y = M_PLOTDATA->m_Ydata + start_index; - for (i = start_index; i <= end_index; i++, x++, y++) - { - *x = pow(*x, powerX); - *y = pow(*y, powerY); - } + int i; + double *x = M_PLOTDATA->m_Xdata + start_index; + double *y = M_PLOTDATA->m_Ydata + start_index; + for (i = start_index; i <= end_index; i++, x++, y++) { + *x = pow(*x, powerX); + *y = pow(*y, powerY); + } - CalcBoundingRect(); + CalcBoundingRect(); } -wxPlotData wxPlotData::Resample( double start_x, double dx, int points ) const +wxPlotData wxPlotData::Resample(double start_x, double dx, int points) const { - wxPlotData dst; - wxCHECK_MSG(Ok(), dst, wxT("Invalid wxPlotData")); - wxCHECK_MSG(points > 0, dst, wxT("invalid number of points")); + wxPlotData dst; + wxCHECK_MSG(Ok(), dst, wxT("Invalid wxPlotData")); + wxCHECK_MSG(points > 0, dst, wxT("invalid number of points")); - if (!dst.Create(points, false)) return dst; + if (!dst.Create(points, false)) { + return dst; + } - double x = start_x; + double x = start_x; - wxPlotData thisData = *this; + wxPlotData thisData = *this; - for (int i=0; i< points; i++, x += dx) - { - dst.SetPoint(i, wxPoint2DDouble(x, thisData.GetY(x))); - } + for (int i = 0; i < points; i++, x += dx) { + dst.SetPoint(i, wxPoint2DDouble(x, thisData.GetY(x))); + } - dst.CalcBoundingRect(); - return dst; + dst.CalcBoundingRect(); + return dst; } -wxPlotData wxPlotData::Resample( const wxPlotData &source ) const +wxPlotData wxPlotData::Resample(const wxPlotData &source) const { - wxPlotData dst; - wxCHECK_MSG( Ok(), dst, wxT("Invalid wxPlotData") ); + wxPlotData dst; + wxCHECK_MSG(Ok(), dst, wxT("Invalid wxPlotData")); - int src_index_min = source.GetIndexFromX(wxMax(GetBoundingRect().m_x, source.GetBoundingRect().m_x)); - int src_index_max = source.GetIndexFromX(wxMin(GetBoundingRect().GetRight(), source.GetBoundingRect().GetRight())); + int src_index_min = + source.GetIndexFromX(wxMax(GetBoundingRect().m_x, source.GetBoundingRect().m_x)); + int src_index_max = source.GetIndexFromX( + wxMin(GetBoundingRect().GetRight(), source.GetBoundingRect().GetRight())); - int index_min = GetIndexFromX(wxMax(GetBoundingRect().m_x, source.GetBoundingRect().m_x)); - //int index_max = GetIndexFromX(wxMin(GetBoundingRect().GetRight(), source.GetBoundingRect().GetRight())); + int index_min = GetIndexFromX(wxMax(GetBoundingRect().m_x, source.GetBoundingRect().m_x)); + // int index_max = GetIndexFromX(wxMin(GetBoundingRect().GetRight(), + // source.GetBoundingRect().GetRight())); - int count = src_index_max - src_index_min; - if (count <= 0) - return dst; + int count = src_index_max - src_index_min; + if (count <= 0) { + return dst; + } - if (!dst.Create(src_index_max - src_index_min, false)) return dst; + if (!dst.Create(src_index_max - src_index_min, false)) { + return dst; + } - double *dst_x_data = dst.GetXData(); - double *dst_y_data = dst.GetYData(); + double *dst_x_data = dst.GetXData(); + double *dst_y_data = dst.GetYData(); - double x, s_x, y; + double x, s_x, y; - for (int i=0; i s_x) - { - if (i+index_min > 0) - index1--; - } - else - { - if (i+index_min > 0) - index2++; - } - - y = LinearInterpolateY( GetXValue(index1), GetYValue(index1), - GetXValue(index2), GetYValue(index2), x ); + if (s_x == x) { + y = GetYValue(i + index_min); + } + else { + int index1 = i + index_min; + int index2 = i + index_min; + if (x > s_x) { + if (i + index_min > 0) { + index1--; + } + } + else { + if (i + index_min > 0) { + index2++; } + } - *dst_x_data++ = x; - *dst_y_data++ = y; + y = LinearInterpolateY(GetXValue(index1), GetYValue(index1), GetXValue(index2), + GetYValue(index2), x); } - dst.CalcBoundingRect(); - return dst; + *dst_x_data++ = x; + *dst_y_data++ = y; + } + + dst.CalcBoundingRect(); + return dst; } //---------------------------------------------------------------------------- // Data manipulation //---------------------------------------------------------------------------- -wxPlotData wxPlotData::Modify( const wxPlotFunction &func_, FuncModify_Type type ) const +wxPlotData wxPlotData::Modify(const wxPlotFunction &func_, FuncModify_Type type) const { - wxPlotData dst; - wxCHECK_MSG( Ok() && func_.Ok(), dst, wxT("Invalid wxPlotData") ); + wxPlotData dst; + wxCHECK_MSG(Ok() && func_.Ok(), dst, wxT("Invalid wxPlotData")); - int i, count = M_PLOTDATA->m_count; + int i, count = M_PLOTDATA->m_count; - if (!dst.Create(count)) return dst; + if (!dst.Create(count)) { + return dst; + } - double *x_data = M_PLOTDATA->m_Xdata; - double *y_data = M_PLOTDATA->m_Ydata; - double *dst_x_data = dst.GetXData(); - double *dst_y_data = dst.GetYData(); + double *x_data = M_PLOTDATA->m_Xdata; + double *y_data = M_PLOTDATA->m_Ydata; + double *dst_x_data = dst.GetXData(); + double *dst_y_data = dst.GetYData(); - if (M_PLOTDATA->m_Yidata) - { - double *yi = (double*)malloc(count*sizeof(double)); - if (!yi) - { - dst.Destroy(); - return dst; - } - dst.SetYiData(yi); + if (M_PLOTDATA->m_Yidata) { + double *yi = (double *)malloc(count * sizeof(double)); + if (!yi) { + dst.Destroy(); + return dst; } + dst.SetYiData(yi); + } - wxPlotFunction func(func_); + wxPlotFunction func(func_); - switch (type) - { - case add_x : - { - memcpy(dst_y_data, y_data, count*sizeof(double)); - if (M_PLOTDATA->m_Yidata) - memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); + switch (type) { + case add_x: { + memcpy(dst_y_data, y_data, count * sizeof(double)); + if (M_PLOTDATA->m_Yidata) { + memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count * sizeof(double)); + } - for (i=0; im_Yidata) - memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); + for (i = 0; i < count; i++) { + *dst_x_data++ = (*x_data) + func.GetY(*x_data); + x_data++; + } + break; + } + case add_y: { + if (M_PLOTDATA->m_Yidata) { + memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count * sizeof(double)); + } - for (i=0; im_Yidata) - memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); + for (i = 0; i < count; i++) { + *dst_y_data++ = (*y_data++) + func.GetY(*x_data); + *dst_x_data++ = *x_data++; + } + break; + } + case mult_x: { + memcpy(dst_y_data, y_data, count * sizeof(double)); + if (M_PLOTDATA->m_Yidata) { + memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count * sizeof(double)); + } - for (i=0; im_Yidata) - memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count*sizeof(double)); + for (i = 0; i < count; i++) { + *dst_x_data++ = (*x_data) * func.GetY(*x_data); + x_data++; + } + break; + } + case mult_y: { + if (M_PLOTDATA->m_Yidata) { + memcpy(dst.GetYiData(), M_PLOTDATA->m_Yidata, count * sizeof(double)); + } - for (i=0; im_Yidata; - double *dst_yi_data = dst.GetYiData(); + double *yi_data = M_PLOTDATA->m_Yidata; + double *dst_yi_data = dst.GetYiData(); - for (i=0; im_Yidata; - double *dst_yi_data = dst.GetYiData(); + double *yi_data = M_PLOTDATA->m_Yidata; + double *dst_yi_data = dst.GetYiData(); - for (i=0; im_count; - double *x_data = M_PLOTDATA->m_Xdata; - double *y_data = M_PLOTDATA->m_Ydata; + double curve2_x_min = curve2.GetBoundingRect().GetLeft(); + double curve2_x_max = curve2.GetBoundingRect().GetRight(); + int curve2_count = curve2.GetCount(); - if (!dst.Create(count)) return dst; + int count = M_PLOTDATA->m_count; + double *x_data = M_PLOTDATA->m_Xdata; + double *y_data = M_PLOTDATA->m_Ydata; - double *dst_x_data = dst.GetXData(); - double *dst_y_data = dst.GetYData(); - - int i, index1, index2; - - for (i=0; i curve2_x_min) && (*x_data < curve2_x_max)) + if (!dst.Create(count)) { + return dst; + } + + double *dst_x_data = dst.GetXData(); + double *dst_y_data = dst.GetYData(); + + int i, index1, index2; + + for (i = 0; i < count; i++) { + *dst_x_data = *x_data; + + if ((*x_data > curve2_x_min) && (*x_data < curve2_x_max)) { + index1 = curve2.GetIndexFromX(*x_data); + if (curve2.GetXValue(index1) == *x_data) { + *dst_y_data = factor1 * (*y_data) + factor2 * curve2.GetYValue(index1); + } + else // need to interpolate to find data's y value at this x + { + if (*x_data < curve2.GetXValue(index1)) { + index2 = index1; + index1--; + } + else // if (*x_data < data.GetX(index1)) { - index1 = curve2.GetIndexFromX(*x_data); - if ( curve2.GetXValue(index1) == *x_data ) - { - *dst_y_data = factor1*(*y_data) + factor2*curve2.GetYValue(index1); - } - else // need to interpolate to find data's y value at this x - { - if (*x_data < curve2.GetXValue(index1)) - { - index2 = index1; - index1--; - } - else //if (*x_data < data.GetX(index1)) - { - index2 = index1 + 1; - } - if ((index1 >= 0) && (index1 < curve2_count) && (index2 >= 0) && (index2 < curve2_count) ) - { - *dst_y_data = factor1*(*y_data) + factor2*LinearInterpolateY( curve2.GetXValue(index1), curve2.GetYValue(index1), - curve2.GetXValue(index2), curve2.GetYValue(index2), - *x_data ); - } - else - { - *dst_y_data = *x_data; - } - } + index2 = index1 + 1; } - x_data++; - y_data++; - dst_x_data++; - dst_y_data++; + if ((index1 >= 0) && (index1 < curve2_count) && (index2 >= 0) && (index2 < curve2_count)) { + *dst_y_data = factor1 * (*y_data) + + factor2 * LinearInterpolateY( + curve2.GetXValue(index1), curve2.GetYValue(index1), + curve2.GetXValue(index2), curve2.GetYValue(index2), *x_data); + } + else { + *dst_y_data = *x_data; + } + } } + x_data++; + y_data++; + dst_x_data++; + dst_y_data++; + } - dst.CalcBoundingRect(); - return dst; + dst.CalcBoundingRect(); + return dst; } //---------------------------------------------------------------------------- // RunAverage //---------------------------------------------------------------------------- -wxPlotData wxPlotData::RunAverage( int points, int start_index, int count ) const +wxPlotData wxPlotData::RunAverage(int points, int start_index, int count) const { - wxPlotData dst; + wxPlotData dst; - wxCHECK_MSG( Ok(), dst, wxT("Invalid wxPlotData") ); - int data_count = M_PLOTDATA->m_count; - wxCHECK_MSG((start_index < data_count), dst, wxT("Invalid runaverage range") ); + wxCHECK_MSG(Ok(), dst, wxT("Invalid wxPlotData")); + int data_count = M_PLOTDATA->m_count; + wxCHECK_MSG((start_index < data_count), dst, wxT("Invalid runaverage range")); - int i; - int half_width = points/2; - int width = half_width * 2 + 1; - double dpoints = width; - int end_index = count <= 0 ? data_count : start_index + count; - int run_start = wxMax(start_index, half_width); - int run_end = wxMin(end_index, data_count - half_width); + int i; + int half_width = points / 2; + int width = half_width * 2 + 1; + double dpoints = width; + int end_index = count <= 0 ? data_count : start_index + count; + int run_start = wxMax(start_index, half_width); + int run_end = wxMin(end_index, data_count - half_width); - //wxCHECK_MSG((points > 2) && (start_index+count 2) && (start_index+count= run_end) return dst; + if (run_start >= run_end) { + return dst; + } - //double *src = M_PLOTDATA->m_Ydata; - //double *dest = dst.GetYData(); + // double *src = M_PLOTDATA->m_Ydata; + // double *dest = dst.GetYData(); - double run_sum = 0.0; + double run_sum = 0.0; - for (i=run_start-half_width; i<=run_start+half_width; i++) - run_sum += GetYValue(i); //src[i]; + for (i = run_start - half_width; i <= run_start + half_width; i++) { + run_sum += GetYValue(i); // src[i]; + } - dst.SetYValue(run_start, run_sum/dpoints); //dest[half_width] = runsum / dpoints; + dst.SetYValue(run_start, run_sum / dpoints); // dest[half_width] = runsum / dpoints; - // fake the initial runaverage (ideally this should be thrown away) - double run_sum_init = run_sum; - for (i=run_start-1; i>=start_index; i--) - { - run_sum_init += GetYValue(i) - GetYValue(i+half_width); - dst.SetYValue(i, run_sum_init/dpoints); - } + // fake the initial runaverage (ideally this should be thrown away) + double run_sum_init = run_sum; + for (i = run_start - 1; i >= start_index; i--) { + run_sum_init += GetYValue(i) - GetYValue(i + half_width); + dst.SetYValue(i, run_sum_init / dpoints); + } - for (i=run_start+1; i=0; i--) + { + init_runsum += src[i]; + dest[i] = init_runsum / double(half_width - i + 1); + } - // these first points < half_width are "undefined" but we'll do it anyway - double init_runsum = runsum/dpoints; - for (i=half_width-1; i>=0; i--) - { - init_runsum += src[i]; - dest[i] = init_runsum / double(half_width - i + 1); - } + // middle "good" runaveraged points + dest[half_width] = runsum / dpoints; - // middle "good" runaveraged points - dest[half_width] = runsum / dpoints; + for (i=half_width+1; im_count; i++) + { + runsum += src[i]; + dest[i] = runsum / double(half_width - (M_PLOTDATA->m_count - i) + 2); + } - // end points, do as in the beginning - runsum /= dpoints; - for (i=runend; im_count; i++) - { - runsum += src[i]; - dest[i] = runsum / double(half_width - (M_PLOTDATA->m_count - i) + 2); - } - - memcpy(dst.GetXData(), M_PLOTDATA->m_Xdata, M_PLOTDATA->m_count*sizeof(double)); -*/ + memcpy(dst.GetXData(), M_PLOTDATA->m_Xdata, M_PLOTDATA->m_count*sizeof(double)); + */ - dst.CalcBoundingRect(); + dst.CalcBoundingRect(); - return dst; + return dst; } //---------------------------------------------------------------------------- @@ -2053,26 +2184,27 @@ wxPlotData wxPlotData::RunAverage( int points, int start_index, int count ) cons wxPlotData wxPlotData::Abs() const { - wxPlotData dst; + wxPlotData dst; - wxCHECK_MSG(Ok(), dst, wxT("invalid plotdata")); - int points = M_PLOTDATA->m_count; + wxCHECK_MSG(Ok(), dst, wxT("invalid plotdata")); + int points = M_PLOTDATA->m_count; - if (!dst.Create(points, false)) return dst; + if (!dst.Create(points, false)) { + return dst; + } - double *y_data = M_PLOTDATA->m_Ydata; + double *y_data = M_PLOTDATA->m_Ydata; - double *dst_y_data = dst.GetYData(); + double *dst_y_data = dst.GetYData(); - memcpy(dst.GetXData(), GetXData(), points*sizeof(double)); + memcpy(dst.GetXData(), GetXData(), points * sizeof(double)); - for (int i=0; im_count; - if (count <= 0) count = points - start_index; - wxCHECK_MSG((start_index + count <= points), dst, wxT("invalid index")); + wxCHECK_MSG(Ok(), dst, wxT("invalid plotdata")); + int points = M_PLOTDATA->m_count; + if (count <= 0) { + count = points - start_index; + } + wxCHECK_MSG((start_index + count <= points), dst, wxT("invalid index")); - double x0 = M_PLOTDATA->m_Xdata[start_index]; - double y0 = M_PLOTDATA->m_Ydata[start_index]; - double x1 = M_PLOTDATA->m_Xdata[start_index+count-1]; - double y1 = M_PLOTDATA->m_Ydata[start_index+count-1]; + double x0 = M_PLOTDATA->m_Xdata[start_index]; + double y0 = M_PLOTDATA->m_Ydata[start_index]; + double x1 = M_PLOTDATA->m_Xdata[start_index + count - 1]; + double y1 = M_PLOTDATA->m_Ydata[start_index + count - 1]; - wxCHECK_MSG(wxFinite(x0)&&wxFinite(y0)&&wxFinite(x1)&&wxFinite(y1), dst, wxT("values are NaN")); + wxCHECK_MSG(wxFinite(x0) && wxFinite(y0) && wxFinite(x1) && wxFinite(y1), dst, + wxT("values are NaN")); - if (!dst.Copy(*this, true)) return dst; + if (!dst.Copy(*this, true)) { + return dst; + } - double x, y, m = (y1-y0)/count; + double x, y, m = (y1 - y0) / count; - // equally spaced y values - if (x1 == x0) - { - y = y0; - for (int i=start_index+1; im_Xdata[i]; - if (wxFinite(x)) - { - y = (m*x + (y0 - m*x0)); - if (wxFinite(y)) - dst.SetYValue(i, y); - } + for (int i = start_index + 1; i < start_index + count - 1; i++) { + x = M_PLOTDATA->m_Xdata[i]; + if (wxFinite(x)) { + y = (m * x + (y0 - m * x0)); + if (wxFinite(y)) { + dst.SetYValue(i, y); + } } + } - dst.CalcBoundingRect(); - return dst; + dst.CalcBoundingRect(); + return dst; } // FIXME - this is not strictly correct should be xnew_n = (x_(n+1)+x_n)/2, do I care? wxPlotData wxPlotData::Derivitive() const { - wxCHECK_MSG( Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok(), wxPlotData(), wxT("Invalid wxPlotData")); - int count = M_PLOTDATA->m_count; + int count = M_PLOTDATA->m_count; - wxPlotData dst(count, false); + wxPlotData dst(count, false); - double *y_data = M_PLOTDATA->m_Ydata; - double *dst_y_data = dst.GetYData(); + double *y_data = M_PLOTDATA->m_Ydata; + double *dst_y_data = dst.GetYData(); - memcpy(dst.GetXData(), GetXData(), count*sizeof(double)); + memcpy(dst.GetXData(), GetXData(), count * sizeof(double)); - *dst_y_data++ = 0; + *dst_y_data++ = 0; - for (int i=1; i)^2))/N double wxPlotData::Variance(int start_index, int count) const { - wxCHECK_MSG( Ok(), 0, wxT("Invalid wxPlotData") ); - int points = M_PLOTDATA->m_count; - if (count <= 0) count = points - start_index; - wxCHECK_MSG((start_index >= 0) && (start_index + count <= points), 0, wxT("invalid index")); + wxCHECK_MSG(Ok(), 0, wxT("Invalid wxPlotData")); + int points = M_PLOTDATA->m_count; + if (count <= 0) { + count = points - start_index; + } + wxCHECK_MSG((start_index >= 0) && (start_index + count <= points), 0, wxT("invalid index")); - double *y_data = GetYData() + start_index; - double sum = 0; - double ave = GetAverage(start_index, count); + double *y_data = GetYData() + start_index; + double sum = 0; + double ave = GetAverage(start_index, count); - for (int i=0; im_count; + wxPlotData dst; + wxCHECK_MSG(Ok(), dst, wxT("Invalid wxPlotData")); - int i; - int half_width = points/2; - int width = half_width * 2 + 1; - int end_index = data_count; //count <= 0 ? data_count : start_index + count; - int run_start = wxMax(0, half_width); - int run_end = wxMin(end_index, data_count - half_width); - - wxCHECK_MSG((data_count > half_width), dst, wxT("invalid data indexes")); - - if (!dst.Create(data_count, false)) return dst; + int data_count = M_PLOTDATA->m_count; - memcpy(dst.GetXData(), GetXData(), data_count*sizeof(double)); - memset(dst.GetYData(), 0, half_width*sizeof(double)); - memset(dst.GetYData()+data_count-half_width, 0, half_width*sizeof(double)); + int i; + int half_width = points / 2; + int width = half_width * 2 + 1; + int end_index = data_count; // count <= 0 ? data_count : start_index + count; + int run_start = wxMax(0, half_width); + int run_end = wxMin(end_index, data_count - half_width); - if (run_start >= run_end) return dst; - - for (i=run_start; i half_width), dst, wxT("invalid data indexes")); - dst.CalcBoundingRect(); + if (!dst.Create(data_count, false)) { return dst; -} - -double wxPlotData::Deviation( const wxPlotData &data, int min, int max ) const -{ - wxCHECK_MSG( Ok() && data.Ok(), 0.0, wxT("Invalid wxPlotData") ); - const int count = GetCount(); - wxCHECK_MSG((min >= 0)&&(min min, 0.0, wxT("invalid index range")); - - double data_x_min = data.GetBoundingRect().GetLeft(); - double data_x_max = data.GetBoundingRect().GetRight(); - const int data_count = data.GetCount(); - - double *x_data = M_PLOTDATA->m_Xdata + min; - double *y_data = M_PLOTDATA->m_Ydata + min; + } - double x, y, dev = 0.0; + memcpy(dst.GetXData(), GetXData(), data_count * sizeof(double)); + memset(dst.GetYData(), 0, half_width * sizeof(double)); + memset(dst.GetYData() + data_count - half_width, 0, half_width * sizeof(double)); - int index1=0, index2=0; - int points = 0; - int i; - - for (i=min; i= data_x_min) && (x <= data_x_max) ) + if (run_start >= run_end) { + return dst; + } + + for (i = run_start; i < run_end; i++) { + dst.SetYValue(i, Variance(i - half_width, width)); + } + + dst.CalcBoundingRect(); + return dst; +} + +double wxPlotData::Deviation(const wxPlotData &data, int min, int max) const +{ + wxCHECK_MSG(Ok() && data.Ok(), 0.0, wxT("Invalid wxPlotData")); + const int count = GetCount(); + wxCHECK_MSG((min >= 0) && (min < count), 0.0, wxT("invalid min index")); + if (max < 0) { + max = count; + } + wxCHECK_MSG(max > min, 0.0, wxT("invalid index range")); + + double data_x_min = data.GetBoundingRect().GetLeft(); + double data_x_max = data.GetBoundingRect().GetRight(); + const int data_count = data.GetCount(); + + double *x_data = M_PLOTDATA->m_Xdata + min; + double *y_data = M_PLOTDATA->m_Ydata + min; + + double x, y, dev = 0.0; + + int index1 = 0, index2 = 0; + int points = 0; + int i; + + for (i = min; i < max; i++) { + x = GetXValue(i); + y = GetYValue(i); + + if ((x >= data_x_min) && (x <= data_x_max)) { + index1 = data.GetIndexFromX(x); + if (data.GetXValue(index1) == x) { + double yd = (y - data.GetYValue(index1)); + dev += yd * yd; + points++; + } + else // need to interpolate to find data's y value at this x + { + if (x < data.GetXValue(index1)) { + index2 = index1; + index1--; + } + else // if (*x_data < data.GetX(index1)) { - index1 = data.GetIndexFromX(x); - if ( data.GetXValue(index1) == x ) - { - double yd = (y - data.GetYValue(index1)); - dev += yd*yd; - points++; - } - else // need to interpolate to find data's y value at this x - { - if (x < data.GetXValue(index1)) - { - index2 = index1; - index1--; - } - else //if (*x_data < data.GetX(index1)) - { - index2 = index1 + 1; - } - - if ((index1 >= 0) && (index2 < data_count) ) - { - double yd = y - LinearInterpolateY( data.GetXValue(index1), data.GetYValue(index1), - data.GetXValue(index2), data.GetYValue(index2), x ); - dev += yd*yd; - points++; - } - } + index2 = index1 + 1; + } + + if ((index1 >= 0) && (index2 < data_count)) { + double yd = y - LinearInterpolateY(data.GetXValue(index1), data.GetYValue(index1), + data.GetXValue(index2), data.GetYValue(index2), x); + dev += yd * yd; + points++; } - x_data++; - y_data++; + } } + x_data++; + y_data++; + } - dev = sqrt(dev); + dev = sqrt(dev); - if (points > 0) - return dev/double(points); + if (points > 0) { + return dev / double(points); + } - return -1; + return -1; } -double wxPlotData::CrossCorrelation( const wxPlotData &other, int runave, int min, int max ) const +double wxPlotData::CrossCorrelation(const wxPlotData &other, int runave, int min, int max) const { - //http://astronomy.swin.edu.au/~pbourke/analysis/correlate/ for discussion of crosscorrelation + // http://astronomy.swin.edu.au/~pbourke/analysis/correlate/ for discussion of crosscorrelation - wxCHECK_MSG( Ok() && other.Ok(), 0.0, wxT("Invalid wxPlotData") ); - const int count = GetCount(); - wxCHECK_MSG((min >= 0)&&(min min, 0.0, wxT("invalid index range")); + wxCHECK_MSG(Ok() && other.Ok(), 0.0, wxT("Invalid wxPlotData")); + const int count = GetCount(); + wxCHECK_MSG((min >= 0) && (min < count), 0.0, wxT("invalid min index")); + if (max < 0) { + max = count; + } + wxCHECK_MSG(max > min, 0.0, wxT("invalid index range")); - double cc = 0.0; + double cc = 0.0; - wxPlotData smooth(RunAverage(runave)); - wxPlotData other_smooth(other.RunAverage(runave)); + wxPlotData smooth(RunAverage(runave)); + wxPlotData other_smooth(other.RunAverage(runave)); - smooth.CalcBoundingRect(); - other_smooth.CalcBoundingRect(); + smooth.CalcBoundingRect(); + other_smooth.CalcBoundingRect(); - double other_x_min = other.GetBoundingRect().GetLeft(); - double other_x_max = other.GetBoundingRect().GetRight(); - int other_count = other.GetCount(); + double other_x_min = other.GetBoundingRect().GetLeft(); + double other_x_max = other.GetBoundingRect().GetRight(); + int other_count = other.GetCount(); - int i; + int i; - double *x_data = M_PLOTDATA->m_Xdata; - double *y_data = M_PLOTDATA->m_Ydata; - double *smooth_y_data = smooth.GetYData(); + double *x_data = M_PLOTDATA->m_Xdata; + double *y_data = M_PLOTDATA->m_Ydata; + double *smooth_y_data = smooth.GetYData(); - double x; + double x; - int index1, index2; + int index1, index2; - for (i=min; i= other_x_min) && (x <= other_x_max) ) + if ((x >= other_x_min) && (x <= other_x_max)) { + index1 = other.GetIndexFromX(x); + if (other.GetXValue(index1) == x) { + //*y_data -= data.GetY(index1); + // cc += (*y_data - data.GetY(index1))*(*y_data - data.GetY(index1)); + cc += (GetYValue(i) - smooth.GetYValue(i)) * + (other.GetYValue(index1) - other_smooth.GetYValue(index1)); + } + else // need to interpolate to find data's y value at this x + { + if (x < other.GetXValue(index1)) { + index2 = index1; + index1--; + } + else // if (*x_data < data.GetX(index1)) { - index1 = other.GetIndexFromX(x); - if ( other.GetXValue(index1) == x ) - { - //*y_data -= data.GetY(index1); - //cc += (*y_data - data.GetY(index1))*(*y_data - data.GetY(index1)); - cc += (GetYValue(i) - smooth.GetYValue(i))*(other.GetYValue(index1)-other_smooth.GetYValue(index1)); - } - else // need to interpolate to find data's y value at this x - { - if (x < other.GetXValue(index1)) - { - index2 = index1; - index1--; - } - else //if (*x_data < data.GetX(index1)) - { - index2 = index1 + 1; - } - if ((index1 >= 0) && (index1 < other_count) && (index2 >= 0) && (index2 < other_count) ) - { - double y = LinearInterpolateY( other.GetXValue(index1), other.GetYValue(index1), - other.GetXValue(index2), other.GetYValue(index2), - x ); - - double ys = LinearInterpolateY( other_smooth.GetXValue(index1), other_smooth.GetYValue(index1), - other_smooth.GetXValue(index2), other_smooth.GetYValue(index2), - x ); - - cc += (GetYValue(i) - smooth.GetYValue(i))*(y-ys); - } - } + index2 = index1 + 1; } + if ((index1 >= 0) && (index1 < other_count) && (index2 >= 0) && (index2 < other_count)) { + double y = LinearInterpolateY(other.GetXValue(index1), other.GetYValue(index1), + other.GetXValue(index2), other.GetYValue(index2), x); + + double ys = LinearInterpolateY( + other_smooth.GetXValue(index1), other_smooth.GetYValue(index1), + other_smooth.GetXValue(index2), other_smooth.GetYValue(index2), x); - x_data++; - y_data++; - smooth_y_data++; + cc += (GetYValue(i) - smooth.GetYValue(i)) * (y - ys); + } + } } - //cc = sqrt(cc); + x_data++; + y_data++; + smooth_y_data++; + } + + // cc = sqrt(cc); - return cc; + return cc; } -double wxPlotData::MinShiftX( const wxPlotData &other ) const +double wxPlotData::MinShiftX(const wxPlotData &other) const { - wxCHECK_MSG(Ok() && other.Ok(), 0.0, wxT("invalid plotcurve")); + wxCHECK_MSG(Ok() && other.Ok(), 0.0, wxT("invalid plotcurve")); - wxRect2DDouble boundRect = GetBoundingRect(); - wxRect2DDouble other_boundRect = other.GetBoundingRect(); + wxRect2DDouble boundRect = GetBoundingRect(); + wxRect2DDouble other_boundRect = other.GetBoundingRect(); - double start_shift = (boundRect.m_x - other_boundRect.m_x) - other_boundRect.m_width/2.0; - double end_shift = (boundRect.GetRight() - other_boundRect.m_x) - other_boundRect.m_width/2.0; - double min_dev = 0, min_shift = start_shift; - double step = fabs(M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]); + double start_shift = (boundRect.m_x - other_boundRect.m_x) - other_boundRect.m_width / 2.0; + double end_shift = (boundRect.GetRight() - other_boundRect.m_x) - other_boundRect.m_width / 2.0; + double min_dev = 0, min_shift = start_shift; + double step = fabs(M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]); - wxPlotData shifted; - shifted.Copy(other); - shifted.OffsetX(min_shift); + wxPlotData shifted; + shifted.Copy(other); + shifted.OffsetX(min_shift); - for (double x=start_shift; x= 0) - { - if (x == start_shift) - min_dev = dev; - else if (dev < min_dev) - { - min_dev = dev; - min_shift = x; - } - } + for (double x = start_shift; x < end_shift; x += step) { + double dev = Deviation(shifted); - shifted.OffsetX(step); + if (dev >= 0) { + if (x == start_shift) { + min_dev = dev; + } + else if (dev < min_dev) { + min_dev = dev; + min_shift = x; + } } - return min_shift; -} + shifted.OffsetX(step); + } + return min_shift; +} //---------------------------------------------------------------------------- // Fast Fourier Transform //---------------------------------------------------------------------------- -wxPlotData wxPlotData::FFT( bool forward ) -{ - wxCHECK_MSG( Ok(), wxPlotData(), wxT("Invalid wxPlotData") ); - wxCHECK_MSG( GetCount() < 2, wxPlotData(), wxT("Invalid wxPlotData size") ); - - // Find the next highest 2^n power - int samples = 1; - int orig_count = M_PLOTDATA->m_count; - while (samples < orig_count) samples *= 2; - - wxPlotData source; - source.Copy(*this); - - // resize the curve to the 2^n sample size required by fft_double - if (samples > orig_count) - { - double dx = M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]; - source.Resize(samples, dx, M_PLOTDATA->m_Ydata[orig_count - 1]); - } - - wxPlotData trans(samples); - trans.SetYiData( (double*)malloc(samples*sizeof(double)) ); - - if (fft_double( samples, (forward ? 0 : 1), - source.GetYData(), source.GetYiData(), - trans.GetYData(), trans.GetYiData() ) == 0) - return wxPlotData(); - - if (forward) - { - double *trans_xData = trans.GetXData(); - trans_xData[0] = 0.0; - double timestep = (M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0])*samples; - for (int i=0; im_Xdata[1] - M_PLOTDATA->m_Xdata[0])*double(samples)); - for (int i=0; im_count; + while (samples < orig_count) { + samples *= 2; + } + + wxPlotData source; + source.Copy(*this); + + // resize the curve to the 2^n sample size required by fft_double + if (samples > orig_count) { + double dx = M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]; + source.Resize(samples, dx, M_PLOTDATA->m_Ydata[orig_count - 1]); + } + + wxPlotData trans(samples); + trans.SetYiData((double *)malloc(samples * sizeof(double))); + + if (fft_double(samples, (forward ? 0 : 1), source.GetYData(), source.GetYiData(), + trans.GetYData(), trans.GetYiData()) == 0) { + return wxPlotData(); + } + + if (forward) { + double *trans_xData = trans.GetXData(); + trans_xData[0] = 0.0; + double timestep = (M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]) * samples; + for (int i = 0; i < samples; i++) { + trans_xData[i] = double(i) / timestep; + } + /* FIXME - what to do with the other half of the FFT transform ? + if you throw it away, should you create other half automatically + + for (int i=1; i<=samples/2; i++) + { + trans_xData[i] = double(i)/timestep; + trans_xData[samples-i] = double(i)/timestep; + } + */ + // trans = trans.Remove(samples/2, samples/2); + } + else { + double *trans_xData = trans.GetXData(); + double timestep = 1.0 / ((M_PLOTDATA->m_Xdata[1] - M_PLOTDATA->m_Xdata[0]) * double(samples)); + for (int i = 0; i < samples; i++) { + trans_xData[i] = timestep * double(i); } + } - trans.CalcBoundingRect(); - return trans; + trans.CalcBoundingRect(); + return trans; } wxPlotData wxPlotData::PowerSpectrum() { - wxCHECK_MSG( Ok(), wxPlotData(), wxT("Invalid wxPlotData, wxPlotData::RunAverage()") ); - - wxPlotData power(FFT(true)); - wxCHECK_MSG(power.Ok(), wxPlotData(), wxT("Invalid FFT data curve")); - - int i, count = power.GetCount(); - for (i=0; i%lg"), hi); - case FilterButterworth : return wxString::Format(wxT("1 - 1/(1+(x/%lg)^(2*%lg))"), hi, n); - case FilterGaussian : return wxString::Format(wxT("exp(-(%lg^2)/(2*x*x))"), hi); - case FilterFermi : return wxString::Format(wxT("1/(1+exp((%lg-x)/%lg))"), hi, n); - default : break; - } - return wxEmptyString; -} - -wxString wxPlotData::FFTLoPassFilterFormat( double lo, wxPlotData::FFTFilter_Type filter, double n ) -{ - switch (filter) - { - case FilterStep : return wxString::Format(wxT("x<%lg"), lo); - case FilterButterworth : return wxString::Format(wxT("1/(1+(x/%lg)^(2*%lg))"), lo, n); - case FilterGaussian : return wxString::Format(wxT("1 - exp(-(%lg^2)/(2*x*x))"), lo); - case FilterFermi : return wxString::Format(wxT("1/(1+exp((%lg-x)/(-%lg)))"), lo, n); - default : break; - } - return wxEmptyString; -} - -wxString wxPlotData::FFTNotchFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) -{ - switch (filter) - { - case FilterStep : return wxString::Format(wxT("(x<%lg)|(x>%lg)"), lo, hi); - case FilterButterworth : return wxString::Format(wxT("1/(1+(x/%lg)^(2*%lg)) + (1-1/(1+(x/%lg)^(2*%lg)))"), lo, n, hi, n); - case FilterGaussian : return wxString::Format(wxT("2-(exp(-(%lg^2)/(2*x*x))+(1-exp(-(%lg^2)/(2*x*x))))"), lo, hi); - case FilterFermi : return wxString::Format(wxT("1/(1+exp((%lg-x)/(-%lg))) + 1/(1+exp((%lg-x)/(%lg)))"), lo, n, hi, n); - default : break; - } - return wxEmptyString; -} - -wxString wxPlotData::FFTBandPassFilterFormat( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) -{ - switch (filter) - { - case FilterStep : return wxString::Format(wxT("(x>%lg)&(x<%lg)"), lo, hi); - case FilterButterworth : return wxString::Format(wxT("1 - (1/(1+(x/%lg)^(2*%lg))+(1-1/(1+(x/%lg)^(2*%lg))))"), lo, n, hi, n); - case FilterGaussian : return wxString::Format(wxT("exp(-(%lg^2)/(2*x*x)) - exp(-(%lg^2)/(2*x*x))"), lo, hi); - case FilterFermi : return wxString::Format(wxT("1 - 1/(1+exp((%lg-x)/(-%lg))) - 1/(1+exp((%lg-x)/(%lg)))"), lo, n, hi, n); - default : break; - } - return wxEmptyString; + wxCHECK_MSG(Ok(), wxPlotData(), wxT("Invalid wxPlotData, wxPlotData::RunAverage()")); + + wxPlotData power(FFT(true)); + wxCHECK_MSG(power.Ok(), wxPlotData(), wxT("Invalid FFT data curve")); + + int i, count = power.GetCount(); + for (i = 0; i < count; i++) { + power.GetYData()[i] = pow(power.GetYData()[i] * power.GetYData()[i] + + power.GetYiData()[i] * power.GetYiData()[i], + 0.5) / + double(count); + } + + power.CalcBoundingRect(); + + return power; +} + +wxString wxPlotData::FFTHiPassFilterFormat(double hi, wxPlotData::FFTFilter_Type filter, double n) +{ + switch (filter) { + case FilterStep: + return wxString::Format(wxT("x>%lg"), hi); + case FilterButterworth: + return wxString::Format(wxT("1 - 1/(1+(x/%lg)^(2*%lg))"), hi, n); + case FilterGaussian: + return wxString::Format(wxT("exp(-(%lg^2)/(2*x*x))"), hi); + case FilterFermi: + return wxString::Format(wxT("1/(1+exp((%lg-x)/%lg))"), hi, n); + default: + break; + } + return wxEmptyString; +} + +wxString wxPlotData::FFTLoPassFilterFormat(double lo, wxPlotData::FFTFilter_Type filter, double n) +{ + switch (filter) { + case FilterStep: + return wxString::Format(wxT("x<%lg"), lo); + case FilterButterworth: + return wxString::Format(wxT("1/(1+(x/%lg)^(2*%lg))"), lo, n); + case FilterGaussian: + return wxString::Format(wxT("1 - exp(-(%lg^2)/(2*x*x))"), lo); + case FilterFermi: + return wxString::Format(wxT("1/(1+exp((%lg-x)/(-%lg)))"), lo, n); + default: + break; + } + return wxEmptyString; +} + +wxString wxPlotData::FFTNotchFilterFormat(double lo, double hi, wxPlotData::FFTFilter_Type filter, + double n) +{ + switch (filter) { + case FilterStep: + return wxString::Format(wxT("(x<%lg)|(x>%lg)"), lo, hi); + case FilterButterworth: + return wxString::Format(wxT("1/(1+(x/%lg)^(2*%lg)) + (1-1/(1+(x/%lg)^(2*%lg)))"), lo, n, hi, + n); + case FilterGaussian: + return wxString::Format(wxT("2-(exp(-(%lg^2)/(2*x*x))+(1-exp(-(%lg^2)/(2*x*x))))"), lo, hi); + case FilterFermi: + return wxString::Format(wxT("1/(1+exp((%lg-x)/(-%lg))) + 1/(1+exp((%lg-x)/(%lg)))"), lo, n, hi, + n); + default: + break; + } + return wxEmptyString; +} + +wxString wxPlotData::FFTBandPassFilterFormat(double lo, double hi, + wxPlotData::FFTFilter_Type filter, double n) +{ + switch (filter) { + case FilterStep: + return wxString::Format(wxT("(x>%lg)&(x<%lg)"), lo, hi); + case FilterButterworth: + return wxString::Format(wxT("1 - (1/(1+(x/%lg)^(2*%lg))+(1-1/(1+(x/%lg)^(2*%lg))))"), lo, n, + hi, n); + case FilterGaussian: + return wxString::Format(wxT("exp(-(%lg^2)/(2*x*x)) - exp(-(%lg^2)/(2*x*x))"), lo, hi); + case FilterFermi: + return wxString::Format(wxT("1 - 1/(1+exp((%lg-x)/(-%lg))) - 1/(1+exp((%lg-x)/(%lg)))"), lo, n, + hi, n); + default: + break; + } + return wxEmptyString; } // butterworth lo=1./(1.+ (x/fc)**(2*n)), hi=1-1./(1.+ (x/fc)**(2*n)) // gaussian lo = 1.0-exp(-fc**2/(2.*x**2)), hi = exp(-fc**2/(2.*x**2)) // fermi lo= 1/(1+exp[(fc-x)/n]) , hi = 1/(1+exp((x-fc)/(-n))) -wxPlotData wxPlotData::FFTHiPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n ) +wxPlotData wxPlotData::FFTHiPassFilter(double fc, wxPlotData::FFTFilter_Type filter, double n) { - wxCHECK_MSG( Ok() && (n>0), wxPlotData(), wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok() && (n > 0), wxPlotData(), wxT("Invalid wxPlotData")); - wxPlotData xform( FFT(true) ); + wxPlotData xform(FFT(true)); - int i, count = xform.GetCount(); - double f, x; - double *ydata = xform.GetYData(), - *yidata = xform.GetYiData(); + int i, count = xform.GetCount(); + double f, x; + double *ydata = xform.GetYData(), *yidata = xform.GetYiData(); - for (i=0; im_Xdata[0]); - dest.CalcBoundingRect(); - return dest; + ydata++; + yidata++; + } + + wxPlotData dest(xform.FFT(false)); + dest.OffsetX(M_PLOTDATA->m_Xdata[0]); + dest.CalcBoundingRect(); + return dest; } -wxPlotData wxPlotData::FFTLoPassFilter( double fc, wxPlotData::FFTFilter_Type filter, double n ) +wxPlotData wxPlotData::FFTLoPassFilter(double fc, wxPlotData::FFTFilter_Type filter, double n) { - wxCHECK_MSG( Ok() && (n>0), wxPlotData(), wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok() && (n > 0), wxPlotData(), wxT("Invalid wxPlotData")); - wxPlotData xform( FFT(true) ); + wxPlotData xform(FFT(true)); - int i, count = xform.GetCount(); - double f, x; - double *ydata = xform.GetYData(), - *yidata = xform.GetYiData(); + int i, count = xform.GetCount(); + double f, x; + double *ydata = xform.GetYData(), *yidata = xform.GetYiData(); - for (i=0; i fc)) - { - *ydata = 0; - *yidata = 0; - } - else - { - if (filter == FilterButterworth) - f = 1.0/(1.0 + pow(x/fc, 2.0*n)); - else if (filter == FilterGaussian) - f = 1.0 - exp(-fc*fc/(2.0*x*x)); - else // (filter == FilterFermi) - f = 1.0/(1.0+exp((fc-x)/(-n))); - - *ydata *= f; - *yidata *= f; - } + if ((filter == FilterStep) && (x > fc)) { + *ydata = 0; + *yidata = 0; + } + else { + if (filter == FilterButterworth) { + f = 1.0 / (1.0 + pow(x / fc, 2.0 * n)); + } + else if (filter == FilterGaussian) { + f = 1.0 - exp(-fc * fc / (2.0 * x * x)); + } + else { // (filter == FilterFermi) + f = 1.0 / (1.0 + exp((fc - x) / (-n))); + } - ydata++; - yidata++; + *ydata *= f; + *yidata *= f; } - wxPlotData dest( xform.FFT(false) ); - dest.OffsetX(M_PLOTDATA->m_Xdata[0]); - dest.CalcBoundingRect(); - return dest; + ydata++; + yidata++; + } + + wxPlotData dest(xform.FFT(false)); + dest.OffsetX(M_PLOTDATA->m_Xdata[0]); + dest.CalcBoundingRect(); + return dest; } -wxPlotData wxPlotData::FFTNotchFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) +wxPlotData wxPlotData::FFTNotchFilter(double lo, double hi, wxPlotData::FFTFilter_Type filter, + double n) { - wxCHECK_MSG( Ok() && (lo <= hi) && (n>0), wxPlotData(), wxT("Invalid wxPlotData") ); + wxCHECK_MSG(Ok() && (lo <= hi) && (n > 0), wxPlotData(), wxT("Invalid wxPlotData")); - wxPlotData xform( FFT(true) ); + wxPlotData xform(FFT(true)); - int i, count = xform.GetCount(); - double x, f; - double *ydata = xform.GetYData(), - *yidata = xform.GetYiData(); + int i, count = xform.GetCount(); + double x, f; + double *ydata = xform.GetYData(), *yidata = xform.GetYiData(); - for (i=0; i= lo) && (x <= hi))) - { - *ydata = 0; - *yidata = 0; - } - else - { - if (filter == FilterButterworth) - f = 1.0/(1.0 + pow(x/lo, 2.0*n)) + (1.0-1.0/(1.0 + pow(x/hi, 2.0*n))); - else if (filter == FilterGaussian) - f = 2.0 - (exp(-lo*lo/(2.0*x*x)) + (1.0 - exp(-hi*hi/(2.0*x*x)))); - else // (filter == FilterFermi) - f = 1.0/(1.0+exp((lo-x)/(-n))) + 1.0/(1.0+exp((hi-x)/(n))); - - *ydata *= f; - *yidata *= f; - } + if ((filter == FilterStep) && ((x >= lo) && (x <= hi))) { + *ydata = 0; + *yidata = 0; + } + else { + if (filter == FilterButterworth) { + f = 1.0 / (1.0 + pow(x / lo, 2.0 * n)) + (1.0 - 1.0 / (1.0 + pow(x / hi, 2.0 * n))); + } + else if (filter == FilterGaussian) { + f = 2.0 - (exp(-lo * lo / (2.0 * x * x)) + (1.0 - exp(-hi * hi / (2.0 * x * x)))); + } + else { // (filter == FilterFermi) + f = 1.0 / (1.0 + exp((lo - x) / (-n))) + 1.0 / (1.0 + exp((hi - x) / (n))); + } - ydata++; - yidata++; + *ydata *= f; + *yidata *= f; } - wxPlotData dest( xform.FFT(false) ); - dest.OffsetX(M_PLOTDATA->m_Xdata[0]); - dest.CalcBoundingRect(); - return dest; + ydata++; + yidata++; + } + + wxPlotData dest(xform.FFT(false)); + dest.OffsetX(M_PLOTDATA->m_Xdata[0]); + dest.CalcBoundingRect(); + return dest; } -wxPlotData wxPlotData::FFTBandPassFilter( double lo, double hi, wxPlotData::FFTFilter_Type filter, double n ) +wxPlotData wxPlotData::FFTBandPassFilter(double lo, double hi, wxPlotData::FFTFilter_Type filter, + double n) { - wxPlotData xform; - wxCHECK_MSG( Ok() && (lo <= hi) && (n>0), xform, wxT("Invalid wxPlotData") ); + wxPlotData xform; + wxCHECK_MSG(Ok() && (lo <= hi) && (n > 0), xform, wxT("Invalid wxPlotData")); - xform = FFT(true); - if (!xform.Ok()) return xform; + xform = FFT(true); + if (!xform.Ok()) { + return xform; + } - int i, count = xform.GetCount(); - double x, f; + int i, count = xform.GetCount(); + double x, f; - double *xform_xdata = xform.GetXData(), - *xform_ydata = xform.GetYData(), - *xform_yidata = xform.GetYiData(); + double *xform_xdata = xform.GetXData(), *xform_ydata = xform.GetYData(), + *xform_yidata = xform.GetYiData(); - for (i=0; i= hi))) - { - *xform_ydata = 0; - *xform_yidata = 0; - } - else - { - if (filter == FilterButterworth) - f = 1.0-(1.0/(1.0 + pow(x/lo, 2.0*n)) + (1.0-1.0/(1.0 + pow(x/hi, 2.0*n)))); - else if (filter == FilterGaussian) - f = exp(-lo*lo/(2.0*x*x)) - exp(-hi*hi/(2.0*x*x)); - else // (filter == FilterFermi) - f = 1.0 - 1.0/(1.0+exp((lo-x)/(-n))) - 1.0/(1.0+exp((hi-x)/(n))); - - *xform_ydata *= f; - *xform_yidata *= f; - } + if ((filter == FilterStep) && ((x <= lo) || (x >= hi))) { + *xform_ydata = 0; + *xform_yidata = 0; + } + else { + if (filter == FilterButterworth) { + f = 1.0 - + (1.0 / (1.0 + pow(x / lo, 2.0 * n)) + (1.0 - 1.0 / (1.0 + pow(x / hi, 2.0 * n)))); + } + else if (filter == FilterGaussian) { + f = exp(-lo * lo / (2.0 * x * x)) - exp(-hi * hi / (2.0 * x * x)); + } + else { // (filter == FilterFermi) + f = 1.0 - 1.0 / (1.0 + exp((lo - x) / (-n))) - 1.0 / (1.0 + exp((hi - x) / (n))); + } - xform_ydata++; - xform_yidata++; + *xform_ydata *= f; + *xform_yidata *= f; } - wxPlotData dst( xform.FFT(false) ); - if (!dst.Ok()) return dst; - dst.OffsetX(M_PLOTDATA->m_Xdata[0]); - dst.CalcBoundingRect(); + xform_ydata++; + xform_yidata++; + } + + wxPlotData dst(xform.FFT(false)); + if (!dst.Ok()) { return dst; + } + dst.OffsetX(M_PLOTDATA->m_Xdata[0]); + dst.CalcBoundingRect(); + return dst; } -wxPlotData wxPlotData::FFTCustomFilter( const wxPlotFunction &func ) +wxPlotData wxPlotData::FFTCustomFilter(const wxPlotFunction &func) { - wxCHECK_MSG(Ok() && func.Ok(), wxPlotData(), wxT("invalid curve")); - - wxPlotData xform = FFT(true); - if (!xform.Ok()) return xform; + wxCHECK_MSG(Ok() && func.Ok(), wxPlotData(), wxT("invalid curve")); - xform = xform.Modify(func, mult_y); - if (!xform.Ok()) return xform; + wxPlotData xform = FFT(true); + if (!xform.Ok()) { + return xform; + } - xform = xform.Modify(func, mult_yi); - if (!xform.Ok()) return xform; + xform = xform.Modify(func, mult_y); + if (!xform.Ok()) { + return xform; + } - wxPlotData dst( xform.FFT(false) ); - if (!dst.Ok()) return dst; + xform = xform.Modify(func, mult_yi); + if (!xform.Ok()) { + return xform; + } - dst.OffsetX(M_PLOTDATA->m_Xdata[0]); - dst.CalcBoundingRect(); + wxPlotData dst(xform.FFT(false)); + if (!dst.Ok()) { return dst; + } + + dst.OffsetX(M_PLOTDATA->m_Xdata[0]); + dst.CalcBoundingRect(); + return dst; } bool wxPlotData::SortByX() { - wxCHECK_MSG( Ok(), false, wxT("Invalid wxPlotData") ); - IMPLEMENT_PIXEL_QSORT2(double, M_PLOTDATA->m_Xdata, M_PLOTDATA->m_Ydata, M_PLOTDATA->m_count); - return true; + wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); + IMPLEMENT_PIXEL_QSORT2(double, M_PLOTDATA->m_Xdata, M_PLOTDATA->m_Ydata, M_PLOTDATA->m_count); + return true; } bool wxPlotData::SortByY() { - wxCHECK_MSG( Ok(), false, wxT("Invalid wxPlotData") ); - IMPLEMENT_PIXEL_QSORT2(double, M_PLOTDATA->m_Ydata, M_PLOTDATA->m_Xdata, M_PLOTDATA->m_count); - return true; + wxCHECK_MSG(Ok(), false, wxT("Invalid wxPlotData")); + IMPLEMENT_PIXEL_QSORT2(double, M_PLOTDATA->m_Ydata, M_PLOTDATA->m_Xdata, M_PLOTDATA->m_count); + return true; } //------------------------------------------------------------------------- @@ -2828,104 +2991,98 @@ int wxPlotData::AmoebaFit( const wxPlotFunction &func, double *vars ) wxBitmap wxPlotData::GetSymbol(wxPlotPen_Type colour_type) const { - wxCHECK_MSG( Ok(), M_PLOTDATA->m_normalSymbol, wxT("Invalid wxPlotData") ); - - switch (colour_type) - { - case wxPLOTPEN_ACTIVE : - return M_PLOTDATA->m_activeSymbol; - case wxPLOTPEN_SELECTED : - return M_PLOTDATA->m_selectedSymbol; - default : break; //case wxPLOTPEN_NORMAL : - } - - return M_PLOTDATA->m_normalSymbol; -} - -void wxPlotData::SetSymbol( const wxBitmap &bitmap, wxPlotPen_Type colour_type ) -{ - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - wxCHECK_RET( bitmap.Ok(), wxT("Invalid bitmap") ); - - switch (colour_type) - { - case wxPLOTPEN_ACTIVE : - M_PLOTDATA->m_activeSymbol = bitmap; - break; - case wxPLOTPEN_SELECTED : - M_PLOTDATA->m_selectedSymbol = bitmap; - break; - default : //case wxPLOTPEN_NORMAL : - M_PLOTDATA->m_normalSymbol = bitmap; - break; - } -} -void wxPlotData::SetSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type, int width , int height, - const wxPen *pen, const wxBrush *brush) -{ - wxCHECK_RET( Ok(), wxT("Invalid wxPlotData") ); - - switch (colour_type) - { - case wxPLOTPEN_ACTIVE : - M_PLOTDATA->m_activeSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); - break; - case wxPLOTPEN_SELECTED : - M_PLOTDATA->m_selectedSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); - break; - default : //case wxPLOTPEN_NORMAL : - M_PLOTDATA->m_normalSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); - break; - } -} - -wxBitmap wxPlotData::CreateSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour_type, int width, int height, - const wxPen *pen, const wxBrush *brush) -{ - wxBitmap b(width, height); - - wxMemoryDC mdc; - mdc.SelectObject(b); - mdc.SetPen(*wxWHITE_PEN); - mdc.SetBrush(*wxWHITE_BRUSH); + wxCHECK_MSG(Ok(), M_PLOTDATA->m_normalSymbol, wxT("Invalid wxPlotData")); + + switch (colour_type) { + case wxPLOTPEN_ACTIVE: + return M_PLOTDATA->m_activeSymbol; + case wxPLOTPEN_SELECTED: + return M_PLOTDATA->m_selectedSymbol; + default: + break; // case wxPLOTPEN_NORMAL : + } + + return M_PLOTDATA->m_normalSymbol; +} + +void wxPlotData::SetSymbol(const wxBitmap &bitmap, wxPlotPen_Type colour_type) +{ + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + wxCHECK_RET(bitmap.Ok(), wxT("Invalid bitmap")); + + switch (colour_type) { + case wxPLOTPEN_ACTIVE: + M_PLOTDATA->m_activeSymbol = bitmap; + break; + case wxPLOTPEN_SELECTED: + M_PLOTDATA->m_selectedSymbol = bitmap; + break; + default: // case wxPLOTPEN_NORMAL : + M_PLOTDATA->m_normalSymbol = bitmap; + break; + } +} +void wxPlotData::SetSymbol(wxPlotSymbol_Type type, wxPlotPen_Type colour_type, int width, + int height, const wxPen *pen, const wxBrush *brush) +{ + wxCHECK_RET(Ok(), wxT("Invalid wxPlotData")); + + switch (colour_type) { + case wxPLOTPEN_ACTIVE: + M_PLOTDATA->m_activeSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); + break; + case wxPLOTPEN_SELECTED: + M_PLOTDATA->m_selectedSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); + break; + default: // case wxPLOTPEN_NORMAL : + M_PLOTDATA->m_normalSymbol = CreateSymbol(type, colour_type, width, height, pen, brush); + break; + } +} + +wxBitmap wxPlotData::CreateSymbol(wxPlotSymbol_Type type, wxPlotPen_Type colour_type, int width, + int height, const wxPen *pen, const wxBrush *brush) +{ + wxBitmap b(width, height); + + wxMemoryDC mdc; + mdc.SelectObject(b); + mdc.SetPen(*wxWHITE_PEN); + mdc.SetBrush(*wxWHITE_BRUSH); + mdc.DrawRectangle(0, 0, width, height); + /* + if (pen) + mdc.SetPen(*pen); + else + mdc.SetPen(GetNormalPen()); + */ + switch (type) { + case wxPLOTSYMBOL_ELLIPSE: { + mdc.DrawEllipse(width / 2, height / 2, width / 2, height / 2); + break; + } + case wxPLOTSYMBOL_RECTANGLE: { mdc.DrawRectangle(0, 0, width, height); -/* - if (pen) - mdc.SetPen(*pen); - else - mdc.SetPen(GetNormalPen()); -*/ - switch (type) - { - case wxPLOTSYMBOL_ELLIPSE : - { - mdc.DrawEllipse(width/2, height/2, width/2, height/2); - break; - } - case wxPLOTSYMBOL_RECTANGLE : - { - mdc.DrawRectangle(0, 0, width, height); - break; - } - case wxPLOTSYMBOL_CROSS : - { - mdc.DrawLine(0, 0, width , height); - mdc.DrawLine(0, height, width, 0); - break; - } - case wxPLOTSYMBOL_PLUS : - { - mdc.DrawLine(0, height/2, width, height/2); - mdc.DrawLine(width/2, 0, width/2, height); - break; - } + break; + } + case wxPLOTSYMBOL_CROSS: { + mdc.DrawLine(0, 0, width, height); + mdc.DrawLine(0, height, width, 0); + break; + } + case wxPLOTSYMBOL_PLUS: { + mdc.DrawLine(0, height / 2, width, height / 2); + mdc.DrawLine(width / 2, 0, width / 2, height); + break; + } - default : break; - } + default: + break; + } - b.SetMask(new wxMask(b, *wxWHITE)); + b.SetMask(new wxMask(b, *wxWHITE)); - return b; + return b; } // ---------------------------------------------------------------------------- @@ -2934,78 +3091,70 @@ wxBitmap wxPlotData::CreateSymbol( wxPlotSymbol_Type type, wxPlotPen_Type colour #include "wx/clipbrd.h" #if wxUSE_DATAOBJ && wxUSE_CLIPBOARD -const wxChar* wxDF_wxPlotData = wxT("wxDF_wxPlotData"); +const wxChar *wxDF_wxPlotData = wxT("wxDF_wxPlotData"); static wxPlotData s_clipboardwxPlotData; // temp storage of clipboard data static wxString s_clipboardwxPlotData_data; // holds wxNow() to match clipboard data // For some strange reason you get a segfault destroying s_clipboardwxPlotData // using gcc 3.4 at least. Using a wxModule to destroy it fixes this. -//#0 0x40aefee1 in posix_memalign () from /lib/tls/libc.so.6 -//#1 0x40aedd4c in mallopt () from /lib/tls/libc.so.6 -//#2 0x40aeb8ba in free () from /lib/tls/libc.so.6 -//#3 0x4060e885 in ~wxPlotDataRefData (this=0x82bc4b0) at plotcurve.cpp:203 -//#4 0x40518d1a in wxObject::UnRef() (this=0x40630ef4) at src/common/object.cpp:309 -//#5 0x0809d0e4 in ~wxObject (this=0x40630ef4) at object.h:431 -//#6 0x4061cd42 in ~wxPlotCurve (this=0x40630ef4) at plotcurve.h:110 -//#7 0x4061c43c in ~wxPlotData (this=0x40630ef4) at plotcurve.h:297 -//#8 0x4061c247 in __tcf_7 () at plotcurve.cpp:3044 +// #0 0x40aefee1 in posix_memalign () from /lib/tls/libc.so.6 +// #1 0x40aedd4c in mallopt () from /lib/tls/libc.so.6 +// #2 0x40aeb8ba in free () from /lib/tls/libc.so.6 +// #3 0x4060e885 in ~wxPlotDataRefData (this=0x82bc4b0) at plotcurve.cpp:203 +// #4 0x40518d1a in wxObject::UnRef() (this=0x40630ef4) at src/common/object.cpp:309 +// #5 0x0809d0e4 in ~wxObject (this=0x40630ef4) at object.h:431 +// #6 0x4061cd42 in ~wxPlotCurve (this=0x40630ef4) at plotcurve.h:110 +// #7 0x4061c43c in ~wxPlotData (this=0x40630ef4) at plotcurve.h:297 +// #8 0x4061c247 in __tcf_7 () at plotcurve.cpp:3044 #include "wx/module.h" -class wxPlotDataModule: public wxModule -{ -DECLARE_DYNAMIC_CLASS(wxPlotDataModule) +class wxPlotDataModule : public wxModule { + DECLARE_DYNAMIC_CLASS(wxPlotDataModule) public: - wxPlotDataModule() : wxModule() {} - bool OnInit() - { - return true; - } - void OnExit() - { - s_clipboardwxPlotData.Destroy(); - } + wxPlotDataModule() : wxModule() {} + bool OnInit() { return true; } + void OnExit() { s_clipboardwxPlotData.Destroy(); } }; IMPLEMENT_DYNAMIC_CLASS(wxPlotDataModule, wxModule) wxPlotData wxClipboardGetPlotData() { - bool is_opened = wxTheClipboard->IsOpened(); - wxPlotData plotData; + bool is_opened = wxTheClipboard->IsOpened(); + wxPlotData plotData; - if (is_opened || wxTheClipboard->Open()) - { - wxPlotDataObject plotDataObject; - if (wxTheClipboard->IsSupported(wxDataFormat(wxDF_wxPlotData)) && - wxTheClipboard->GetData(plotDataObject) && - (plotDataObject.GetText() == s_clipboardwxPlotData_data)) - { - plotData.Copy(plotDataObject.GetPlotData(), true); - } + if (is_opened || wxTheClipboard->Open()) { + wxPlotDataObject plotDataObject; + if (wxTheClipboard->IsSupported(wxDataFormat(wxDF_wxPlotData)) && + wxTheClipboard->GetData(plotDataObject) && + (plotDataObject.GetText() == s_clipboardwxPlotData_data)) { + plotData.Copy(plotDataObject.GetPlotData(), true); + } - if (!is_opened) - wxTheClipboard->Close(); + if (!is_opened) { + wxTheClipboard->Close(); } + } - return plotData; + return plotData; } -bool wxClipboardSetPlotData(const wxPlotData& plotData) +bool wxClipboardSetPlotData(const wxPlotData &plotData) { wxCHECK_MSG(plotData.Ok(), false, wxT("Invalid wxPlotData to copy to clipboard")); - bool is_opened = wxTheClipboard->IsOpened(); + bool is_opened = wxTheClipboard->IsOpened(); - if (is_opened || wxTheClipboard->Open()) - { - wxPlotDataObject *plotDataObject = new wxPlotDataObject(plotData); - bool ret = wxTheClipboard->SetData( plotDataObject ); + if (is_opened || wxTheClipboard->Open()) { + wxPlotDataObject *plotDataObject = new wxPlotDataObject(plotData); + bool ret = wxTheClipboard->SetData(plotDataObject); - if (!is_opened) - wxTheClipboard->Close(); - - return ret; + if (!is_opened) { + wxTheClipboard->Close(); } - return false; + return ret; + } + + return false; } // ---------------------------------------------------------------------------- @@ -3014,26 +3163,25 @@ bool wxClipboardSetPlotData(const wxPlotData& plotData) wxPlotDataObject::wxPlotDataObject() : wxTextDataObject() { - SetFormat(wxDataFormat(wxDF_wxPlotData)); -} -wxPlotDataObject::wxPlotDataObject(const wxPlotData& plotData) : wxTextDataObject() -{ - SetFormat(wxDataFormat(wxDF_wxPlotData)); - SetPlotData(plotData); + SetFormat(wxDataFormat(wxDF_wxPlotData)); } -wxPlotData wxPlotDataObject::GetPlotData() const +wxPlotDataObject::wxPlotDataObject(const wxPlotData &plotData) : wxTextDataObject() { - return s_clipboardwxPlotData; + SetFormat(wxDataFormat(wxDF_wxPlotData)); + SetPlotData(plotData); } -void wxPlotDataObject::SetPlotData(const wxPlotData& plotData) +wxPlotData wxPlotDataObject::GetPlotData() const { return s_clipboardwxPlotData; } +void wxPlotDataObject::SetPlotData(const wxPlotData &plotData) { - s_clipboardwxPlotData_data = wxNow(); - SetText(s_clipboardwxPlotData_data); + s_clipboardwxPlotData_data = wxNow(); + SetText(s_clipboardwxPlotData_data); - if (plotData.Ok()) - s_clipboardwxPlotData.Copy(plotData, true); - else - s_clipboardwxPlotData.Destroy(); + if (plotData.Ok()) { + s_clipboardwxPlotData.Copy(plotData, true); + } + else { + s_clipboardwxPlotData.Destroy(); + } } #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD diff --git a/src/labenski/src/plotdraw.cpp b/src/labenski/src/plotdraw.cpp index 7e04f34ec..f9cab9645 100644 --- a/src/labenski/src/plotdraw.cpp +++ b/src/labenski/src/plotdraw.cpp @@ -12,11 +12,11 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/dcmemory.h" +#include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/math.h" @@ -29,33 +29,35 @@ // MSVC hogs global namespace with these min/max macros - remove them #ifdef max - #undef max +#undef max #endif #ifdef min - #undef min +#undef min #endif -#ifdef GetYValue // Visual Studio 7 defines this - #undef GetYValue +#ifdef GetYValue // Visual Studio 7 defines this +#undef GetYValue #endif #ifdef wxFinite #undef wxFinite #define wxFinite(x) std::isfinite(x) -#endif // wxFinite +#endif // wxFinite -#define LONG_TO_WXCOLOUR(c) wxColour((unsigned char)((c>>16)&0xFF), (unsigned char)((c>>8 )&0xFF), (unsigned char)((c)&0xFF)) -#define WXCOLOUR_TO_LONG(c) ((c.Red()<<16)|(c.Green()<<8)|(c.Blue())) +#define LONG_TO_WXCOLOUR(c) \ + wxColour((unsigned char)((c >> 16) & 0xFF), (unsigned char)((c >> 8) & 0xFF), \ + (unsigned char)((c) & 0xFF)) +#define WXCOLOUR_TO_LONG(c) ((c.Red() << 16) | (c.Green() << 8) | (c.Blue())) -#define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x) - 0.5)) +#define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x)-0.5)) -#if !wxCHECK_VERSION(2,5,0) - bool WXRECT2DDOUBLE_EQUAL(const wxRect2DDouble& r1, const wxRect2DDouble& r2) - { - return (r1.m_x == r1.m_x) && (r1.m_y == r1.m_y) && - (r1.m_width == r1.m_width) && (r1.m_height == r1.m_height); - } +#if !wxCHECK_VERSION(2, 5, 0) +bool WXRECT2DDOUBLE_EQUAL(const wxRect2DDouble &r1, const wxRect2DDouble &r2) +{ + return (r1.m_x == r1.m_x) && (r1.m_y == r1.m_y) && (r1.m_width == r1.m_width) && + (r1.m_height == r1.m_height); +} #else - #define WXRECT2DDOUBLE_EQUAL(r1, r2) ((r1) == (r2)) +#define WXRECT2DDOUBLE_EQUAL(r1, r2) ((r1) == (r2)) #endif // wxCHECK_VERSION(2,5,0) //----------------------------------------------------------------------------- @@ -65,115 +67,112 @@ // Skip the wxWidgets drawing routines since they calc an unnecessary bounding rect // You may turn this off by defining wxPLOT_FAST_GRAPHICS=0 to the compilier #ifndef wxPLOT_FAST_GRAPHICS - #define wxPLOT_FAST_GRAPHICS 0 +#define wxPLOT_FAST_GRAPHICS 0 #endif // wxPLOT_FAST_GRAPHICS #if defined(__WXGTK__) && wxPLOT_FAST_GRAPHICS extern "C" { - #include +#include } - #define INITIALIZE_FAST_GRAPHICS \ - double dc_scale_x = 1, dc_scale_y = 1; \ - dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ - wxPoint dc_origin = dc->GetDeviceOrigin(); \ - wxWindowDC *winDC = wxDynamicCast(dc, wxWindowDC); \ - GdkWindow *window = NULL; \ - GdkGC *pen = NULL; \ - if (winDC && (dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ - { \ - window = winDC->m_window; \ - pen = winDC->m_penGC; \ - } - - // inline void wxPLOT_DRAW_LINE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0, int x1, int y1) - #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ - if (win && pen) \ - gdk_draw_line( win, pen, x0, y0, x1, y1 ); \ - else \ - dc->DrawLine( x0, y0, x1, y1 ); - - // note : need to draw outline since the filled part isn't really a circle - // gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); // false for outline, true for inside - //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0) - #define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ - if (win && pen) \ - gdk_draw_arc( win, pen, false, (x0)-(w), (y0)-(h), (w)*2, (h)*2, 0, 360*64 ); \ - else \ - dc->DrawEllipse(x0, y0, w, h); +#define INITIALIZE_FAST_GRAPHICS \ + double dc_scale_x = 1, dc_scale_y = 1; \ + dc->GetUserScale(&dc_scale_x, &dc_scale_y); \ + wxPoint dc_origin = dc->GetDeviceOrigin(); \ + wxWindowDC *winDC = wxDynamicCast(dc, wxWindowDC); \ + GdkWindow *window = NULL; \ + GdkGC *pen = NULL; \ + if (winDC && (dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0, 0))) { \ + window = winDC->m_window; \ + pen = winDC->m_penGC; \ + } + +// inline void wxPLOT_DRAW_LINE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0, int x1, int +// y1) +#define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ + if (win && pen) \ + gdk_draw_line(win, pen, x0, y0, x1, y1); \ + else \ + dc->DrawLine(x0, y0, x1, y1); + +// note : need to draw outline since the filled part isn't really a circle +// gdk_draw_arc( win, pen, false, x0-2, y0-2, 4, 4, 0, 360*64 ); // false for outline, true +// for inside +// inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, GdkWindow *win, GdkGC *pen, int x0, int y0) +#define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ + if (win && pen) \ + gdk_draw_arc(win, pen, false, (x0) - (w), (y0) - (h), (w) * 2, (h) * 2, 0, 360 * 64); \ + else \ + dc->DrawEllipse(x0, y0, w, h); #elif defined(__WXMSW__) && wxPLOT_FAST_GRAPHICS - #define INITIALIZE_FAST_GRAPHICS \ - double dc_scale_x = 1, dc_scale_y = 1; \ - dc->GetUserScale( &dc_scale_x, &dc_scale_y ); \ - wxPoint dc_origin = dc->GetDeviceOrigin(); \ - HDC window = 0; \ - if ((dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0,0))) \ - window = (HDC)dc->GetHDC(); \ - int pen = 0; pen = 0; // no unused var warning - - //inline void wxPLOT_DRAW_LINE(wxDC *dc, HDC win, int pen, int x0, int y0, int x1, int y1) - #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ - if (win) \ - { \ - (void)MoveToEx(win, x0, y0, NULL); \ - (void)LineTo(win, x1, y1); \ - } \ - else \ - dc->DrawLine( x0, y0, x1, y1 ); - - //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, HDC win, int pen, int x0, int y0) - #define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ - if (win) \ - (void)Ellipse(win, (x0)-(w), (y0)-(w), (x0)+(w)*2, (y0)+(h)*2); \ - else \ - dc->DrawEllipse(x0, y0, w, h); +#define INITIALIZE_FAST_GRAPHICS \ + double dc_scale_x = 1, dc_scale_y = 1; \ + dc->GetUserScale(&dc_scale_x, &dc_scale_y); \ + wxPoint dc_origin = dc->GetDeviceOrigin(); \ + HDC window = 0; \ + if ((dc_scale_x == 1.0) && (dc_scale_y == 1.0) && (dc_origin == wxPoint(0, 0))) \ + window = (HDC)dc->GetHDC(); \ + int pen = 0; \ + pen = 0; // no unused var warning + +// inline void wxPLOT_DRAW_LINE(wxDC *dc, HDC win, int pen, int x0, int y0, int x1, int y1) +#define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ + if (win) { \ + (void)MoveToEx(win, x0, y0, NULL); \ + (void)LineTo(win, x1, y1); \ + } \ + else \ + dc->DrawLine(x0, y0, x1, y1); + +// inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, HDC win, int pen, int x0, int y0) +#define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ + if (win) \ + (void)Ellipse(win, (x0) - (w), (y0) - (w), (x0) + (w) * 2, (y0) + (h) * 2); \ + else \ + dc->DrawEllipse(x0, y0, w, h); #else // !wxPLOT_FAST_GRAPHICS or not gtk/msw - #define INITIALIZE_FAST_GRAPHICS \ - int window = 0; window = 0; \ - int pen = 0; pen = 0; +#define INITIALIZE_FAST_GRAPHICS \ + int window = 0; \ + window = 0; \ + int pen = 0; \ + pen = 0; - //inline void wxPLOT_DRAW_LINE(wxDC *dc, int win, int pen, int x0, int y0, int x1, int y1) - #define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) \ - dc->DrawLine( x0, y0, x1, y1 ); +// inline void wxPLOT_DRAW_LINE(wxDC *dc, int win, int pen, int x0, int y0, int x1, int y1) +#define wxPLOT_DRAW_LINE(dc, win, pen, x0, y0, x1, y1) dc->DrawLine(x0, y0, x1, y1); - //inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, int win, int pen, int x0, int y0) - #define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) \ - dc->DrawEllipse(x0, y0, w, h); +// inline void wxPLOT_DRAW_CIRCLE(wxDC *dc, int win, int pen, int x0, int y0) +#define wxPLOT_DRAW_ELLIPSE(dc, win, pen, x0, y0, w, h) dc->DrawEllipse(x0, y0, w, h); #endif // wxPLOT_FAST_GRAPHICS - // differs from wxRect2DDouble::Intersects by allowing for 0 width or height inline bool wxPlotRect2DDoubleIntersects(const wxRect2DDouble &a, const wxRect2DDouble &b) { - return (wxMax(a.m_x, b.m_x) <= wxMin(a.GetRight(), b.GetRight())) && - (wxMax(a.m_y, b.m_y) <= wxMin(a.GetBottom(), b.GetBottom())); + return (wxMax(a.m_x, b.m_x) <= wxMin(a.GetRight(), b.GetRight())) && + (wxMax(a.m_y, b.m_y) <= wxMin(a.GetBottom(), b.GetBottom())); } // same as wxPlotRect2DDouble::Contains, but doesn't convert to wxPoint2DDouble inline bool wxPlotRect2DDoubleContains(double x, double y, const wxRect2DDouble &rect) { - return ((x>=rect.m_x) && (y>=rect.m_y) && (x<=rect.GetRight()) && (y<=rect.GetBottom())); + return ((x >= rect.m_x) && (y >= rect.m_y) && (x <= rect.GetRight()) && (y <= rect.GetBottom())); } // differs from wxRect2DDouble::GetOutCode by swaping top and bottom for plot origin -//inline wxOutCode wxPlotRect2DDoubleOutCode( double x, double y, const wxRect2DDouble &rect ) +// inline wxOutCode wxPlotRect2DDoubleOutCode( double x, double y, const wxRect2DDouble &rect ) //{ // return wxOutCode((x < rect.m_x ? wxOutLeft : // (x > rect.GetRight() ? wxOutRight : wxInside )) + // (y < rect.m_y ? wxOutTop : // (y > rect.GetBottom() ? wxOutBottom : wxInside )) ); //} -#define wxPlotRect2DDoubleOutCode( x, y, rect ) \ - wxOutCode(((x) < rect.m_x ? wxOutLeft : \ - ((x) > rect.GetRight() ? wxOutRight : wxInside )) + \ - ((y) < rect.m_y ? wxOutTop : \ - ((y) > rect.GetBottom() ? wxOutBottom : wxInside )) ) - +#define wxPlotRect2DDoubleOutCode(x, y, rect) \ + wxOutCode(((x) < rect.m_x ? wxOutLeft : ((x) > rect.GetRight() ? wxOutRight : wxInside)) + \ + ((y) < rect.m_y ? wxOutTop : ((y) > rect.GetBottom() ? wxOutBottom : wxInside))) // modified Cohen-Sutherland Algorithm for line clipping in at most two passes // the the original endless loop is too unstable @@ -181,124 +180,143 @@ inline bool wxPlotRect2DDoubleContains(double x, double y, const wxRect2DDouble // The line connecting (x0,y0)-(x1,y1) is clipped to rect and which // points were clipped is returned. -enum ClipLine_Type -{ - ClippedNeither = 0x0000, - ClippedFirstX = 0x0001, - ClippedFirstY = 0x0002, - ClippedFirst = ClippedFirstX | ClippedFirstY, - ClippedSecondX = 0x0010, - ClippedSecondY = 0x0020, - ClippedSecond = ClippedSecondX | ClippedSecondY, - ClippedBoth = ClippedFirst | ClippedSecond, - ClippedOut = 0x0100 // no intersection, so can't clip +enum ClipLine_Type { + ClippedNeither = 0x0000, + ClippedFirstX = 0x0001, + ClippedFirstY = 0x0002, + ClippedFirst = ClippedFirstX | ClippedFirstY, + ClippedSecondX = 0x0010, + ClippedSecondY = 0x0020, + ClippedSecond = ClippedSecondX | ClippedSecondY, + ClippedBoth = ClippedFirst | ClippedSecond, + ClippedOut = 0x0100 // no intersection, so can't clip }; -int ClipLineToRect( double &x0, double &y0, - double &x1, double &y1, - const wxRect2DDouble &rect ) +int ClipLineToRect(double &x0, double &y0, double &x1, double &y1, const wxRect2DDouble &rect) { - if (!wxFinite(x0) || !wxFinite(y0) || - !wxFinite(x1) || !wxFinite(y1)) return ClippedOut; - - wxOutCode out0 = wxPlotRect2DDoubleOutCode( x0, y0, rect ); - wxOutCode out1 = wxPlotRect2DDoubleOutCode( x1, y1, rect ); - - if ((out0 & out1) != wxInside) return ClippedOut; // both outside on same side - if ((out0 | out1) == wxInside) return ClippedNeither; // both inside - - int ret = ClippedNeither; - - if (x0 == x1) // vertical line - { - if (out0 & wxOutTop) {y0 = rect.GetTop(); ret |= ClippedFirstY;} - else if (out0 & wxOutBottom) {y0 = rect.GetBottom(); ret |= ClippedFirstY;} - if (out1 & wxOutTop) {y1 = rect.GetTop(); ret |= ClippedSecondY;} - else if (out1 & wxOutBottom) {y1 = rect.GetBottom(); ret |= ClippedSecondY;} - return ret; + if (!wxFinite(x0) || !wxFinite(y0) || !wxFinite(x1) || !wxFinite(y1)) { + return ClippedOut; + } + + wxOutCode out0 = wxPlotRect2DDoubleOutCode(x0, y0, rect); + wxOutCode out1 = wxPlotRect2DDoubleOutCode(x1, y1, rect); + + if ((out0 & out1) != wxInside) { + return ClippedOut; // both outside on same side + } + if ((out0 | out1) == wxInside) { + return ClippedNeither; // both inside + } + + int ret = ClippedNeither; + + if (x0 == x1) // vertical line + { + if (out0 & wxOutTop) { + y0 = rect.GetTop(); + ret |= ClippedFirstY; } - if (y0 == y1) // horiz line - { - if (out0 & wxOutLeft) {x0 = rect.GetLeft(); ret |= ClippedFirstX;} - else if (out0 & wxOutRight) {x0 = rect.GetRight(); ret |= ClippedFirstX;} - if (out1 & wxOutLeft) {x1 = rect.GetLeft(); ret |= ClippedSecondX;} - else if (out1 & wxOutRight) {x1 = rect.GetRight(); ret |= ClippedSecondX;} - return ret; + else if (out0 & wxOutBottom) { + y0 = rect.GetBottom(); + ret |= ClippedFirstY; } - - double x = x0, y = y0; - wxOutCode out = out0; - int points_out = 2; - bool out0_outside = true; - if (out0 == wxInside) - { - out0_outside = false; - points_out = 1; - out = out1; + if (out1 & wxOutTop) { + y1 = rect.GetTop(); + ret |= ClippedSecondY; + } + else if (out1 & wxOutBottom) { + y1 = rect.GetBottom(); + ret |= ClippedSecondY; + } + return ret; + } + if (y0 == y1) // horiz line + { + if (out0 & wxOutLeft) { + x0 = rect.GetLeft(); + ret |= ClippedFirstX; + } + else if (out0 & wxOutRight) { + x0 = rect.GetRight(); + ret |= ClippedFirstX; + } + if (out1 & wxOutLeft) { + x1 = rect.GetLeft(); + ret |= ClippedSecondX; + } + else if (out1 & wxOutRight) { + x1 = rect.GetRight(); + ret |= ClippedSecondX; + } + return ret; + } + + double x = x0, y = y0; + wxOutCode out = out0; + int points_out = 2; + bool out0_outside = true; + if (out0 == wxInside) { + out0_outside = false; + points_out = 1; + out = out1; + } + else if (out1 == wxInside) { + points_out = 1; + } + + for (int i = 0; i < points_out; i++) { + if (out & wxOutTop) { + y = rect.GetTop(); + x = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + out = wxPlotRect2DDoubleOutCode(x, y, rect); + } + else if (out & wxOutBottom) { + y = rect.GetBottom(); + x = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + out = wxPlotRect2DDoubleOutCode(x, y, rect); + } + // check left and right + if (out & wxOutRight) { + x = rect.GetRight(); + y = y0 + (y1 - y0) * (x - x0) / (x1 - x0); + out = wxPlotRect2DDoubleOutCode(x, y, rect); + } + else if (out & wxOutLeft) { + x = rect.GetLeft(); + y = y0 + (y1 - y0) * (x - x0) / (x1 - x0); + out = wxPlotRect2DDoubleOutCode(x, y, rect); + } + // check top and bottom again + if (out & wxOutTop) { + y = rect.GetTop(); + x = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + out = wxPlotRect2DDoubleOutCode(x, y, rect); + } + else if (out & wxOutBottom) { + y = rect.GetBottom(); + x = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + out = wxPlotRect2DDoubleOutCode(x, y, rect); } - else if (out1 == wxInside) - points_out = 1; - - for (int i=0; ix1 = x1_; stack_top->y1 = y1_; \ - stack_top->x2 = x2_; stack_top->y2 = y2_; \ - stack_top->x3 = x3_; stack_top->y3 = y3_; \ - stack_top->x4 = x4_; stack_top->y4 = y4_; \ - stack_top++; \ - m_stack_count++; - -#define SPLINE_POP(x1_, y1_, x2_, y2_, x3_, y3_, x4_, y4_) \ - stack_top--; \ - m_stack_count--; \ - x1_ = stack_top->x1; y1_ = stack_top->y1; \ - x2_ = stack_top->x2; y2_ = stack_top->y2; \ - x3_ = stack_top->x3; y3_ = stack_top->y3; \ - x4_ = stack_top->x4; y4_ = stack_top->y4; - -class SplineDrawer -{ +#define THRESHOLD 4 // number of pixels between spline points + +#define SPLINE_PUSH(x1_, y1_, x2_, y2_, x3_, y3_, x4_, y4_) \ + stack_top->x1 = x1_; \ + stack_top->y1 = y1_; \ + stack_top->x2 = x2_; \ + stack_top->y2 = y2_; \ + stack_top->x3 = x3_; \ + stack_top->y3 = y3_; \ + stack_top->x4 = x4_; \ + stack_top->y4 = y4_; \ + stack_top++; \ + m_stack_count++; + +#define SPLINE_POP(x1_, y1_, x2_, y2_, x3_, y3_, x4_, y4_) \ + stack_top--; \ + m_stack_count--; \ + x1_ = stack_top->x1; \ + y1_ = stack_top->y1; \ + x2_ = stack_top->x2; \ + y2_ = stack_top->y2; \ + x3_ = stack_top->x3; \ + y3_ = stack_top->y3; \ + x4_ = stack_top->x4; \ + y4_ = stack_top->y4; + +class SplineDrawer { public: - SplineDrawer() : m_dc(NULL) { } - // the wxRect2DDouble rect is the allowed dc area in pixel coords - // wxRangeDoubleSelection is the ranges to use selPen, also in pixel coords - // x1_, y1_, x2_, y2_ are the first 2 points to draw - void Create(wxDC *dc, const wxPen &curPen, const wxPen &selPen, - const wxRect2DDouble &rect, wxRangeDoubleSelection *rangeSel, - double x1_, double y1_, double x2_, double y2_) - { - m_dc = dc; - wxCHECK_RET( dc, wxT("invalid window dc") ); + SplineDrawer() : m_dc(NULL) {} + // the wxRect2DDouble rect is the allowed dc area in pixel coords + // wxRangeDoubleSelection is the ranges to use selPen, also in pixel coords + // x1_, y1_, x2_, y2_ are the first 2 points to draw + void Create(wxDC *dc, const wxPen &curPen, const wxPen &selPen, const wxRect2DDouble &rect, + wxRangeDoubleSelection *rangeSel, double x1_, double y1_, double x2_, double y2_) + { + m_dc = dc; + wxCHECK_RET(dc, wxT("invalid window dc")); + + m_selPen = selPen; + m_curPen = curPen; + m_rangeSel = rangeSel; + + m_rect = rect; - m_selPen = selPen; - m_curPen = curPen; - m_rangeSel = rangeSel; + m_stack_count = 0; - m_rect = rect; + m_x1 = x1_; + m_y1 = y1_; + m_x2 = x2_; + m_y2 = y2_; + m_cx1 = (m_x1 + m_x2) / 2.0; + m_cy1 = (m_y1 + m_y2) / 2.0; + m_cx2 = (m_cx1 + m_x2) / 2.0; + m_cy2 = (m_cy1 + m_y2) / 2.0; - m_stack_count = 0; + m_last_x = m_x1; + m_last_y = m_y1; + } - m_x1 = x1_; - m_y1 = y1_; - m_x2 = x2_; - m_y2 = y2_; - m_cx1 = (m_x1 + m_x2) / 2.0; - m_cy1 = (m_y1 + m_y2) / 2.0; - m_cx2 = (m_cx1 + m_x2) / 2.0; - m_cy2 = (m_cy1 + m_y2) / 2.0; + // actually do the drawing here + void DrawSpline(double x, double y); - m_last_x = m_x1; - m_last_y = m_y1; - } - - // actually do the drawing here - void DrawSpline(double x, double y); - - // After the last point call this to finish the drawing - void EndSpline() - { - wxCHECK_RET( m_dc, wxT("invalid window dc") ); - if (ClipLineToRect(m_cx1, m_cy1, m_x2, m_y2, m_rect) != ClippedOut) - m_dc->DrawLine((int)m_cx1, (int)m_cy1, (int)m_x2, (int)m_y2); + // After the last point call this to finish the drawing + void EndSpline() + { + wxCHECK_RET(m_dc, wxT("invalid window dc")); + if (ClipLineToRect(m_cx1, m_cy1, m_x2, m_y2, m_rect) != ClippedOut) { + m_dc->DrawLine((int)m_cx1, (int)m_cy1, (int)m_x2, (int)m_y2); } + } private: + typedef struct SplineStack { + double x1, y1, x2, y2, x3, y3, x4, y4; + } SplineStack; - typedef struct SplineStack - { - double x1, y1, x2, y2, x3, y3, x4, y4; - } SplineStack; - - wxDC *m_dc; - wxRect2DDouble m_rect; + wxDC *m_dc; + wxRect2DDouble m_rect; - SplineStack m_splineStack[SPLINE_STACK_DEPTH]; - int m_stack_count; + SplineStack m_splineStack[SPLINE_STACK_DEPTH]; + int m_stack_count; - double m_cx1, m_cy1, m_cx2, m_cy2, m_cx3, m_cy3, m_cx4, m_cy4; - double m_x1, m_y1, m_x2, m_y2; - double m_last_x, m_last_y; + double m_cx1, m_cy1, m_cx2, m_cy2, m_cx3, m_cy3, m_cx4, m_cy4; + double m_x1, m_y1, m_x2, m_y2; + double m_last_x, m_last_y; - wxPen m_selPen, m_curPen; - wxRangeDoubleSelection *m_rangeSel; + wxPen m_selPen, m_curPen; + wxRangeDoubleSelection *m_rangeSel; }; -void SplineDrawer::DrawSpline( double x, double y ) +void SplineDrawer::DrawSpline(double x, double y) { - wxCHECK_RET( m_dc, wxT("invalid window dc") ); - wxPen oldPen = m_dc->GetPen(); - - bool is_selected = (oldPen == m_selPen); - - m_x1 = m_x2; - m_y1 = m_y2; - m_x2 = x; - m_y2 = y; - m_cx4 = (m_x1 + m_x2) / 2.0; - m_cy4 = (m_y1 + m_y2) / 2.0; - m_cx3 = (m_x1 + m_cx4) / 2.0; - m_cy3 = (m_y1 + m_cy4) / 2.0; - - double xmid, ymid; - double xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4; + wxCHECK_RET(m_dc, wxT("invalid window dc")); + wxPen oldPen = m_dc->GetPen(); + + bool is_selected = (oldPen == m_selPen); + + m_x1 = m_x2; + m_y1 = m_y2; + m_x2 = x; + m_y2 = y; + m_cx4 = (m_x1 + m_x2) / 2.0; + m_cy4 = (m_y1 + m_y2) / 2.0; + m_cx3 = (m_x1 + m_cx4) / 2.0; + m_cy3 = (m_y1 + m_cy4) / 2.0; + + double xmid, ymid; + double xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4; + + SplineStack *stack_top = m_splineStack; + m_stack_count = 0; + + SPLINE_PUSH(m_cx1, m_cy1, m_cx2, m_cy2, m_cx3, m_cy3, m_cx4, m_cy4); + + while (m_stack_count > 0) { + SPLINE_POP(xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4); + + xmid = (xx2 + xx3) / 2.0; + ymid = (yy2 + yy3) / 2.0; + if ((fabs(xx1 - xmid) < THRESHOLD) && (fabs(yy1 - ymid) < THRESHOLD) && + (fabs(xmid - xx4) < THRESHOLD) && (fabs(ymid - yy4) < THRESHOLD)) { + // FIXME - is this really necessary, better safe than sorry? + double t1_last_x = m_last_x; + double t1_last_y = m_last_y; + double t1_xx1 = xx1; + double t1_yy1 = yy1; + if (ClipLineToRect(t1_last_x, t1_last_y, t1_xx1, t1_yy1, m_rect) != ClippedOut) { + if (m_rangeSel && (m_rangeSel->Contains((m_last_x + xx1) / 2) != is_selected)) { + is_selected = is_selected ? false : true; + if (is_selected) { + m_dc->SetPen(m_selPen); + } + else { + m_dc->SetPen(m_curPen); + } + } - SplineStack *stack_top = m_splineStack; - m_stack_count = 0; + m_dc->DrawLine((int)t1_last_x, (int)t1_last_y, (int)t1_xx1, (int)t1_yy1); + } + + double t2_xx1 = xx1; + double t2_yy1 = yy1; + double t2_xmid = xmid; + double t2_ymid = ymid; + if (ClipLineToRect(t2_xx1, t2_yy1, t2_xmid, t2_ymid, m_rect) != ClippedOut) { + if (m_rangeSel && (m_rangeSel->Contains((xx1 + xmid) / 2) != is_selected)) { + is_selected = is_selected ? false : true; + if (is_selected) { + m_dc->SetPen(m_selPen); + } + else { + m_dc->SetPen(m_curPen); + } + } - SPLINE_PUSH(m_cx1, m_cy1, m_cx2, m_cy2, m_cx3, m_cy3, m_cx4, m_cy4); + m_dc->DrawLine((int)t2_xx1, (int)t2_yy1, (int)t2_xmid, (int)t2_ymid); + } - while (m_stack_count > 0) - { - SPLINE_POP(xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4); - - xmid = (xx2 + xx3)/2.0; - ymid = (yy2 + yy3)/2.0; - if ((fabs(xx1 - xmid) < THRESHOLD) && (fabs(yy1 - ymid) < THRESHOLD) && - (fabs(xmid - xx4) < THRESHOLD) && (fabs(ymid - yy4) < THRESHOLD)) - { - // FIXME - is this really necessary, better safe than sorry? - double t1_last_x = m_last_x; - double t1_last_y = m_last_y; - double t1_xx1 = xx1; - double t1_yy1 = yy1; - if (ClipLineToRect(t1_last_x, t1_last_y, t1_xx1, t1_yy1, m_rect) != ClippedOut) - { - if (m_rangeSel && (m_rangeSel->Contains((m_last_x + xx1)/2) != is_selected)) - { - is_selected = is_selected ? false : true; - if (is_selected) - m_dc->SetPen(m_selPen); - else - m_dc->SetPen(m_curPen); - } - - m_dc->DrawLine((int)t1_last_x, (int)t1_last_y, (int)t1_xx1, (int)t1_yy1); - } - - double t2_xx1 = xx1; - double t2_yy1 = yy1; - double t2_xmid = xmid; - double t2_ymid = ymid; - if (ClipLineToRect(t2_xx1, t2_yy1, t2_xmid, t2_ymid, m_rect) != ClippedOut) - { - if (m_rangeSel && (m_rangeSel->Contains((xx1+xmid)/2) != is_selected)) - { - is_selected = is_selected ? false : true; - if (is_selected) - m_dc->SetPen(m_selPen); - else - m_dc->SetPen(m_curPen); - } - - m_dc->DrawLine((int)t2_xx1, (int)t2_yy1, (int)t2_xmid, (int)t2_ymid); - } - - m_last_x = xmid; - m_last_y = ymid; - } - else - { - wxCHECK_RET(m_stack_count < SPLINE_STACK_DEPTH - 2, wxT("Spline stack overflow")); - SPLINE_PUSH(xmid, ymid, (xmid + xx3)/2.0, (ymid + yy3)/2.0, - (xx3 + xx4)/2.0, (yy3 + yy4)/2.0, xx4, yy4); - SPLINE_PUSH(xx1, yy1, (xx1 + xx2)/2.0, (yy1 + yy2)/2.0, - (xx2 + xmid)/2.0, (yy2 + ymid)/2.0, xmid, ymid); - } + m_last_x = xmid; + m_last_y = ymid; } + else { + wxCHECK_RET(m_stack_count < SPLINE_STACK_DEPTH - 2, wxT("Spline stack overflow")); + SPLINE_PUSH(xmid, ymid, (xmid + xx3) / 2.0, (ymid + yy3) / 2.0, (xx3 + xx4) / 2.0, + (yy3 + yy4) / 2.0, xx4, yy4); + SPLINE_PUSH(xx1, yy1, (xx1 + xx2) / 2.0, (yy1 + yy2) / 2.0, (xx2 + xmid) / 2.0, + (yy2 + ymid) / 2.0, xmid, ymid); + } + } - m_cx1 = m_cx4; - m_cy1 = m_cy4; - m_cx2 = (m_cx1 + m_x2) / 2.0; - m_cy2 = (m_cy1 + m_y2) / 2.0; + m_cx1 = m_cx4; + m_cy1 = m_cy4; + m_cx2 = (m_cx1 + m_x2) / 2.0; + m_cy2 = (m_cy1 + m_y2) / 2.0; - m_dc->SetPen(oldPen); + m_dc->SetPen(oldPen); } //*************************************************************************** - //----------------------------------------------------------------------------- // wxPlotDrawerAxisBase //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerBase, wxObject) -wxPlotDrawerAxisBase::wxPlotDrawerAxisBase(wxPlotCtrl* owner) - :wxPlotDrawerBase(owner) +wxPlotDrawerAxisBase::wxPlotDrawerAxisBase(wxPlotCtrl *owner) : wxPlotDrawerBase(owner) { - m_tickFont = *wxNORMAL_FONT; - m_labelFont = *wxSWISS_FONT; - m_tickColour = wxGenericColour(0,0,0); - m_labelColour = wxGenericColour(0,0,0); + m_tickFont = *wxNORMAL_FONT; + m_labelFont = *wxSWISS_FONT; + m_tickColour = wxGenericColour(0, 0, 0); + m_labelColour = wxGenericColour(0, 0, 0); - m_tickPen = wxGenericPen(m_tickColour, wxSOLID); - m_backgroundBrush = wxGenericBrush(wxGenericColour(255,255,255), wxBRUSHSTYLE_SOLID); + m_tickPen = wxGenericPen(m_tickColour, wxSOLID); + m_backgroundBrush = wxGenericBrush(wxGenericColour(255, 255, 255), wxBRUSHSTYLE_SOLID); } //----------------------------------------------------------------------------- @@ -509,9 +527,7 @@ wxPlotDrawerAxisBase::wxPlotDrawerAxisBase(wxPlotCtrl* owner) //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerArea, wxPlotDrawerBase) -void wxPlotDrawerArea::Draw(wxDC *dc, bool refresh) -{ -} +void wxPlotDrawerArea::Draw(wxDC *dc, bool refresh) {} //----------------------------------------------------------------------------- // wxPlotDrawerAxisBase @@ -525,54 +541,53 @@ IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerXAxis, wxPlotDrawerAxisBase) void wxPlotDrawerXAxis::Draw(wxDC *dc, bool refresh) { - wxCHECK_RET(dc, wxT("Invalid dc")); - - wxRect dcRect(GetDCRect()); - - // Draw background - if (refresh) - { - dc->SetBrush(m_backgroundBrush.GetBrush()); - dc->SetPen(*wxTRANSPARENT_PEN); - dc->DrawRectangle(dcRect); - } - - wxFont tickFont = m_tickFont; - if (m_font_scale != 1) - tickFont.SetPointSize( wxMax(2, RINT(tickFont.GetPointSize() * m_font_scale)) ); - - wxPoint dcOrigin(dc->GetDeviceOrigin()); - dc->SetDeviceOrigin(dcRect.x, dcRect.y); - dc->SetTextForeground( m_tickColour.GetColour() ); - dc->SetFont( tickFont ); - - wxString label; - - // center the text in the window - int x, y; - dc->GetTextExtent(wxT("5"), &x, &y); - int y_pos = (GetDCRect().height - y)/2 + 2; // FIXME I want to center this -// double current = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; - int i, count = m_tickPositions.GetCount(); - for (i=0; iDrawText(m_tickLabels[i], m_tickPositions[i], y_pos); - -// if (!IsFinite(current, wxT("axis label is not finite"))) -// break; -// label.Printf( m_xAxisTickFormat.c_str(), current ); -// dc->DrawText(label, m_xAxisTicks[i], y_pos); -// current += m_xAxisTick_step; - } + wxCHECK_RET(dc, wxT("Invalid dc")); + + wxRect dcRect(GetDCRect()); + + // Draw background + if (refresh) { + dc->SetBrush(m_backgroundBrush.GetBrush()); + dc->SetPen(*wxTRANSPARENT_PEN); + dc->DrawRectangle(dcRect); + } + + wxFont tickFont = m_tickFont; + if (m_font_scale != 1) { + tickFont.SetPointSize(wxMax(2, RINT(tickFont.GetPointSize() * m_font_scale))); + } + + wxPoint dcOrigin(dc->GetDeviceOrigin()); + dc->SetDeviceOrigin(dcRect.x, dcRect.y); + dc->SetTextForeground(m_tickColour.GetColour()); + dc->SetFont(tickFont); + + wxString label; + + // center the text in the window + int x, y; + dc->GetTextExtent(wxT("5"), &x, &y); + int y_pos = (GetDCRect().height - y) / 2 + 2; // FIXME I want to center this + // double current = ceil(m_viewRect.GetLeft() / m_xAxisTick_step) * m_xAxisTick_step; + int i, count = m_tickPositions.GetCount(); + for (i = 0; i < count; i++) { + dc->DrawText(m_tickLabels[i], m_tickPositions[i], y_pos); + + // if (!IsFinite(current, wxT("axis label is not finite"))) + // break; + // label.Printf( m_xAxisTickFormat.c_str(), current ); + // dc->DrawText(label, m_xAxisTicks[i], y_pos); + // current += m_xAxisTick_step; + } #ifdef DRAW_BORDERS - // Test code for sizing to show the extent of the axes - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - dc->SetPen( wxPen(GetBorderColour(), 1, wxSOLID) ); - dc->DrawRectangle(wxRect(wxPoint(0,0), clientSize)); + // Test code for sizing to show the extent of the axes + dc->SetBrush(*wxTRANSPARENT_BRUSH); + dc->SetPen(wxPen(GetBorderColour(), 1, wxSOLID)); + dc->DrawRectangle(wxRect(wxPoint(0, 0), clientSize)); #endif // DRAW_BORDERS - dc->SetDeviceOrigin(dcOrigin.x, dcOrigin.y); + dc->SetDeviceOrigin(dcOrigin.x, dcOrigin.y); } //----------------------------------------------------------------------------- @@ -582,50 +597,49 @@ IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerYAxis, wxPlotDrawerAxisBase) void wxPlotDrawerYAxis::Draw(wxDC *dc, bool refresh) { - wxCHECK_RET(dc, wxT("Invalid dc")); + wxCHECK_RET(dc, wxT("Invalid dc")); - wxRect dcRect(GetDCRect()); + wxRect dcRect(GetDCRect()); - // Draw background - if (refresh) - { - dc->SetBrush(m_backgroundBrush.GetBrush()); - dc->SetPen(*wxTRANSPARENT_PEN); - dc->DrawRectangle(dcRect); - } + // Draw background + if (refresh) { + dc->SetBrush(m_backgroundBrush.GetBrush()); + dc->SetPen(*wxTRANSPARENT_PEN); + dc->DrawRectangle(dcRect); + } - wxFont tickFont = m_tickFont; - if (m_font_scale != 1) - tickFont.SetPointSize( wxMax(2, RINT(tickFont.GetPointSize() * m_font_scale)) ); + wxFont tickFont = m_tickFont; + if (m_font_scale != 1) { + tickFont.SetPointSize(wxMax(2, RINT(tickFont.GetPointSize() * m_font_scale))); + } - wxPoint dcOrigin(dc->GetDeviceOrigin()); - dc->SetDeviceOrigin(dcRect.x, dcRect.y); - dc->SetTextForeground( m_tickColour.GetColour() ); - dc->SetFont( tickFont ); + wxPoint dcOrigin(dc->GetDeviceOrigin()); + dc->SetDeviceOrigin(dcRect.x, dcRect.y); + dc->SetTextForeground(m_tickColour.GetColour()); + dc->SetFont(tickFont); - wxString label; + wxString label; -// double current = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; - int i, count = m_tickLabels.GetCount(); - for (i=0; iDrawText( m_tickLabels[i], 2, m_tickPositions[i] ); + // double current = ceil(m_viewRect.GetTop() / m_yAxisTick_step) * m_yAxisTick_step; + int i, count = m_tickLabels.GetCount(); + for (i = 0; i < count; i++) { + dc->DrawText(m_tickLabels[i], 2, m_tickPositions[i]); -// if (!IsFinite(current, wxT("axis label is not finite"))) -// break; -// label.Printf( m_yAxisTickFormat.c_str(), current); -// dc->DrawText( label, 2, m_yAxisTicks[i] ); -// current += m_yAxisTick_step; - } + // if (!IsFinite(current, wxT("axis label is not finite"))) + // break; + // label.Printf( m_yAxisTickFormat.c_str(), current); + // dc->DrawText( label, 2, m_yAxisTicks[i] ); + // current += m_yAxisTick_step; + } #ifdef DRAW_BORDERS - // Test code for sizing to show the extent of the axes - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - dc->SetPen( wxPen(GetBorderColour(), 1, wxSOLID) ); - dc->DrawRectangle(wxRect(wxPoint(0,0), clientSize)); + // Test code for sizing to show the extent of the axes + dc->SetBrush(*wxTRANSPARENT_BRUSH); + dc->SetPen(wxPen(GetBorderColour(), 1, wxSOLID)); + dc->DrawRectangle(wxRect(wxPoint(0, 0), clientSize)); #endif // DRAW_BORDERS - dc->SetDeviceOrigin(dcOrigin.x, dcOrigin.y); + dc->SetDeviceOrigin(dcOrigin.x, dcOrigin.y); } //----------------------------------------------------------------------------- @@ -633,100 +647,103 @@ void wxPlotDrawerYAxis::Draw(wxDC *dc, bool refresh) //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerKey, wxPlotDrawerBase) -wxPlotDrawerKey::wxPlotDrawerKey(wxPlotCtrl* owner) - :wxPlotDrawerBase(owner) +wxPlotDrawerKey::wxPlotDrawerKey(wxPlotCtrl *owner) : wxPlotDrawerBase(owner) { - m_font = *wxNORMAL_FONT; - m_fontColour = wxGenericColour(0, 0, 0); - m_keyPosition = wxPoint(100, 100); - m_border = 5; - m_key_inside = true; - m_key_line_width = 20; - m_key_line_margin = 5; + m_font = *wxNORMAL_FONT; + m_fontColour = wxGenericColour(0, 0, 0); + m_keyPosition = wxPoint(100, 100); + m_border = 5; + m_key_inside = true; + m_key_line_width = 20; + m_key_line_margin = 5; } -void wxPlotDrawerKey::Draw(wxDC *dc, const wxString& keyString_) +void wxPlotDrawerKey::Draw(wxDC *dc, const wxString &keyString_) { - wxCHECK_RET(dc && m_owner, wxT("Invalid dc")); + wxCHECK_RET(dc && m_owner, wxT("Invalid dc")); - if (keyString_.IsEmpty()) - return; + if (keyString_.IsEmpty()) { + return; + } - wxString keyString = keyString_; + wxString keyString = keyString_; -/* - // GTK - kills X if font size is too small - double x_scale = 1, y_scale = 1; - dc->GetUserScale( &x_scale, &y_scale ); + /* + // GTK - kills X if font size is too small + double x_scale = 1, y_scale = 1; + dc->GetUserScale( &x_scale, &y_scale ); - wxFont font = m_owner->GetKeyFont(); - if (0 && x_scale != 1) - { - font.SetPointSize(wxMax(int(font.GetPointSize()/x_scale), 4)); - if (!font.Ok()) - font = GetKeyFont(); - } -*/ + wxFont font = m_owner->GetKeyFont(); + if (0 && x_scale != 1) + { + font.SetPointSize(wxMax(int(font.GetPointSize()/x_scale), 4)); + if (!font.Ok()) + font = GetKeyFont(); + } + */ - wxFont keyFont = m_font; - if (m_font_scale != 1) - keyFont.SetPointSize( wxMax(2, RINT(keyFont.GetPointSize() * m_font_scale)) ); + wxFont keyFont = m_font; + if (m_font_scale != 1) { + keyFont.SetPointSize(wxMax(2, RINT(keyFont.GetPointSize() * m_font_scale))); + } - int key_line_width = RINT(m_key_line_width * m_pen_scale); - int key_line_margin = RINT(m_key_line_margin * m_pen_scale); + int key_line_width = RINT(m_key_line_width * m_pen_scale); + int key_line_margin = RINT(m_key_line_margin * m_pen_scale); - dc->SetFont(keyFont); - dc->SetTextForeground(m_fontColour.GetColour()); + dc->SetFont(keyFont); + dc->SetTextForeground(m_fontColour.GetColour()); - wxRect keyRect; - int heightLine = 0; + wxRect keyRect; + int heightLine = 0; - dc->GetMultiLineTextExtent(keyString, &keyRect.width, &keyRect.height, &heightLine); + dc->GetMultiLineTextExtent(keyString, &keyRect.width, &keyRect.height, &heightLine); - wxRect dcRect(GetDCRect()); - wxSize areaSize = dcRect.GetSize(); + wxRect dcRect(GetDCRect()); + wxSize areaSize = dcRect.GetSize(); - keyRect.x = 30 + int((m_keyPosition.x*.01)*areaSize.x); - keyRect.y = areaSize.y - int((m_keyPosition.y*.01)*areaSize.y); + keyRect.x = 30 + int((m_keyPosition.x * .01) * areaSize.x); + keyRect.y = areaSize.y - int((m_keyPosition.y * .01) * areaSize.y); - if (m_key_inside) - { - keyRect.x = wxMax(30, keyRect.x); - keyRect.x = wxMin(areaSize.x - keyRect.width - m_border, keyRect.GetRight()); - - keyRect.y = wxMax(m_border, keyRect.y); - keyRect.y = wxMin(areaSize.y - keyRect.height - m_border, keyRect.y); - } + if (m_key_inside) { + keyRect.x = wxMax(30, keyRect.x); + keyRect.x = wxMin(areaSize.x - keyRect.width - m_border, keyRect.GetRight()); - int h = keyRect.y; - int i = 0; + keyRect.y = wxMax(m_border, keyRect.y); + keyRect.y = wxMin(areaSize.y - keyRect.height - m_border, keyRect.y); + } - while (!keyString.IsEmpty()) - { - wxString subkey = keyString.BeforeFirst(wxT('\n')).Strip(wxString::both); - keyString = keyString.AfterFirst(wxT('\n')); - if (subkey.IsEmpty()) break; - - if (m_owner && m_owner->GetCurve(i)) - { - wxPen keyPen = m_owner->GetCurve(i)->GetPen(wxPLOTPEN_NORMAL).GetPen(); - if (m_pen_scale != 1) - keyPen.SetWidth(int(keyPen.GetWidth() * m_pen_scale)); - - if(keyPen.GetWidth() < 3) keyPen.SetWidth(3); - dc->SetPen(keyPen); - dc->DrawLine(keyRect.x - (key_line_width + key_line_margin), h + heightLine/2, - keyRect.x - key_line_margin, h + heightLine/2); - } + int h = keyRect.y; + int i = 0; - dc->DrawText(subkey, keyRect.x, h); + while (!keyString.IsEmpty()) { + wxString subkey = keyString.BeforeFirst(wxT('\n')).Strip(wxString::both); + keyString = keyString.AfterFirst(wxT('\n')); + if (subkey.IsEmpty()) { + break; + } - h += heightLine; - i++; + if (m_owner && m_owner->GetCurve(i)) { + wxPen keyPen = m_owner->GetCurve(i)->GetPen(wxPLOTPEN_NORMAL).GetPen(); + if (m_pen_scale != 1) { + keyPen.SetWidth(int(keyPen.GetWidth() * m_pen_scale)); + } + + if (keyPen.GetWidth() < 3) { + keyPen.SetWidth(3); + } + dc->SetPen(keyPen); + dc->DrawLine(keyRect.x - (key_line_width + key_line_margin), h + heightLine / 2, + keyRect.x - key_line_margin, h + heightLine / 2); } - dc->SetPen(wxNullPen); - dc->SetFont(wxNullFont); + dc->DrawText(subkey, keyRect.x, h); + + h += heightLine; + i++; + } + + dc->SetPen(wxNullPen); + dc->SetFont(wxNullFont); } //----------------------------------------------------------------------------- @@ -736,74 +753,73 @@ IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerCurve, wxPlotDrawerBase) void wxPlotDrawerCurve::Draw(wxDC *dc, wxPlotCurve *curve, int curve_index) { - wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve")); - INITIALIZE_FAST_GRAPHICS + wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve")); + INITIALIZE_FAST_GRAPHICS - wxRect dcRect(GetDCRect()); + wxRect dcRect(GetDCRect()); - int i, j0, j1; - double x0, y0, x1, y1, yy0, yy1; - x0 = m_owner->GetPlotCoordFromClientX(0); - y0 = yy0 = curve->GetY(x0); + int i, j0, j1; + double x0, y0, x1, y1, yy0, yy1; + x0 = m_owner->GetPlotCoordFromClientX(0); + y0 = yy0 = curve->GetY(x0); - //wxRect2DDouble viewRect = m_viewRect; - wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect( dcRect ); - //printf("curve rect %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height); fflush(stdout); - //printf("curve subviewrect %lf %lf %lf %lf\n", subViewRect.m_x, subViewRect.m_y, subViewRect.m_width, subViewRect.m_height); fflush(stdout); + // wxRect2DDouble viewRect = m_viewRect; + wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect(dcRect); + // printf("curve rect %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height); fflush(stdout); + // printf("curve subviewrect %lf %lf %lf %lf\n", subViewRect.m_x, subViewRect.m_y, + // subViewRect.m_width, subViewRect.m_height); fflush(stdout); - int right = dcRect.GetRight(); + int right = dcRect.GetRight(); - wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen() - : curve->GetPen(wxPLOTPEN_NORMAL).GetPen(); - wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen(); + wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) + ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen() + : curve->GetPen(wxPLOTPEN_NORMAL).GetPen(); + wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen(); - if (m_pen_scale != 1) - { - currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale)); - selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale)); - } - - dc->SetPen(currentPen); + if (m_pen_scale != 1) { + currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale)); + selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale)); + } - const wxRangeDoubleSelection *ranges = m_owner->GetCurveSelection(curve_index); - bool selected = false; + dc->SetPen(currentPen); - int clipped = ClippedNeither; + const wxRangeDoubleSelection *ranges = m_owner->GetCurveSelection(curve_index); + bool selected = false; - for (i=dcRect.x; iGetPlotCoordFromClientX(i); - y1 = yy1 = curve->GetY(x1); + int clipped = ClippedNeither; - clipped = ClipLineToRect(x0, yy0, x1, yy1, subViewRect); + for (i = dcRect.x; i < right; i++) { + x1 = m_owner->GetPlotCoordFromClientX(i); + y1 = yy1 = curve->GetY(x1); - if (selected != ranges->Contains(x1)) - { - if (selected) - dc->SetPen(currentPen); - else - dc->SetPen(selectedPen); + clipped = ClipLineToRect(x0, yy0, x1, yy1, subViewRect); - selected = !selected; - } + if (selected != ranges->Contains(x1)) { + if (selected) { + dc->SetPen(currentPen); + } + else { + dc->SetPen(selectedPen); + } - if (clipped != ClippedOut) - { - j0 = m_owner->GetClientCoordFromPlotY(yy0); - j1 = m_owner->GetClientCoordFromPlotY(yy1); - wxPLOT_DRAW_LINE(dc, window, pen, i-1, j0, i, j1); + selected = !selected; + } - if (selected && !((clipped & ClippedSecond) != 0)) - { - wxPLOT_DRAW_ELLIPSE(dc, window, pen, i, j1, 2, 2); - } - } + if (clipped != ClippedOut) { + j0 = m_owner->GetClientCoordFromPlotY(yy0); + j1 = m_owner->GetClientCoordFromPlotY(yy1); + wxPLOT_DRAW_LINE(dc, window, pen, i - 1, j0, i, j1); - x0 = x1; - y0 = yy0 = y1; + if (selected && !((clipped & ClippedSecond) != 0)) { + wxPLOT_DRAW_ELLIPSE(dc, window, pen, i, j1, 2, 2); + } } - dc->SetPen(wxNullPen); + x0 = x1; + y0 = yy0 = y1; + } + + dc->SetPen(wxNullPen); } //----------------------------------------------------------------------------- @@ -811,198 +827,191 @@ void wxPlotDrawerCurve::Draw(wxDC *dc, wxPlotCurve *curve, int curve_index) //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerDataCurve, wxPlotDrawerBase) -void wxPlotDrawerDataCurve::Draw(wxDC *dc, wxPlotData* curve, int curve_index) +void wxPlotDrawerDataCurve::Draw(wxDC *dc, wxPlotData *curve, int curve_index) { - wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve")); - INITIALIZE_FAST_GRAPHICS - - wxRect dcRect(GetDCRect()); - - wxRect2DDouble viewRect( GetPlotViewRect() ); //m_viewRect ); - wxRect2DDouble subViewRect( m_owner->GetPlotRectFromClientRect(dcRect) ); - wxRect2DDouble curveRect( curve->GetBoundingRect() ); - if (!wxPlotRect2DDoubleIntersects(curveRect, subViewRect)) return; - -/* // FIXME - drawing symbol bitmaps in MSW is very slow - wxBitmap bitmap; - if (curve == GetActiveCurve()) - bitmap = curve->GetSymbol(wxPLOTPEN_ACTIVE); - else - bitmap = curve->GetSymbol(wxPLOTPEN_NORMAL); - - if (!bitmap.Ok()) - { - if (curve == GetActiveCurve()) - bitmap = wxPlotSymbolCurrent; - else - bitmap = wxPlotSymbolNormal; + wxCHECK_RET(dc && m_owner && curve && curve->Ok(), wxT("invalid curve")); + INITIALIZE_FAST_GRAPHICS + + wxRect dcRect(GetDCRect()); + + wxRect2DDouble viewRect(GetPlotViewRect()); // m_viewRect ); + wxRect2DDouble subViewRect(m_owner->GetPlotRectFromClientRect(dcRect)); + wxRect2DDouble curveRect(curve->GetBoundingRect()); + if (!wxPlotRect2DDoubleIntersects(curveRect, subViewRect)) { + return; + } + + /* // FIXME - drawing symbol bitmaps in MSW is very slow + wxBitmap bitmap; + if (curve == GetActiveCurve()) + bitmap = curve->GetSymbol(wxPLOTPEN_ACTIVE); + else + bitmap = curve->GetSymbol(wxPLOTPEN_NORMAL); + + if (!bitmap.Ok()) + { + if (curve == GetActiveCurve()) + bitmap = wxPlotSymbolCurrent; + else + bitmap = wxPlotSymbolNormal; + } + + int bitmapHalfWidth = bitmap.GetWidth()/2; + int bitmapHalfHeight = bitmap.GetHeight()/2; + */ + + // find the starting and ending indexes into the data curve + int n, n_start, n_end; + bool x_ordered = curve->GetIsXOrdered(); + + if (x_ordered) { + n_start = curve->GetIndexFromX(subViewRect.GetLeft(), wxPlotData::index_floor); + n_end = curve->GetIndexFromX(subViewRect.GetRight(), wxPlotData::index_ceil); + n_end++; // for statement comparison is < + } + else { + n_start = 0; + n_end = curve->GetCount(); + } + + // set the pens to draw with + wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) + ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen() + : curve->GetPen(wxPLOTPEN_NORMAL).GetPen(); + wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen(); + if (m_pen_scale != 1) { + currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale)); + selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale)); + } + + dc->SetPen(currentPen); + + // handle the selected ranges and initialize the starting range + const wxArrayRangeInt &ranges = m_owner->GetDataCurveSelection(curve_index)->GetRangeArray(); + int n_range = 0, range_count = ranges.GetCount(); + int min_sel = -1, max_sel = -1; + for (n_range = 0; n_range < range_count; n_range++) { + const wxRangeInt &range = ranges[n_range]; + if ((range.m_max >= n_start) || (range.m_min >= n_start)) { + min_sel = range.m_min; + max_sel = range.m_max; + if (range.Contains(n_start)) { + dc->SetPen(selectedPen); + } + + break; } + } - int bitmapHalfWidth = bitmap.GetWidth()/2; - int bitmapHalfHeight = bitmap.GetHeight()/2; -*/ + // data variables + const double *x_data = &curve->GetXData()[n_start]; + const double *y_data = &curve->GetYData()[n_start]; - // find the starting and ending indexes into the data curve - int n, n_start, n_end; - bool x_ordered = curve->GetIsXOrdered(); + int i0, j0, i1, j1; // curve coords in pixels + double x0, y0, x1, y1; // original curve coords + double xx0, yy0, xx1, yy1; // clipped curve coords - if (x_ordered) - { - n_start = curve->GetIndexFromX(subViewRect.GetLeft(), wxPlotData::index_floor); - n_end = curve->GetIndexFromX(subViewRect.GetRight(), wxPlotData::index_ceil); - n_end++; // for statement comparison is < - } - else - { - n_start = 0; - n_end = curve->GetCount(); - } - - // set the pens to draw with - wxPen currentPen = (curve_index == m_owner->GetActiveIndex()) ? curve->GetPen(wxPLOTPEN_ACTIVE).GetPen() - : curve->GetPen(wxPLOTPEN_NORMAL).GetPen(); - wxPen selectedPen = curve->GetPen(wxPLOTPEN_SELECTED).GetPen(); - if (m_pen_scale != 1) - { - currentPen.SetWidth(int(currentPen.GetWidth() * m_pen_scale)); - selectedPen.SetWidth(int(selectedPen.GetWidth() * m_pen_scale)); - } - - dc->SetPen(currentPen); - - // handle the selected ranges and initialize the starting range - const wxArrayRangeInt &ranges = m_owner->GetDataCurveSelection(curve_index)->GetRangeArray(); - int n_range = 0, range_count = ranges.GetCount(); - int min_sel = -1, max_sel = -1; - for (n_range=0; n_range= n_start) || (range.m_min >= n_start)) - { - min_sel = range.m_min; - max_sel = range.m_max; - if (range.Contains(n_start)) - dc->SetPen( selectedPen ); - - break; - } - } - - // data variables - const double *x_data = &curve->GetXData()[n_start]; - const double *y_data = &curve->GetYData()[n_start]; + x0 = *x_data; + y0 = *y_data; - int i0, j0, i1, j1; // curve coords in pixels - double x0, y0, x1, y1; // original curve coords - double xx0, yy0, xx1, yy1; // clipped curve coords + int clipped = ClippedNeither; - x0 = *x_data; - y0 = *y_data; + bool draw_lines = m_owner->GetDrawLines(); + bool draw_symbols = m_owner->GetDrawSymbols(); + bool draw_spline = m_owner->GetDrawSpline(); - int clipped = ClippedNeither; + SplineDrawer sd; + wxRangeDoubleSelection dblRangeSel; - bool draw_lines = m_owner->GetDrawLines(); - bool draw_symbols = m_owner->GetDrawSymbols(); - bool draw_spline = m_owner->GetDrawSpline(); + if (draw_spline) { + wxRangeDouble viewRange(viewRect.m_x, viewRect.GetRight()); + wxRangeDouble dcRange(dcRect.x, dcRect.GetRight()); - SplineDrawer sd; - wxRangeDoubleSelection dblRangeSel; + for (int r = n_range; r < range_count; r++) { + wxRangeDouble plotRange(curve->GetXValue(ranges[r].m_min), + curve->GetXValue(ranges[r].m_max)); - if (draw_spline) - { - wxRangeDouble viewRange(viewRect.m_x, viewRect.GetRight()); - wxRangeDouble dcRange(dcRect.x, dcRect.GetRight()); - - for (int r = n_range; r < range_count; r++) - { - wxRangeDouble plotRange(curve->GetXValue(ranges[r].m_min), - curve->GetXValue(ranges[r].m_max)); - - if (viewRange.Intersects(plotRange)) - { - double min_x = m_owner->GetClientCoordFromPlotX(plotRange.m_min); - double max_x = m_owner->GetClientCoordFromPlotX(plotRange.m_max); - dblRangeSel.SelectRange(wxRangeDouble(min_x, max_x)); - } - else - break; - } - - // spline starts 2 points back for smoothness - int s_start = n_start > 1 ? -2 : n_start > 0 ? -1 : 0; - sd.Create(dc, currentPen, selectedPen, - wxRect2DDouble(dcRect.x, dcRect.y, dcRect.width, dcRect.height), - &dblRangeSel, - m_owner->GetClientCoordFromPlotX(x_data[s_start]), - m_owner->GetClientCoordFromPlotY(y_data[s_start]), - m_owner->GetClientCoordFromPlotX(x_data[s_start+1]), - m_owner->GetClientCoordFromPlotY(y_data[s_start+1])); + if (viewRange.Intersects(plotRange)) { + double min_x = m_owner->GetClientCoordFromPlotX(plotRange.m_min); + double max_x = m_owner->GetClientCoordFromPlotX(plotRange.m_max); + dblRangeSel.SelectRange(wxRangeDouble(min_x, max_x)); + } + else { + break; + } } - for (n = n_start; n < n_end; n++) - { - x1 = *x_data++; - y1 = *y_data++; - - if (draw_spline) - sd.DrawSpline(m_owner->GetClientCoordFromPlotX(x1), - m_owner->GetClientCoordFromPlotY(y1)); - - xx0 = x0; yy0 = y0; xx1 = x1; yy1 = y1; - clipped = ClipLineToRect(xx0, yy0, xx1, yy1, viewRect); - if (clipped != ClippedOut) - { - i0 = m_owner->GetClientCoordFromPlotX(xx0); - j0 = m_owner->GetClientCoordFromPlotY(yy0); - i1 = m_owner->GetClientCoordFromPlotX(xx1); - j1 = m_owner->GetClientCoordFromPlotY(yy1); - - if (draw_lines && ((i0 != i1) || (j0 != j1))) - { - wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j1); - } - - if (n == min_sel) - dc->SetPen( selectedPen ); - - if (draw_symbols && !((clipped & ClippedSecond) != 0) && - ((i0 != i1) || (j0 != j1) || (n == min_sel) || (n == n_start))) - { - //dc->DrawBitmap( bitmap, i1 - bitmapHalfWidth, j1 - bitmapHalfHeight, true ); - wxPLOT_DRAW_ELLIPSE(dc, window, pen, i1, j1, 2, 2); - } - } - else if (n == min_sel) - { - dc->SetPen( selectedPen ); - } + // spline starts 2 points back for smoothness + int s_start = n_start > 1 ? -2 : n_start > 0 ? -1 : 0; + sd.Create(dc, currentPen, selectedPen, + wxRect2DDouble(dcRect.x, dcRect.y, dcRect.width, dcRect.height), &dblRangeSel, + m_owner->GetClientCoordFromPlotX(x_data[s_start]), + m_owner->GetClientCoordFromPlotY(y_data[s_start]), + m_owner->GetClientCoordFromPlotX(x_data[s_start + 1]), + m_owner->GetClientCoordFromPlotY(y_data[s_start + 1])); + } + + for (n = n_start; n < n_end; n++) { + x1 = *x_data++; + y1 = *y_data++; + + if (draw_spline) { + sd.DrawSpline(m_owner->GetClientCoordFromPlotX(x1), m_owner->GetClientCoordFromPlotY(y1)); + } - if (n == max_sel) - { - dc->SetPen( currentPen ); - if (n_range < range_count - 1) - { - n_range++; - min_sel = ranges[n_range].m_min; - max_sel = ranges[n_range].m_max; - } - } + xx0 = x0; + yy0 = y0; + xx1 = x1; + yy1 = y1; + clipped = ClipLineToRect(xx0, yy0, xx1, yy1, viewRect); + if (clipped != ClippedOut) { + i0 = m_owner->GetClientCoordFromPlotX(xx0); + j0 = m_owner->GetClientCoordFromPlotY(yy0); + i1 = m_owner->GetClientCoordFromPlotX(xx1); + j1 = m_owner->GetClientCoordFromPlotY(yy1); + + if (draw_lines && ((i0 != i1) || (j0 != j1))) { + wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j1); + } + + if (n == min_sel) { + dc->SetPen(selectedPen); + } + + if (draw_symbols && !((clipped & ClippedSecond) != 0) && + ((i0 != i1) || (j0 != j1) || (n == min_sel) || (n == n_start))) { + // dc->DrawBitmap( bitmap, i1 - bitmapHalfWidth, j1 - bitmapHalfHeight, true ); + wxPLOT_DRAW_ELLIPSE(dc, window, pen, i1, j1, 2, 2); + } + } + else if (n == min_sel) { + dc->SetPen(selectedPen); + } - x0 = x1; - y0 = y1; + if (n == max_sel) { + dc->SetPen(currentPen); + if (n_range < range_count - 1) { + n_range++; + min_sel = ranges[n_range].m_min; + max_sel = ranges[n_range].m_max; + } } - if (draw_spline) - { - // want an extra point at the end to smooth it out - if (n_end < (int)curve->GetCount() - 1) - sd.DrawSpline(m_owner->GetClientCoordFromPlotX(*x_data), - m_owner->GetClientCoordFromPlotY(*y_data)); + x0 = x1; + y0 = y1; + } - sd.EndSpline(); + if (draw_spline) { + // want an extra point at the end to smooth it out + if (n_end < (int)curve->GetCount() - 1) { + sd.DrawSpline(m_owner->GetClientCoordFromPlotX(*x_data), + m_owner->GetClientCoordFromPlotY(*y_data)); } - dc->SetPen(wxNullPen); + sd.EndSpline(); + } + + dc->SetPen(wxNullPen); } //----------------------------------------------------------------------------- @@ -1010,159 +1019,151 @@ void wxPlotDrawerDataCurve::Draw(wxDC *dc, wxPlotData* curve, int curve_index) //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotDrawerMarker, wxPlotDrawerBase) -void wxPlotDrawerMarker::Draw(wxDC *dc, const wxPlotMarker& marker) +void wxPlotDrawerMarker::Draw(wxDC *dc, const wxPlotMarker &marker) { - // drawing multiple markers is faster, so just drawing a single one takes a hit - wxArrayPlotMarker markers; - markers.Add(marker); - Draw(dc, markers); + // drawing multiple markers is faster, so just drawing a single one takes a hit + wxArrayPlotMarker markers; + markers.Add(marker); + Draw(dc, markers); } -void wxPlotDrawerMarker::Draw(wxDC *dc, const wxArrayPlotMarker& markers) +void wxPlotDrawerMarker::Draw(wxDC *dc, const wxArrayPlotMarker &markers) { - wxCHECK_RET(dc && m_owner, wxT("dc or owner")); - INITIALIZE_FAST_GRAPHICS - - wxRect dcRect(GetDCRect()); - wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect( dcRect ); + wxCHECK_RET(dc && m_owner, wxT("dc or owner")); + INITIALIZE_FAST_GRAPHICS + + wxRect dcRect(GetDCRect()); + wxRect2DDouble subViewRect = m_owner->GetPlotRectFromClientRect(dcRect); + + double x0 = 0, y0 = 0, x1 = 0, y1 = 0; + int n, count = markers.GetCount(); + for (n = 0; n < count; n++) { + const wxPlotMarker &marker = markers[n]; + wxCHECK_RET(marker.Ok(), wxT("Invalid marker")); + wxRect2DDouble r = marker.GetPlotRect(); + x0 = r.m_x; + y0 = r.m_y; + x1 = r.GetRight(); + y1 = r.GetBottom(); + + if (marker.GetPen().Ok()) { + dc->SetPen(marker.GetPen().GetPen()); + } + if (marker.GetBrush().Ok()) { + dc->SetBrush(marker.GetBrush().GetBrush()); + } - double x0 = 0, y0 = 0, x1 = 0, y1 = 0; - int n, count = markers.GetCount(); - for (n = 0; n < count; n++) + // determine what to draw + int marker_type = marker.GetMarkerType(); + wxSize size = marker.GetSize(); + + if (marker_type == wxPLOTMARKER_BITMAP) { + wxBitmap bmp(marker.GetBitmap()); + int w = bmp.GetWidth(), h = bmp.GetHeight(); + // FIXME - add scaling and shifting later - maybe + int i0 = m_owner->GetClientCoordFromPlotX(x0); + int j0 = m_owner->GetClientCoordFromPlotY(y0); + dc->DrawBitmap(bmp, RINT(i0 - w / 2.0), RINT(j0 - h / 2.0), true); + } + else if (marker_type == wxPLOTMARKER_LINE) { + if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { + int i0 = m_owner->GetClientCoordFromPlotX(x0); + int j0 = m_owner->GetClientCoordFromPlotY(y0); + int i1 = m_owner->GetClientCoordFromPlotX(x1); + int j1 = m_owner->GetClientCoordFromPlotY(y1); + wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j1); + } + } + else if (marker_type == wxPLOTMARKER_ELLIPSE) { + // fixed pixel size + if ((size.x > 0) && (size.y > 0)) { + if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { + int i0 = m_owner->GetClientCoordFromPlotX(x0); + int j0 = m_owner->GetClientCoordFromPlotY(y0); + wxPLOT_DRAW_ELLIPSE(dc, window, pen, i0, j0, size.x, size.y); + } + } + /* + else if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) + { + int i0 = m_owner->GetClientCoordFromPlotX(x0); + int j0 = m_owner->GetClientCoordFromPlotY(y0); + int i1 = m_owner->GetClientCoordFromPlotX(x1); + int j1 = m_owner->GetClientCoordFromPlotY(y1); + wxPLOT_DRAW_ELLIPSE(dc, window, pen, i0, j0, i1, j1); + } + */ + } + else // figure out the rest { - const wxPlotMarker &marker = markers[n]; - wxCHECK_RET(marker.Ok(), wxT("Invalid marker")); - wxRect2DDouble r = marker.GetPlotRect(); - x0 = r.m_x; - y0 = r.m_y; - x1 = r.GetRight(); - y1 = r.GetBottom(); - - if (marker.GetPen().Ok()) - dc->SetPen(marker.GetPen().GetPen()); - if (marker.GetBrush().Ok()) - dc->SetBrush(marker.GetBrush().GetBrush()); - - // determine what to draw - int marker_type = marker.GetMarkerType(); - wxSize size = marker.GetSize(); - - if (marker_type == wxPLOTMARKER_BITMAP) - { - wxBitmap bmp(marker.GetBitmap()); - int w = bmp.GetWidth(), h = bmp.GetHeight(); - // FIXME - add scaling and shifting later - maybe - int i0 = m_owner->GetClientCoordFromPlotX(x0); - int j0 = m_owner->GetClientCoordFromPlotY(y0); - dc->DrawBitmap(bmp, RINT(i0 - w/2.0), RINT(j0 - h/2.0), true); + // we may ignore type if rect is in certain states + + bool is_horiz = r.m_width < 0; + bool is_vert = r.m_height < 0; + + bool cross = is_horiz && is_vert; + + if (is_horiz) { + x0 = subViewRect.m_x - subViewRect.m_width; // push outside win + x1 = subViewRect.GetRight() + subViewRect.m_width; + } + if (is_vert) { + y0 = subViewRect.m_y - subViewRect.m_height; + y1 = subViewRect.GetBottom() + subViewRect.m_height; + } + + if ((marker_type == wxPLOTMARKER_POINT) || ((x0 == x1) && (y0 == y1))) { + if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { + int i0 = m_owner->GetClientCoordFromPlotX(x0); + int j0 = m_owner->GetClientCoordFromPlotY(y0); + dc->DrawPoint(i0, j0); } - else if (marker_type == wxPLOTMARKER_LINE) - { - if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) - { - int i0 = m_owner->GetClientCoordFromPlotX(x0); - int j0 = m_owner->GetClientCoordFromPlotY(y0); - int i1 = m_owner->GetClientCoordFromPlotX(x1); - int j1 = m_owner->GetClientCoordFromPlotY(y1); - wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j1); - } + } + else if ((marker_type == wxPLOTMARKER_VERT_LINE) || ((x0 == x1) && (y0 != y1))) { + if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { + int i0 = m_owner->GetClientCoordFromPlotX(x0); + int j0 = m_owner->GetClientCoordFromPlotY(y0); + int j1 = m_owner->GetClientCoordFromPlotY(y1); + wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i0, j1); } - else if (marker_type == wxPLOTMARKER_ELLIPSE) - { - // fixed pixel size - if ((size.x > 0) && (size.y > 0)) - { - if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) - { - int i0 = m_owner->GetClientCoordFromPlotX(x0); - int j0 = m_owner->GetClientCoordFromPlotY(y0); - wxPLOT_DRAW_ELLIPSE(dc, window, pen, i0, j0, size.x, size.y); - } - } -/* - else if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) - { - int i0 = m_owner->GetClientCoordFromPlotX(x0); - int j0 = m_owner->GetClientCoordFromPlotY(y0); - int i1 = m_owner->GetClientCoordFromPlotX(x1); - int j1 = m_owner->GetClientCoordFromPlotY(y1); - wxPLOT_DRAW_ELLIPSE(dc, window, pen, i0, j0, i1, j1); - } -*/ + } + else if ((marker_type == wxPLOTMARKER_HORIZ_LINE) || ((y0 == y1) && (x0 != x1))) { + if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) { + int i0 = m_owner->GetClientCoordFromPlotX(x0); + int i1 = m_owner->GetClientCoordFromPlotX(x1); + int j0 = m_owner->GetClientCoordFromPlotY(y0); + wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j0); } - else // figure out the rest - { - // we may ignore type if rect is in certain states - - bool is_horiz = r.m_width < 0; - bool is_vert = r.m_height < 0; - - bool cross = is_horiz && is_vert; - - if (is_horiz) - { - x0 = subViewRect.m_x - subViewRect.m_width; // push outside win - x1 = subViewRect.GetRight() + subViewRect.m_width; - } - if (is_vert) - { - y0 = subViewRect.m_y - subViewRect.m_height; - y1 = subViewRect.GetBottom() + subViewRect.m_height; - } - - if ((marker_type == wxPLOTMARKER_POINT) || ((x0 == x1) && (y0 == y1))) - { - if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) - { - int i0 = m_owner->GetClientCoordFromPlotX(x0); - int j0 = m_owner->GetClientCoordFromPlotY(y0); - dc->DrawPoint(i0, j0); - } - } - else if ((marker_type == wxPLOTMARKER_VERT_LINE) || ((x0 == x1) && (y0 != y1))) - { - if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) - { - int i0 = m_owner->GetClientCoordFromPlotX(x0); - int j0 = m_owner->GetClientCoordFromPlotY(y0); - int j1 = m_owner->GetClientCoordFromPlotY(y1); - wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i0, j1); - } - } - else if ((marker_type == wxPLOTMARKER_HORIZ_LINE) || ((y0 == y1) && (x0 != x1))) - { - if (ClipLineToRect(x0, y0, x1, y1, subViewRect) != ClippedOut) - { - int i0 = m_owner->GetClientCoordFromPlotX(x0); - int i1 = m_owner->GetClientCoordFromPlotX(x1); - int j0 = m_owner->GetClientCoordFromPlotY(y0); - wxPLOT_DRAW_LINE(dc, window, pen, i0, j0, i1, j0); - } - } - else if ((marker_type == wxPLOTMARKER_CROSS) || cross) - { - - - } - else // rectangle - { - wxRect2DDouble clippedRect(x0, y0, x1 - x0, y1 - y0); - clippedRect.Intersect(subViewRect); - int pen_width = dc->GetPen().GetWidth() + 2; - - int i0 = m_owner->GetClientCoordFromPlotX(clippedRect.m_x); - int i1 = m_owner->GetClientCoordFromPlotX(clippedRect.GetRight()); - int j0 = m_owner->GetClientCoordFromPlotY(clippedRect.m_y); - int j1 = m_owner->GetClientCoordFromPlotY(clippedRect.GetBottom()); - if (r.m_x < subViewRect.m_x) i0 -= pen_width; - if (r.m_y < subViewRect.m_y) j0 -= pen_width; - if (r.GetRight() > subViewRect.GetRight()) i1 += pen_width; - if (r.GetBottom() > subViewRect.GetBottom()) j1 += pen_width; - - dc->SetClippingRegion(dcRect); - dc->DrawRectangle(i0, j0, i1 - i0 + 1, j1 - j0 + 1); - dc->DestroyClippingRegion(); - } + } + else if ((marker_type == wxPLOTMARKER_CROSS) || cross) { + } + else // rectangle + { + wxRect2DDouble clippedRect(x0, y0, x1 - x0, y1 - y0); + clippedRect.Intersect(subViewRect); + int pen_width = dc->GetPen().GetWidth() + 2; + + int i0 = m_owner->GetClientCoordFromPlotX(clippedRect.m_x); + int i1 = m_owner->GetClientCoordFromPlotX(clippedRect.GetRight()); + int j0 = m_owner->GetClientCoordFromPlotY(clippedRect.m_y); + int j1 = m_owner->GetClientCoordFromPlotY(clippedRect.GetBottom()); + if (r.m_x < subViewRect.m_x) { + i0 -= pen_width; } + if (r.m_y < subViewRect.m_y) { + j0 -= pen_width; + } + if (r.GetRight() > subViewRect.GetRight()) { + i1 += pen_width; + } + if (r.GetBottom() > subViewRect.GetBottom()) { + j1 += pen_width; + } + + dc->SetClippingRegion(dcRect); + dc->DrawRectangle(i0, j0, i1 - i0 + 1, j1 - j0 + 1); + dc->DestroyClippingRegion(); + } } + } } diff --git a/src/labenski/src/plotfunc.cpp b/src/labenski/src/plotfunc.cpp index c7fce2074..e3e4fe104 100644 --- a/src/labenski/src/plotfunc.cpp +++ b/src/labenski/src/plotfunc.cpp @@ -12,14 +12,14 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/bitmap.h" - #include "wx/textdlg.h" - #include "wx/msgdlg.h" - #include "wx/dcmemory.h" +#include "wx/bitmap.h" +#include "wx/textdlg.h" +#include "wx/msgdlg.h" +#include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/plotctrl/plotfunc.h" @@ -30,133 +30,124 @@ // wxPlotFuncRefData //---------------------------------------------------------------------------- -class wxPlotFuncRefData: public wxPlotCurveRefData -{ +class wxPlotFuncRefData : public wxPlotCurveRefData { public: - wxPlotFuncRefData() : wxPlotCurveRefData() {} - wxPlotFuncRefData(const wxPlotFuncRefData& data); + wxPlotFuncRefData() : wxPlotCurveRefData() {} + wxPlotFuncRefData(const wxPlotFuncRefData &data); - wxFunctionParser m_parser; + wxFunctionParser m_parser; }; -wxPlotFuncRefData::wxPlotFuncRefData(const wxPlotFuncRefData& data) - :wxPlotCurveRefData() +wxPlotFuncRefData::wxPlotFuncRefData(const wxPlotFuncRefData &data) : wxPlotCurveRefData() { - wxPlotCurveRefData::Copy(data); - m_parser = data.m_parser; + wxPlotCurveRefData::Copy(data); + m_parser = data.m_parser; } -#define M_PLOTFUNCDATA ((wxPlotFuncRefData*)m_refData) +#define M_PLOTFUNCDATA ((wxPlotFuncRefData *)m_refData) //----------------------------------------------------------------------------- // wxPlotFunction //----------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPlotFunction, wxPlotCurve); -wxObjectRefData *wxPlotFunction::CreateRefData() const -{ - return new wxPlotFuncRefData; -} +wxObjectRefData *wxPlotFunction::CreateRefData() const { return new wxPlotFuncRefData; } wxObjectRefData *wxPlotFunction::CloneRefData(const wxObjectRefData *data) const { - return new wxPlotFuncRefData(*(const wxPlotFuncRefData *)data); + return new wxPlotFuncRefData(*(const wxPlotFuncRefData *)data); } -bool wxPlotFunction::Create( const wxPlotFunction& curve ) +bool wxPlotFunction::Create(const wxPlotFunction &curve) { - wxCHECK_MSG(curve.Ok(), false, wxT("invalid plot function")); - UnRef(); - Ref(curve); - return true; + wxCHECK_MSG(curve.Ok(), false, wxT("invalid plot function")); + UnRef(); + Ref(curve); + return true; } -void wxPlotFunction::Destroy() -{ - UnRef(); -} +void wxPlotFunction::Destroy() { UnRef(); } -bool wxPlotFunction::Ok() const -{ - return m_refData && M_PLOTFUNCDATA->m_parser.Ok(); -} +bool wxPlotFunction::Ok() const { return m_refData && M_PLOTFUNCDATA->m_parser.Ok(); } int wxPlotFunction::Create(const wxString &function, const wxString &vars, bool useDegrees) { - UnRef(); + UnRef(); - m_refData = new wxPlotFuncRefData(); - wxCHECK_MSG(m_refData, 0, wxT("can't allocate memory")); + m_refData = new wxPlotFuncRefData(); + wxCHECK_MSG(m_refData, 0, wxT("can't allocate memory")); - int i = M_PLOTFUNCDATA->m_parser.Parse(function, vars, useDegrees); + int i = M_PLOTFUNCDATA->m_parser.Parse(function, vars, useDegrees); - if (!M_PLOTFUNCDATA->m_parser.ErrorMsg().IsEmpty()) - return i; + if (!M_PLOTFUNCDATA->m_parser.ErrorMsg().IsEmpty()) { + return i; + } - return -1; + return -1; } int wxPlotFunction::Parse(const wxString &function, const wxString &vars, bool useDegrees) { - wxCHECK_MSG(m_refData, 0, wxT("Invalid plotfunction")); + wxCHECK_MSG(m_refData, 0, wxT("Invalid plotfunction")); - int i = M_PLOTFUNCDATA->m_parser.Parse(function, vars, useDegrees); + int i = M_PLOTFUNCDATA->m_parser.Parse(function, vars, useDegrees); - if (!M_PLOTFUNCDATA->m_parser.ErrorMsg().IsEmpty()) - return i; + if (!M_PLOTFUNCDATA->m_parser.ErrorMsg().IsEmpty()) { + return i; + } - return -1; + return -1; } wxString wxPlotFunction::GetFunctionString() const { - wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.GetFunctionString(); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.GetFunctionString(); } wxString wxPlotFunction::GetVariableString() const { - wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.GetVariableString(); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.GetVariableString(); } wxString wxPlotFunction::GetVariableName(size_t n) const { - wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); - wxCHECK_MSG((int(n) < GetNumberVariables()), wxEmptyString, wxT("invalid variable index")); - return M_PLOTFUNCDATA->m_parser.GetVariableName(n); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("invalid plotfunction")); + wxCHECK_MSG((int(n) < GetNumberVariables()), wxEmptyString, wxT("invalid variable index")); + return M_PLOTFUNCDATA->m_parser.GetVariableName(n); } int wxPlotFunction::GetNumberVariables() const { - wxCHECK_MSG(Ok(), 0, wxT("Invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.GetNumberVariables(); + wxCHECK_MSG(Ok(), 0, wxT("Invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.GetNumberVariables(); } bool wxPlotFunction::GetUseDegrees() const { - wxCHECK_MSG(m_refData, false, wxT("Invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.GetUseDegrees(); + wxCHECK_MSG(m_refData, false, wxT("Invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.GetUseDegrees(); } wxString wxPlotFunction::GetErrorMsg() const { - wxCHECK_MSG(m_refData, wxEmptyString, wxT("Invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.ErrorMsg(); + wxCHECK_MSG(m_refData, wxEmptyString, wxT("Invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.ErrorMsg(); } -double wxPlotFunction::GetY( double x ) +double wxPlotFunction::GetY(double x) { - wxCHECK_MSG(Ok(), 0.0, wxT("invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.Eval( &x ); + wxCHECK_MSG(Ok(), 0.0, wxT("invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.Eval(&x); } -double wxPlotFunction::GetValue( double *x ) +double wxPlotFunction::GetValue(double *x) { - wxCHECK_MSG(Ok(), 0.0, wxT("invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.Eval( x ); + wxCHECK_MSG(Ok(), 0.0, wxT("invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.Eval(x); } -bool wxPlotFunction::AddConstant(const wxString& name, double value) +bool wxPlotFunction::AddConstant(const wxString &name, double value) { - wxCHECK_MSG(Ok(), false, wxT("invalid plotfunction")); - return M_PLOTFUNCDATA->m_parser.AddConstant(name, value); + wxCHECK_MSG(Ok(), false, wxT("invalid plotfunction")); + return M_PLOTFUNCDATA->m_parser.AddConstant(name, value); } //----------------------------------------------------------------------------- @@ -169,43 +160,42 @@ bool wxPlotFunction::AddConstant(const wxString& name, double value) wxPlotFunction wxClipboardGetPlotFunction() { - bool is_opened = wxTheClipboard->IsOpened(); - wxPlotFunction plotFunc; - - if (is_opened || wxTheClipboard->Open()) - { - wxTextDataObject textDataObject; - if (wxTheClipboard->IsSupported(wxDataFormat(wxDF_TEXT)) && - wxTheClipboard->GetData(textDataObject)) - { - wxString str = textDataObject.GetText(); - plotFunc.Create(str.BeforeLast(wxT(';')), str.AfterLast(wxT(';'))); - } - - if (!is_opened) - wxTheClipboard->Close(); + bool is_opened = wxTheClipboard->IsOpened(); + wxPlotFunction plotFunc; + + if (is_opened || wxTheClipboard->Open()) { + wxTextDataObject textDataObject; + if (wxTheClipboard->IsSupported(wxDataFormat(wxDF_TEXT)) && + wxTheClipboard->GetData(textDataObject)) { + wxString str = textDataObject.GetText(); + plotFunc.Create(str.BeforeLast(wxT(';')), str.AfterLast(wxT(';'))); + } + + if (!is_opened) { + wxTheClipboard->Close(); } + } - return plotFunc; + return plotFunc; } -bool wxClipboardSetPlotFunction(const wxPlotFunction& plotFunc) +bool wxClipboardSetPlotFunction(const wxPlotFunction &plotFunc) { wxCHECK_MSG(plotFunc.Ok(), false, wxT("Invalid wxPlotFunction to copy to clipboard")); - bool is_opened = wxTheClipboard->IsOpened(); + bool is_opened = wxTheClipboard->IsOpened(); - if (is_opened || wxTheClipboard->Open()) - { - wxString str = plotFunc.GetFunctionString() + wxT(";") + plotFunc.GetVariableString(); - wxTextDataObject *textDataObject = new wxTextDataObject(str); - wxTheClipboard->SetData( textDataObject ); + if (is_opened || wxTheClipboard->Open()) { + wxString str = plotFunc.GetFunctionString() + wxT(";") + plotFunc.GetVariableString(); + wxTextDataObject *textDataObject = new wxTextDataObject(str); + wxTheClipboard->SetData(textDataObject); - if (!is_opened) - wxTheClipboard->Close(); - - return true; + if (!is_opened) { + wxTheClipboard->Close(); } - return false; + return true; + } + + return false; } #endif // wxUSE_DATAOBJ && wxUSE_CLIPBOARD diff --git a/src/labenski/src/plotmark.cpp b/src/labenski/src/plotmark.cpp index 44f131218..2976922fb 100644 --- a/src/labenski/src/plotmark.cpp +++ b/src/labenski/src/plotmark.cpp @@ -12,11 +12,11 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/wx.h" +#include "wx/wx.h" #endif // WX_PRECOMP #include "wx/image.h" @@ -25,32 +25,34 @@ #include "wx/plotctrl/plotctrl.h" #include "wx/arrimpl.cpp" -WX_DEFINE_OBJARRAY( wxArrayPlotMarker ); +WX_DEFINE_OBJARRAY(wxArrayPlotMarker); //----------------------------------------------------------------------------- // wxPlotMarkerRefData //----------------------------------------------------------------------------- -class wxPlotMarkerRefData : public wxObjectRefData -{ +class wxPlotMarkerRefData : public wxObjectRefData { public: - wxPlotMarkerRefData(int type = 0, const wxRect2DDouble& rect = wxRect2DDouble()) - : wxObjectRefData(), m_markerType(type), m_rect(rect), m_size(wxSize(-1, -1)) {} - - wxPlotMarkerRefData( const wxPlotMarkerRefData& data ) - : wxObjectRefData(), m_markerType(data.m_markerType), - m_rect(data.m_rect), m_size(data.m_size), m_bitmap(data.m_bitmap), - m_pen(data.m_pen), m_brush(data.m_brush) {} - - int m_markerType; - wxRect2DDouble m_rect; - wxSize m_size; - wxBitmap m_bitmap; - wxGenericPen m_pen; - wxGenericBrush m_brush; + wxPlotMarkerRefData(int type = 0, const wxRect2DDouble &rect = wxRect2DDouble()) + : wxObjectRefData(), m_markerType(type), m_rect(rect), m_size(wxSize(-1, -1)) + { + } + + wxPlotMarkerRefData(const wxPlotMarkerRefData &data) + : wxObjectRefData(), m_markerType(data.m_markerType), m_rect(data.m_rect), m_size(data.m_size), + m_bitmap(data.m_bitmap), m_pen(data.m_pen), m_brush(data.m_brush) + { + } + + int m_markerType; + wxRect2DDouble m_rect; + wxSize m_size; + wxBitmap m_bitmap; + wxGenericPen m_pen; + wxGenericBrush m_brush; }; -#define M_PMARKERDATA ((wxPlotMarkerRefData*)m_refData) +#define M_PMARKERDATA ((wxPlotMarkerRefData *)m_refData) //----------------------------------------------------------------------------- // wxPlotMarker @@ -58,105 +60,102 @@ class wxPlotMarkerRefData : public wxObjectRefData IMPLEMENT_DYNAMIC_CLASS(wxPlotMarker, wxObject); -wxObjectRefData *wxPlotMarker::CreateRefData() const -{ - return new wxPlotMarkerRefData; -} +wxObjectRefData *wxPlotMarker::CreateRefData() const { return new wxPlotMarkerRefData; } wxObjectRefData *wxPlotMarker::CloneRefData(const wxObjectRefData *data) const { - return new wxPlotMarkerRefData(*(const wxPlotMarkerRefData *)data); + return new wxPlotMarkerRefData(*(const wxPlotMarkerRefData *)data); } -void wxPlotMarker::Create(int marker_type, const wxRect2DDouble& rect, - const wxSize& size, const wxGenericPen& pen, - const wxGenericBrush& brush, const wxBitmap& bitmap) +void wxPlotMarker::Create(int marker_type, const wxRect2DDouble &rect, const wxSize &size, + const wxGenericPen &pen, const wxGenericBrush &brush, + const wxBitmap &bitmap) { - UnRef(); - m_refData = new wxPlotMarkerRefData(marker_type, rect); - M_PMARKERDATA->m_size = size; - M_PMARKERDATA->m_pen = pen; - M_PMARKERDATA->m_brush = brush; - M_PMARKERDATA->m_bitmap = bitmap; + UnRef(); + m_refData = new wxPlotMarkerRefData(marker_type, rect); + M_PMARKERDATA->m_size = size; + M_PMARKERDATA->m_pen = pen; + M_PMARKERDATA->m_brush = brush; + M_PMARKERDATA->m_bitmap = bitmap; } int wxPlotMarker::GetMarkerType() const { - wxCHECK_MSG(Ok(), wxPLOTMARKER_NONE, wxT("Invalid plot marker")); - return M_PMARKERDATA->m_markerType; + wxCHECK_MSG(Ok(), wxPLOTMARKER_NONE, wxT("Invalid plot marker")); + return M_PMARKERDATA->m_markerType; } void wxPlotMarker::SetMarkerType(int type) { - wxCHECK_RET(Ok(), wxT("Invalid plot marker")); - M_PMARKERDATA->m_markerType = type; + wxCHECK_RET(Ok(), wxT("Invalid plot marker")); + M_PMARKERDATA->m_markerType = type; } wxRect2DDouble wxPlotMarker::GetPlotRect() const { - wxCHECK_MSG(Ok(), wxRect2DDouble(), wxT("Invalid plot marker")); - return M_PMARKERDATA->m_rect; + wxCHECK_MSG(Ok(), wxRect2DDouble(), wxT("Invalid plot marker")); + return M_PMARKERDATA->m_rect; } -wxRect2DDouble& wxPlotMarker::GetPlotRect() +wxRect2DDouble &wxPlotMarker::GetPlotRect() { - static wxRect2DDouble s_rect; - wxCHECK_MSG(Ok(), s_rect, wxT("Invalid plot marker")); - return M_PMARKERDATA->m_rect; + static wxRect2DDouble s_rect; + wxCHECK_MSG(Ok(), s_rect, wxT("Invalid plot marker")); + return M_PMARKERDATA->m_rect; } -void wxPlotMarker::SetPlotRect(const wxRect2DDouble& rect) +void wxPlotMarker::SetPlotRect(const wxRect2DDouble &rect) { - wxCHECK_RET(Ok(), wxT("Invalid plot marker")); - M_PMARKERDATA->m_rect = rect; + wxCHECK_RET(Ok(), wxT("Invalid plot marker")); + M_PMARKERDATA->m_rect = rect; } wxPoint2DDouble wxPlotMarker::GetPlotPosition() const { - wxCHECK_MSG(Ok(), wxPoint2DDouble(), wxT("Invalid plot marker")); - return M_PMARKERDATA->m_rect.GetLeftTop(); + wxCHECK_MSG(Ok(), wxPoint2DDouble(), wxT("Invalid plot marker")); + return M_PMARKERDATA->m_rect.GetLeftTop(); } -void wxPlotMarker::SetPlotPosition(const wxPoint2DDouble& pos) +void wxPlotMarker::SetPlotPosition(const wxPoint2DDouble &pos) { - wxCHECK_RET(Ok(), wxT("Invalid plot marker")); - M_PMARKERDATA->m_rect.m_x = pos.m_x; - M_PMARKERDATA->m_rect.m_y = pos.m_y; + wxCHECK_RET(Ok(), wxT("Invalid plot marker")); + M_PMARKERDATA->m_rect.m_x = pos.m_x; + M_PMARKERDATA->m_rect.m_y = pos.m_y; } wxSize wxPlotMarker::GetSize() const { - wxCHECK_MSG(Ok(), wxSize(-1, -1), wxT("Invalid plot marker")); - return M_PMARKERDATA->m_size; + wxCHECK_MSG(Ok(), wxSize(-1, -1), wxT("Invalid plot marker")); + return M_PMARKERDATA->m_size; } -void wxPlotMarker::SetSize(const wxSize& size) +void wxPlotMarker::SetSize(const wxSize &size) { - wxCHECK_RET(Ok(), wxT("Invalid plot marker")); - M_PMARKERDATA->m_size = size; + wxCHECK_RET(Ok(), wxT("Invalid plot marker")); + M_PMARKERDATA->m_size = size; } wxGenericPen wxPlotMarker::GetPen() const { - wxCHECK_MSG(Ok(), wxNullGenericPen, wxT("Invalid plot marker")); - return M_PMARKERDATA->m_pen; + wxCHECK_MSG(Ok(), wxNullGenericPen, wxT("Invalid plot marker")); + return M_PMARKERDATA->m_pen; } -void wxPlotMarker::SetPen(const wxGenericPen& pen) +void wxPlotMarker::SetPen(const wxGenericPen &pen) { - wxCHECK_RET(Ok(), wxT("Invalid plot marker")); - M_PMARKERDATA->m_pen = pen; + wxCHECK_RET(Ok(), wxT("Invalid plot marker")); + M_PMARKERDATA->m_pen = pen; } wxGenericBrush wxPlotMarker::GetBrush() const { - wxCHECK_MSG(Ok(), wxNullGenericBrush, wxT("Invalid plot marker")); - return M_PMARKERDATA->m_brush; + wxCHECK_MSG(Ok(), wxNullGenericBrush, wxT("Invalid plot marker")); + return M_PMARKERDATA->m_brush; } -void wxPlotMarker::SetBrush(const wxGenericBrush& brush) +void wxPlotMarker::SetBrush(const wxGenericBrush &brush) { - wxCHECK_RET(Ok(), wxT("Invalid plot marker")); - M_PMARKERDATA->m_brush = brush; + wxCHECK_RET(Ok(), wxT("Invalid plot marker")); + M_PMARKERDATA->m_brush = brush; } wxBitmap wxPlotMarker::GetBitmap() const { - wxCHECK_MSG(Ok(), wxNullBitmap, wxT("Invalid plot marker")); - return M_PMARKERDATA->m_bitmap; + wxCHECK_MSG(Ok(), wxNullBitmap, wxT("Invalid plot marker")); + return M_PMARKERDATA->m_bitmap; } -void wxPlotMarker::SetBitmap(const wxBitmap& bitmap) +void wxPlotMarker::SetBitmap(const wxBitmap &bitmap) { - wxCHECK_RET(Ok(), wxT("Invalid plot marker")); - M_PMARKERDATA->m_bitmap = bitmap; + wxCHECK_RET(Ok(), wxT("Invalid plot marker")); + M_PMARKERDATA->m_bitmap = bitmap; } diff --git a/src/labenski/src/plotprnt.cpp b/src/labenski/src/plotprnt.cpp index f41c45c85..5d389b3a5 100644 --- a/src/labenski/src/plotprnt.cpp +++ b/src/labenski/src/plotprnt.cpp @@ -12,12 +12,12 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/msgdlg.h" - #include "wx/dcmemory.h" +#include "wx/msgdlg.h" +#include "wx/dcmemory.h" #endif // WX_PRECOMP #include "wx/module.h" @@ -26,7 +26,7 @@ #include "wx/plotctrl/plotctrl.h" #include "wx/plotctrl/plotprnt.h" -#define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x) - 0.5)) +#define RINT(x) int((x) >= 0 ? ((x) + 0.5) : ((x)-0.5)) //----------------------------------------------------------------------------- // wxPlotPrintout @@ -40,205 +40,203 @@ bool wxPlotPrintout::s_wxPlotPagesetupdata_static = false; wxPrintData *wxPlotPrintout::GetPrintData(bool create_on_demand) { - if (create_on_demand && (s_wxPlotPrintData == NULL)) - { - wxPrintData *printData = new wxPrintData; - printData->SetPaperId(wxPAPER_LETTER); - SetPrintData(printData, false); - } + if (create_on_demand && (s_wxPlotPrintData == NULL)) { + wxPrintData *printData = new wxPrintData; + printData->SetPaperId(wxPAPER_LETTER); + SetPrintData(printData, false); + } - return s_wxPlotPrintData; + return s_wxPlotPrintData; } wxPageSetupData *wxPlotPrintout::GetPageSetupData(bool create_on_demand) { - if (create_on_demand && (s_wxPlotPageSetupData == NULL)) - { - wxPageSetupData *pageSetupData = new wxPageSetupData; - pageSetupData->SetPaperSize(wxPAPER_LETTER); - pageSetupData->SetMarginTopLeft(wxPoint(20, 20)); - pageSetupData->SetMarginBottomRight(wxPoint(20, 20)); - SetPageSetupData(pageSetupData, false); - } - - return s_wxPlotPageSetupData; + if (create_on_demand && (s_wxPlotPageSetupData == NULL)) { + wxPageSetupData *pageSetupData = new wxPageSetupData; + pageSetupData->SetPaperSize(wxPAPER_LETTER); + pageSetupData->SetMarginTopLeft(wxPoint(20, 20)); + pageSetupData->SetMarginBottomRight(wxPoint(20, 20)); + SetPageSetupData(pageSetupData, false); + } + + return s_wxPlotPageSetupData; } -bool wxPlotPrintout::GetPrintDataStatic() { return s_wxPlotPrintdata_static; } +bool wxPlotPrintout::GetPrintDataStatic() { return s_wxPlotPrintdata_static; } bool wxPlotPrintout::GetPageSetupDataStatic() { return s_wxPlotPagesetupdata_static; } -void wxPlotPrintout::SetPrintData( wxPrintData *printData, bool is_static ) +void wxPlotPrintout::SetPrintData(wxPrintData *printData, bool is_static) { - if (s_wxPlotPrintData && !s_wxPlotPrintdata_static) - delete s_wxPlotPrintData; + if (s_wxPlotPrintData && !s_wxPlotPrintdata_static) { + delete s_wxPlotPrintData; + } - s_wxPlotPrintData = printData; - s_wxPlotPrintdata_static = is_static; + s_wxPlotPrintData = printData; + s_wxPlotPrintdata_static = is_static; } -void wxPlotPrintout::SetPageSetupData( wxPageSetupData *pageSetupData, bool is_static ) +void wxPlotPrintout::SetPageSetupData(wxPageSetupData *pageSetupData, bool is_static) { - if (s_wxPlotPageSetupData && !s_wxPlotPagesetupdata_static) - delete s_wxPlotPageSetupData; + if (s_wxPlotPageSetupData && !s_wxPlotPagesetupdata_static) { + delete s_wxPlotPageSetupData; + } - s_wxPlotPageSetupData = pageSetupData; - s_wxPlotPagesetupdata_static = is_static; + s_wxPlotPageSetupData = pageSetupData; + s_wxPlotPagesetupdata_static = is_static; } - -wxPlotPrintout::wxPlotPrintout( wxPlotCtrl* plotWin, const wxString &title ) - : wxPrintout(title), m_plotWin(plotWin) +wxPlotPrintout::wxPlotPrintout(wxPlotCtrl *plotWin, const wxString &title) + : wxPrintout(title), m_plotWin(plotWin) { } bool wxPlotPrintout::OnBeginDocument(int startPage, int endPage) { - if (!wxPrintout::OnBeginDocument(startPage, endPage)) - return false; + if (!wxPrintout::OnBeginDocument(startPage, endPage)) { + return false; + } - return true; + return true; } bool wxPlotPrintout::OnPrintPage(int page) { - wxCHECK_MSG(m_plotWin, false, wxT("Invalid plotctrl")); + wxCHECK_MSG(m_plotWin, false, wxT("Invalid plotctrl")); - if (page != 1) return false; + if (page != 1) { + return false; + } - wxPoint pagePix; - //GetPageSizePixels(&pagePix.x, &pagePix.y); // no good for preview when scaled - GetDC()->GetSize(&pagePix.x, &pagePix.y); + wxPoint pagePix; + // GetPageSizePixels(&pagePix.x, &pagePix.y); // no good for preview when scaled + GetDC()->GetSize(&pagePix.x, &pagePix.y); - wxPoint tl = GetPageSetupData(true)->GetMarginTopLeft(); - wxPoint br = GetPageSetupData(true)->GetMarginBottomRight(); + wxPoint tl = GetPageSetupData(true)->GetMarginTopLeft(); + wxPoint br = GetPageSetupData(true)->GetMarginBottomRight(); - wxPoint ppi; + wxPoint ppi; - if (IsPreview()) - GetPPIScreen(&ppi.x, &ppi.y); - else - GetPPIPrinter(&ppi.x, &ppi.y); + if (IsPreview()) { + GetPPIScreen(&ppi.x, &ppi.y); + } + else { + GetPPIPrinter(&ppi.x, &ppi.y); + } - //wxPrintf(wxT("ppi %d %d dc size %d %d margin tl %d %d br %d %d\n"), ppi.x, ppi.y, pagePix.x, pagePix.y, tl.x, tl.y, br.x, br.y); + // wxPrintf(wxT("ppi %d %d dc size %d %d margin tl %d %d br %d %d\n"), ppi.x, ppi.y, pagePix.x, + // pagePix.y, tl.x, tl.y, br.x, br.y); - tl.x = int((tl.x*ppi.x)/25.4); - tl.y = int((tl.y*ppi.y)/25.4); - br.x = int((br.x*ppi.x)/25.4); - br.y = int((br.y*ppi.y)/25.4); + tl.x = int((tl.x * ppi.x) / 25.4); + tl.y = int((tl.y * ppi.y) / 25.4); + br.x = int((br.x * ppi.x) / 25.4); + br.y = int((br.y * ppi.y) / 25.4); - wxRect rect(tl.x, tl.y, pagePix.x - tl.x - br.x, pagePix.y - tl.y - br.y); + wxRect rect(tl.x, tl.y, pagePix.x - tl.x - br.x, pagePix.y - tl.y - br.y); - //wxPrintf(wxT("dc size %d %d margin tl %d %d br %d %d\n"), rect.width, rect.height, tl.x, tl.y, br.x, br.y); + // wxPrintf(wxT("dc size %d %d margin tl %d %d br %d %d\n"), rect.width, rect.height, tl.x, + // tl.y, br.x, br.y); - int dpi = ppi.x; + int dpi = ppi.x; - //set dpi of the drawwholeplot function - if (IsPreview()) - { - //dpi is the (screen dpi) * (percent of screen used by preview) - dpi = RINT(ppi.x * ((double)rect.width / pagePix.x)); - } + // set dpi of the drawwholeplot function + if (IsPreview()) { + // dpi is the (screen dpi) * (percent of screen used by preview) + dpi = RINT(ppi.x * ((double)rect.width / pagePix.x)); + } - m_plotWin->DrawWholePlot( GetDC(), rect, dpi ); - return true; + m_plotWin->DrawWholePlot(GetDC(), rect, dpi); + return true; } bool wxPlotPrintout::ShowPrintDialog() { - wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); - wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); - - wxPrinter printer(& printDialogData); - if (!printer.Print(GetPlotCtrl(), this, true)) - { - if (wxPrinter::GetLastError() == wxPRINTER_ERROR) - wxMessageBox(wxT("There was a problem printing.\n") - wxT("Perhaps your printer is not setup correctly?"), - _("Printing"), wxOK, GetPlotCtrl()); + wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); + wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); + + wxPrinter printer(&printDialogData); + if (!printer.Print(GetPlotCtrl(), this, true)) { + if (wxPrinter::GetLastError() == wxPRINTER_ERROR) { + wxMessageBox(wxT("There was a problem printing.\n") + wxT("Perhaps your printer is not setup correctly?"), + _("Printing"), wxOK, GetPlotCtrl()); } + } - if (wxPrinter::GetLastError() != wxPRINTER_CANCELLED) - *wxPlotPrintout::GetPrintData(true) = printer.GetPrintDialogData().GetPrintData(); + if (wxPrinter::GetLastError() != wxPRINTER_CANCELLED) { + *wxPlotPrintout::GetPrintData(true) = printer.GetPrintDialogData().GetPrintData(); + } - return wxPrinter::GetLastError() == wxPRINTER_NO_ERROR; + return wxPrinter::GetLastError() == wxPRINTER_NO_ERROR; } -bool wxPlotPrintout::ShowPrintPreviewDialog(const wxString& frameTitle) +bool wxPlotPrintout::ShowPrintPreviewDialog(const wxString &frameTitle) { - wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); - // Pass two printout objects: for preview, and possible printing. - wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); - wxPrintPreview *preview = new wxPrintPreview(new wxPlotPrintout(GetPlotCtrl(), GetTitle()), - new wxPlotPrintout(GetPlotCtrl(), GetTitle()), - &printDialogData); - if (!preview->Ok()) - { - delete preview; - wxMessageBox(wxT("There was a problem previewing.\n") - wxT("Perhaps your printer is not setup correctly?"), - _("Previewing"), wxOK, GetPlotCtrl()); - return false; - } - - wxRect r(wxGetClientDisplayRect()); - r.width = wxMin(r.width, 600); - r.height = wxMin(r.height, 650); - wxPreviewFrame *frame = new wxPreviewFrame(preview, GetPlotCtrl(), - frameTitle, - wxDefaultPosition, r.GetSize()); - frame->Centre(wxBOTH); - frame->Initialize(); - frame->Show(true); - return true; + wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); + // Pass two printout objects: for preview, and possible printing. + wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); + wxPrintPreview *preview = + new wxPrintPreview(new wxPlotPrintout(GetPlotCtrl(), GetTitle()), + new wxPlotPrintout(GetPlotCtrl(), GetTitle()), &printDialogData); + if (!preview->Ok()) { + delete preview; + wxMessageBox(wxT("There was a problem previewing.\n") + wxT("Perhaps your printer is not setup correctly?"), + _("Previewing"), wxOK, GetPlotCtrl()); + return false; + } + + wxRect r(wxGetClientDisplayRect()); + r.width = wxMin(r.width, 600); + r.height = wxMin(r.height, 650); + wxPreviewFrame *frame = + new wxPreviewFrame(preview, GetPlotCtrl(), frameTitle, wxDefaultPosition, r.GetSize()); + frame->Centre(wxBOTH); + frame->Initialize(); + frame->Show(true); + return true; } bool wxPlotPrintout::ShowPrintSetupDialog() { - wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); - wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); - wxPrintDialog printerDialog(GetPlotCtrl(), & printDialogData); -#if !wxCHECK_VERSION(2,7,0) - printerDialog.GetPrintDialogData().SetSetupDialog(true); -#endif //!wxCHECK_VERSION(2,7,0) - - if (printerDialog.ShowModal() != wxID_CANCEL) - { - *wxPlotPrintout::GetPrintData(true) = printerDialog.GetPrintDialogData().GetPrintData(); - return true; - } + wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); + wxPrintDialogData printDialogData(*wxPlotPrintout::GetPrintData(true)); + wxPrintDialog printerDialog(GetPlotCtrl(), &printDialogData); +#if !wxCHECK_VERSION(2, 7, 0) + printerDialog.GetPrintDialogData().SetSetupDialog(true); +#endif //! wxCHECK_VERSION(2,7,0) + + if (printerDialog.ShowModal() != wxID_CANCEL) { + *wxPlotPrintout::GetPrintData(true) = printerDialog.GetPrintDialogData().GetPrintData(); + return true; + } - return false; + return false; } bool wxPlotPrintout::ShowPrintPageSetupDialog() { - wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); - *wxPlotPrintout::GetPageSetupData(true) = *wxPlotPrintout::GetPrintData(); - wxPageSetupDialog pageSetupDialog(GetPlotCtrl(), wxPlotPrintout::GetPageSetupData()); - - if (pageSetupDialog.ShowModal() != wxID_CANCEL) - { - *wxPlotPrintout::GetPrintData(true) = pageSetupDialog.GetPageSetupData().GetPrintData(); - *wxPlotPrintout::GetPageSetupData(true) = pageSetupDialog.GetPageSetupData(); - return true; - } + wxCHECK_MSG(GetPlotCtrl(), false, wxT("Invalid plot window")); + *wxPlotPrintout::GetPageSetupData(true) = *wxPlotPrintout::GetPrintData(); + wxPageSetupDialog pageSetupDialog(GetPlotCtrl(), wxPlotPrintout::GetPageSetupData()); - return false; + if (pageSetupDialog.ShowModal() != wxID_CANCEL) { + *wxPlotPrintout::GetPrintData(true) = pageSetupDialog.GetPageSetupData().GetPrintData(); + *wxPlotPrintout::GetPageSetupData(true) = pageSetupDialog.GetPageSetupData(); + return true; + } + + return false; } //----------------------------------------------------------------------------- // wxPlotCtrlModule - setup anything after init and delete before closing //----------------------------------------------------------------------------- -class wxPlotCtrlModule : public wxModule -{ -DECLARE_DYNAMIC_CLASS(wxPlotCtrlModule) +class wxPlotCtrlModule : public wxModule { + DECLARE_DYNAMIC_CLASS(wxPlotCtrlModule) public: - wxPlotCtrlModule() : wxModule() {} - bool OnInit() - { - return true; - } - void OnExit() - { - wxPlotPrintout::SetPrintData(NULL, false); - wxPlotPrintout::SetPageSetupData(NULL, false); - } + wxPlotCtrlModule() : wxModule() {} + bool OnInit() { return true; } + void OnExit() + { + wxPlotPrintout::SetPrintData(NULL, false); + wxPlotPrintout::SetPageSetupData(NULL, false); + } }; IMPLEMENT_DYNAMIC_CLASS(wxPlotCtrlModule, wxModule) diff --git a/src/labenski/src/range.cpp b/src/labenski/src/range.cpp index c4aec4924..61132d26d 100644 --- a/src/labenski/src/range.cpp +++ b/src/labenski/src/range.cpp @@ -11,11 +11,11 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/utils.h" +#include "wx/utils.h" #endif // WX_PRECOMP #include "wx/wxthings/range.h" @@ -29,9 +29,8 @@ WX_DEFINE_OBJARRAY(wxArrayRangeDouble); WX_DEFINE_OBJARRAY(wxArrayRangeIntSelection); WX_DEFINE_OBJARRAY(wxArrayRangeDoubleSelection); - // set this if you want to double check that that ranges are really working -//#define CHECK_RANGES +// #define CHECK_RANGES //============================================================================= // wxRangeInt @@ -39,305 +38,342 @@ WX_DEFINE_OBJARRAY(wxArrayRangeDoubleSelection); bool wxRangeInt::Combine(int i, bool only_if_touching) { - if (only_if_touching) - { - if (i == m_min-1) { m_min--; return true; } - else if (i == m_max+1) { m_max++; return true; } + if (only_if_touching) { + if (i == m_min - 1) { + m_min--; + return true; } - else - { - if (i < m_min) { m_min = i; return true; } - else if (i > m_max) { m_max = i; return true; } + else if (i == m_max + 1) { + m_max++; + return true; } - return false; + } + else { + if (i < m_min) { + m_min = i; + return true; + } + else if (i > m_max) { + m_max = i; + return true; + } + } + return false; } -bool wxRangeInt::Combine( const wxRangeInt &r, bool only_if_touching ) +bool wxRangeInt::Combine(const wxRangeInt &r, bool only_if_touching) { - if (only_if_touching) - { - if (Touches(r)) - { - *this+=r; - return true; - } + if (only_if_touching) { + if (Touches(r)) { + *this += r; + return true; } - else - { - bool added = false; - if (r.m_min < m_min) { m_min = r.m_min; added = true; } - if (r.m_max > m_max) { m_max = r.m_max; added = true; } - return added; + } + else { + bool added = false; + if (r.m_min < m_min) { + m_min = r.m_min; + added = true; } - return false; + if (r.m_max > m_max) { + m_max = r.m_max; + added = true; + } + return added; + } + return false; } -bool wxRangeInt::Delete( const wxRangeInt &r, wxRangeInt *right ) +bool wxRangeInt::Delete(const wxRangeInt &r, wxRangeInt *right) { - if (!Contains(r)) - return false; - - if (right) *right = wxEmptyRangeInt; - - if (r.m_min <= m_min) - { - if (r.m_max >= m_max) - { - *this = wxEmptyRangeInt; - return true; - } + if (!Contains(r)) { + return false; + } - m_min = r.m_max + 1; - return true; - } + if (right) { + *right = wxEmptyRangeInt; + } - if (r.m_max >= m_max) - { - m_max = r.m_min - 1; - return true; + if (r.m_min <= m_min) { + if (r.m_max >= m_max) { + *this = wxEmptyRangeInt; + return true; } - if (right) - *right = wxRangeInt(r.m_max + 1, m_max); + m_min = r.m_max + 1; + return true; + } + if (r.m_max >= m_max) { m_max = r.m_min - 1; return true; + } + + if (right) { + *right = wxRangeInt(r.m_max + 1, m_max); + } + + m_max = r.m_min - 1; + return true; } //============================================================================= // wxRangeIntSelection //============================================================================= -const wxRangeInt& wxRangeIntSelection::GetRange( int index ) const +const wxRangeInt &wxRangeIntSelection::GetRange(int index) const { - wxCHECK_MSG((index>=0) && (index= 0) && (index < int(m_ranges.GetCount())), wxEmptyRangeInt, + wxT("Invalid index")); + return m_ranges[index]; } wxRangeInt wxRangeIntSelection::GetBoundingRange() const { - if (int(m_ranges.GetCount()) < 1) return wxEmptyRangeInt; - return wxRangeInt(m_ranges[0].m_min, m_ranges[m_ranges.GetCount()-1].m_max); + if (int(m_ranges.GetCount()) < 1) { + return wxEmptyRangeInt; + } + return wxRangeInt(m_ranges[0].m_min, m_ranges[m_ranges.GetCount() - 1].m_max); } -int wxRangeIntSelection::Index( int i ) const +int wxRangeIntSelection::Index(int i) const { - int count = m_ranges.GetCount(); - if (count < 1) return wxNOT_FOUND; + int count = m_ranges.GetCount(); + if (count < 1) { + return wxNOT_FOUND; + } - if (i < m_ranges[0].m_min) return wxNOT_FOUND; - if (i > m_ranges[count-1].m_max) return wxNOT_FOUND; + if (i < m_ranges[0].m_min) { + return wxNOT_FOUND; + } + if (i > m_ranges[count - 1].m_max) { + return wxNOT_FOUND; + } - // Binary search - int res, tmp, lo = 0, hi = count; + // Binary search + int res, tmp, lo = 0, hi = count; - while ( lo < hi ) - { - tmp = (lo + hi)/2; - res = m_ranges[tmp].Position(i); + while (lo < hi) { + tmp = (lo + hi) / 2; + res = m_ranges[tmp].Position(i); - if (res == 0) - return tmp; - else if ( res < 0 ) - hi = tmp; - else //if ( res > 0 ) - lo = tmp + 1; + if (res == 0) { + return tmp; + } + else if (res < 0) { + hi = tmp; } + else { // if ( res > 0 ) + lo = tmp + 1; + } + } - return wxNOT_FOUND; + return wxNOT_FOUND; } -int wxRangeIntSelection::Index( const wxRangeInt &r ) const +int wxRangeIntSelection::Index(const wxRangeInt &r) const { - int i, count = m_ranges.GetCount(); - for (i=0; i m_ranges[count-1].m_max) return count; - - // Binary search - int res, tmp, lo = 0, hi = count; - - while ( lo < hi ) - { - tmp = (lo + hi)/2; - res = m_ranges[tmp].Position(i); - - if ( res == 0 ) - return tmp; - else if ((i >= m_ranges[tmp].m_max) && (i < m_ranges[wxMin(tmp+1, count-1)].m_min)) - return tmp; - else if ( res < 0 ) - hi = tmp; - else //if ( res > 0 ) - lo = tmp + 1; + int count = m_ranges.GetCount(); + if (count < 1) { + return -1; + } + + if (i < m_ranges[0].m_min) { + return -1; + } + if (i > m_ranges[count - 1].m_max) { + return count; + } + + // Binary search + int res, tmp, lo = 0, hi = count; + + while (lo < hi) { + tmp = (lo + hi) / 2; + res = m_ranges[tmp].Position(i); + + if (res == 0) { + return tmp; + } + else if ((i >= m_ranges[tmp].m_max) && (i < m_ranges[wxMin(tmp + 1, count - 1)].m_min)) { + return tmp; } + else if (res < 0) { + hi = tmp; + } + else { // if ( res > 0 ) + lo = tmp + 1; + } + } - // oops shouldn't get here - wxCHECK_MSG(0, -1, wxT("Error calculating NearestIndex in wxRangeIntSelection")); + // oops shouldn't get here + wxCHECK_MSG(0, -1, wxT("Error calculating NearestIndex in wxRangeIntSelection")); } int wxRangeIntSelection::GetItemCount() const { - int i, items = 0, count = m_ranges.GetCount(); - for (i=0; i 0 ? NearestIndex(range.m_min) : -1; + bool done = false; + int i, count = m_ranges.GetCount(); + int nearest = count > 0 ? NearestIndex(range.m_min) : -1; - if ((nearest < 0) || (nearest == count)) - return false; + if ((nearest < 0) || (nearest == count)) { + return false; + } - wxRangeInt r; - for (i=nearest; i 0) ? i-1 : -1; - } - else if (!r.IsEmpty()) - m_ranges.Insert(r, i+1); - - done = true; - } - } - - return done; + wxRangeInt r; + for (i = nearest; i < int(m_ranges.GetCount()); i++) { + if (range.m_max < m_ranges[i].m_min) { + break; + } + else if (m_ranges[i].Delete(range, &r)) { + if (m_ranges[i].IsEmpty()) { + m_ranges.RemoveAt(i); + i = (i > 0) ? i - 1 : -1; + } + else if (!r.IsEmpty()) { + m_ranges.Insert(r, i + 1); + } + + done = true; + } + } + + return done; } bool wxRangeIntSelection::SelectRange(const wxRangeInt &range) { - wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Selection Range") ); + wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Selection Range")); - // Try to find a range that includes this one and combine it, else insert it, else append it - bool done = false; - int i, count = m_ranges.GetCount(); - int nearest = count > 0 ? NearestIndex(range.m_min) : -1; + // Try to find a range that includes this one and combine it, else insert it, else append it + bool done = false; + int i, count = m_ranges.GetCount(); + int nearest = count > 0 ? NearestIndex(range.m_min) : -1; - if (nearest < 0) - { - if (!((count > 0) && m_ranges[0].Combine(range, true))) - m_ranges.Insert(range, 0); - return true; + if (nearest < 0) { + if (!((count > 0) && m_ranges[0].Combine(range, true))) { + m_ranges.Insert(range, 0); } - else if (nearest == count) - { - if (!((count > 0) && m_ranges[count-1].Combine(range, true))) - m_ranges.Add(range); + return true; + } + else if (nearest == count) { + if (!((count > 0) && m_ranges[count - 1].Combine(range, true))) { + m_ranges.Add(range); + } + return true; + } + else { + if (m_ranges[nearest].Contains(range)) { + return false; + } + + for (i = nearest; i < count; i++) { + if (m_ranges[i].Combine(range, true)) { + done = true; + break; + } + else if (range.m_max < m_ranges[i].m_min) { + m_ranges.Insert(range, i); return true; + } } - else - { - if (m_ranges[nearest].Contains(range)) - return false; - - for (i=nearest; i= range.m_min) { + break; + } - for (i = 0; i < count; i++) + if (m_ranges[i].m_max < range.m_min) // range is out of bounds { - if (m_ranges[i].m_min >= range.m_min) - break; - - if (m_ranges[i].m_max < range.m_min) // range is out of bounds - { - done = true; - m_ranges.RemoveAt(i); - count--; - i--; - } - else - { - done = true; - m_ranges[i].m_min = range.m_min; - break; - } - } - - for (i = m_ranges.GetCount() - 1; i >= 0; i--) + done = true; + m_ranges.RemoveAt(i); + count--; + i--; + } + else { + done = true; + m_ranges[i].m_min = range.m_min; + break; + } + } + + for (i = m_ranges.GetCount() - 1; i >= 0; i--) { + if (m_ranges[i].m_max <= range.m_max) { + break; + } + + if (m_ranges[i].m_min > range.m_max) // range is out of bounds { - if (m_ranges[i].m_max <= range.m_max) - break; - - if (m_ranges[i].m_min > range.m_max) // range is out of bounds - { - done = true; - m_ranges.RemoveAt(i); - } - else - { - done = true; - m_ranges[i].m_max = range.m_max; - break; - } - } - - return done; + done = true; + m_ranges.RemoveAt(i); + } + else { + done = true; + m_ranges[i].m_max = range.m_max; + break; + } + } + + return done; } //============================================================================= @@ -346,292 +382,322 @@ bool wxRangeIntSelection::BoundRanges(const wxRangeInt& range) bool wxRangeDouble::Combine(wxDouble i) { - if (i < m_min) { m_min = i; return true; } - else if (i > m_max) { m_max = i; return true; } - return false; + if (i < m_min) { + m_min = i; + return true; + } + else if (i > m_max) { + m_max = i; + return true; + } + return false; } -bool wxRangeDouble::Combine( const wxRangeDouble &r, bool only_if_touching ) +bool wxRangeDouble::Combine(const wxRangeDouble &r, bool only_if_touching) { - if (only_if_touching) - { - if (Contains(r)) - { - *this+=r; - return true; - } + if (only_if_touching) { + if (Contains(r)) { + *this += r; + return true; } - else - { - bool added = false; - if (r.m_min < m_min) { m_min = r.m_min; added = true; } - if (r.m_max > m_max) { m_max = r.m_max; added = true; } - return added; + } + else { + bool added = false; + if (r.m_min < m_min) { + m_min = r.m_min; + added = true; } - return false; + if (r.m_max > m_max) { + m_max = r.m_max; + added = true; + } + return added; + } + return false; } -bool wxRangeDouble::Delete( const wxRangeDouble &r, wxRangeDouble *right ) +bool wxRangeDouble::Delete(const wxRangeDouble &r, wxRangeDouble *right) { - if (!Contains(r)) - return false; - - if (right) *right = wxEmptyRangeDouble; - - if (r.m_min <= m_min) - { - if (r.m_max >= m_max) - { - *this = wxEmptyRangeDouble; - return true; - } + if (!Contains(r)) { + return false; + } - m_min = r.m_max; - return true; - } + if (right) { + *right = wxEmptyRangeDouble; + } - if (r.m_max >= m_max) - { - m_max = r.m_min; - return true; + if (r.m_min <= m_min) { + if (r.m_max >= m_max) { + *this = wxEmptyRangeDouble; + return true; } - if (right) - *right = wxRangeDouble(r.m_max, m_max); + m_min = r.m_max; + return true; + } + if (r.m_max >= m_max) { m_max = r.m_min; return true; + } + + if (right) { + *right = wxRangeDouble(r.m_max, m_max); + } + + m_max = r.m_min; + return true; } //============================================================================= // wxRangeDoubleSelection //============================================================================= -const wxRangeDouble& wxRangeDoubleSelection::GetRange( int index ) const +const wxRangeDouble &wxRangeDoubleSelection::GetRange(int index) const { - wxCHECK_MSG((index>=0) && (index= 0) && (index < int(m_ranges.GetCount())), wxEmptyRangeDouble, + wxT("Invalid index")); + return m_ranges[index]; } wxRangeDouble wxRangeDoubleSelection::GetBoundingRange() const { - if (int(m_ranges.GetCount()) < 1) return wxEmptyRangeDouble; - return wxRangeDouble(m_ranges[0].m_min, m_ranges[m_ranges.GetCount()-1].m_max); + if (int(m_ranges.GetCount()) < 1) { + return wxEmptyRangeDouble; + } + return wxRangeDouble(m_ranges[0].m_min, m_ranges[m_ranges.GetCount() - 1].m_max); } -int wxRangeDoubleSelection::Index( wxDouble i ) const +int wxRangeDoubleSelection::Index(wxDouble i) const { - int count = m_ranges.GetCount(); - if (count < 1) return wxNOT_FOUND; + int count = m_ranges.GetCount(); + if (count < 1) { + return wxNOT_FOUND; + } - if (i < m_ranges[0].m_min) return wxNOT_FOUND; - if (i > m_ranges[count-1].m_max) return wxNOT_FOUND; + if (i < m_ranges[0].m_min) { + return wxNOT_FOUND; + } + if (i > m_ranges[count - 1].m_max) { + return wxNOT_FOUND; + } - // Binary search - int res, tmp, lo = 0, hi = count; + // Binary search + int res, tmp, lo = 0, hi = count; - while ( lo < hi ) - { - tmp = (lo + hi)/2; - res = m_ranges[tmp].Position(i); + while (lo < hi) { + tmp = (lo + hi) / 2; + res = m_ranges[tmp].Position(i); - if ( res == 0 ) - return tmp; - else if ( res < 0 ) - hi = tmp; - else //if ( res > 0 ) - lo = tmp + 1; + if (res == 0) { + return tmp; + } + else if (res < 0) { + hi = tmp; } + else { // if ( res > 0 ) + lo = tmp + 1; + } + } - return wxNOT_FOUND; + return wxNOT_FOUND; -/* - for (int j=0; j m_ranges[count-1].m_max) return count; - - // Binary search - int res, tmp, lo = 0, hi = count; - - while ( lo < hi ) - { - tmp = (lo + hi)/2; - res = m_ranges[tmp].Position(i); - - if ( res == 0 ) - return tmp; - else if ((i >= m_ranges[tmp].m_max) && (i < m_ranges[wxMin(tmp+1, count-1)].m_min)) - return tmp; - else if ( res < 0 ) - hi = tmp; - else //if ( res > 0 ) - lo = tmp + 1; + int count = m_ranges.GetCount(); + if (count < 1) { + return -1; + } + + if (i < m_ranges[0].m_min) { + return -1; + } + if (i > m_ranges[count - 1].m_max) { + return count; + } + + // Binary search + int res, tmp, lo = 0, hi = count; + + while (lo < hi) { + tmp = (lo + hi) / 2; + res = m_ranges[tmp].Position(i); + + if (res == 0) { + return tmp; + } + else if ((i >= m_ranges[tmp].m_max) && (i < m_ranges[wxMin(tmp + 1, count - 1)].m_min)) { + return tmp; } + else if (res < 0) { + hi = tmp; + } + else { // if ( res > 0 ) + lo = tmp + 1; + } + } - // oops shouldn't get here - wxCHECK_MSG(0, -1, wxT("Error calculating NearestIndex in wxRangeDoubleSelection")); + // oops shouldn't get here + wxCHECK_MSG(0, -1, wxT("Error calculating NearestIndex in wxRangeDoubleSelection")); } bool wxRangeDoubleSelection::SelectRange(const wxRangeDouble &range) { - wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Selection Range") ); + wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Selection Range")); - // Try to find a range that includes this one and combine it, else insert it, else append it - bool done = false; - int i, count = m_ranges.GetCount(); - int nearest = count > 0 ? NearestIndex(range.m_min) : -1; + // Try to find a range that includes this one and combine it, else insert it, else append it + bool done = false; + int i, count = m_ranges.GetCount(); + int nearest = count > 0 ? NearestIndex(range.m_min) : -1; - if (nearest < 0) - { - if (!((count > 0) && m_ranges[0].Combine(range, true))) - m_ranges.Insert(range, 0); - return true; + if (nearest < 0) { + if (!((count > 0) && m_ranges[0].Combine(range, true))) { + m_ranges.Insert(range, 0); } - else if (nearest == count) - { - if (!((count > 0) && m_ranges[count-1].Combine(range, true))) - m_ranges.Add(range); + return true; + } + else if (nearest == count) { + if (!((count > 0) && m_ranges[count - 1].Combine(range, true))) { + m_ranges.Add(range); + } + return true; + } + else { + if (m_ranges[nearest].Contains(range)) { + return false; + } + + for (i = nearest; i < count; i++) { + if (m_ranges[i].Combine(range, true)) { + done = true; + break; + } + else if (range.m_max < m_ranges[i].m_min) { + m_ranges.Insert(range, i); return true; + } } - else - { - if (m_ranges[nearest].Contains(range)) - return false; - - for (i=nearest; i 0 ? NearestIndex(range.m_min) : -1; + bool done = false; + int i, count = m_ranges.GetCount(); + int nearest = count > 0 ? NearestIndex(range.m_min) : -1; - if ((nearest < 0) || (nearest == count)) - return false; + if ((nearest < 0) || (nearest == count)) { + return false; + } - wxRangeDouble r; - for (i=nearest; i 0) ? i-1 : -1; - } - else if (!r.IsEmpty()) - m_ranges.Insert(r, i+1); - - done = true; - } - } - - return done; + wxRangeDouble r; + for (i = nearest; i < int(m_ranges.GetCount()); i++) { + if (range.m_max < m_ranges[i].m_min) { + break; + } + else if (m_ranges[i].Delete(range, &r)) { + if (m_ranges[i].IsEmpty()) { + m_ranges.RemoveAt(i); + i = (i > 0) ? i - 1 : -1; + } + else if (!r.IsEmpty()) { + m_ranges.Insert(r, i + 1); + } + + done = true; + } + } + + return done; } -bool wxRangeDoubleSelection::BoundRanges(const wxRangeDouble& range) +bool wxRangeDoubleSelection::BoundRanges(const wxRangeDouble &range) { - wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Bounding Range") ); - int i, count = m_ranges.GetCount(); - bool done = false; + wxCHECK_MSG(!range.IsEmpty(), false, wxT("Invalid Bounding Range")); + int i, count = m_ranges.GetCount(); + bool done = false; + + for (i = 0; i < count; i++) { + if (m_ranges[i].m_min >= range.m_min) { + break; + } - for (i = 0; i < count; i++) + if (m_ranges[i].m_max < range.m_min) // range is out of bounds { - if (m_ranges[i].m_min >= range.m_min) - break; - - if (m_ranges[i].m_max < range.m_min) // range is out of bounds - { - done = true; - m_ranges.RemoveAt(i); - count--; - i--; - } - else - { - done = true; - m_ranges[i].m_min = range.m_min; - break; - } - } - - for (i = m_ranges.GetCount() - 1; i >= 0; i--) + done = true; + m_ranges.RemoveAt(i); + count--; + i--; + } + else { + done = true; + m_ranges[i].m_min = range.m_min; + break; + } + } + + for (i = m_ranges.GetCount() - 1; i >= 0; i--) { + if (m_ranges[i].m_max <= range.m_max) { + break; + } + + if (m_ranges[i].m_min > range.m_max) // range is out of bounds { - if (m_ranges[i].m_max <= range.m_max) - break; - - if (m_ranges[i].m_min > range.m_max) // range is out of bounds - { - done = true; - m_ranges.RemoveAt(i); - } - else - { - done = true; - m_ranges[i].m_max = range.m_max; - break; - } - } - - return done; + done = true; + m_ranges.RemoveAt(i); + } + else { + done = true; + m_ranges[i].m_max = range.m_max; + break; + } + } + + return done; } diff --git a/src/labenski/src/sheet.cpp b/src/labenski/src/sheet.cpp index b9414be54..c97c4d493 100644 --- a/src/labenski/src/sheet.cpp +++ b/src/labenski/src/sheet.cpp @@ -23,15 +23,15 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/defs.h" - #include "wx/utils.h" - #include "wx/dcclient.h" - #include "wx/settings.h" - #include "wx/log.h" +#include "wx/defs.h" +#include "wx/utils.h" +#include "wx/dcclient.h" +#include "wx/settings.h" +#include "wx/log.h" #endif // WX_PRECOMP #include "wx/sheet/sheet.h" @@ -40,28 +40,31 @@ #include "wx/timer.h" #include "wx/clipbrd.h" -#include "wx/crt.h" // for wxPrintf() +#include "wx/crt.h" // for wxPrintf() - -#define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); -#define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_BLOCK(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_RECT(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); #define SPLIT_BUTTON_WIDTH 6 #define wxStrF wxString::Format #ifndef wxSL_INVERSE // !wxCHECK_VERSION(2,5,3) // FIXME temp fix until 2.5.4 - #define SetOwnBackgroundColour SetBackgroundColour - #define SetOwnForegroundColour SetForegroundColour +#define SetOwnBackgroundColour SetBackgroundColour +#define SetOwnForegroundColour SetForegroundColour #endif #ifdef __wxGTK__ - //#define USE_RENDERNATIVE 1 +// #define USE_RENDERNATIVE 1 #endif // __wxGTK__ -static inline bool wxRectIsEmpty(const wxRect& rect) +static inline bool wxRectIsEmpty(const wxRect &rect) { - return (rect.width < 1) || (rect.height < 1); + return (rect.width < 1) || (rect.height < 1); } // ---------------------------------------------------------------------------- @@ -71,17 +74,17 @@ static inline bool wxRectIsEmpty(const wxRect& rect) // Gambit modification for custom border drawing #define WXSHEET_DRAW_LINES 0 #ifndef WXSHEET_DRAW_LINES - #define WXSHEET_DRAW_LINES 1 +#define WXSHEET_DRAW_LINES 1 #endif // ---------------------------------------------------------------------------- // globals // ---------------------------------------------------------------------------- -//#define DEBUG_ATTR_CACHE +// #define DEBUG_ATTR_CACHE #ifdef DEBUG_ATTR_CACHE - static size_t gs_nAttrCacheHits = 0; - static size_t gs_nAttrCacheMisses = 0; +static size_t gs_nAttrCacheHits = 0; +static size_t gs_nAttrCacheMisses = 0; #endif // DEBUG_ATTR_CACHE // ---------------------------------------------------------------------------- @@ -100,249 +103,248 @@ static inline bool wxRectIsEmpty(const wxRect& rect) // Well, it's still seriously broken so it might be better but needs // fixing anyhow // -- Vadim -#define SHEET_SCROLL_LINE_X 15 // 1 +#define SHEET_SCROLL_LINE_X 15 // 1 #define SHEET_SCROLL_LINE_Y SHEET_SCROLL_LINE_X // ---------------------------------------------------------------------------- // wxSheetDataTypeInfo: for the data type registry // ---------------------------------------------------------------------------- -class wxSheetDataTypeInfo -{ +class wxSheetDataTypeInfo { public: - wxSheetDataTypeInfo(const wxString& typeName, - const wxSheetCellRenderer& renderer, - const wxSheetCellEditor& editor) - : m_typeName(typeName), m_renderer(renderer), m_editor(editor) {} - - wxString m_typeName; - wxSheetCellRenderer m_renderer; - wxSheetCellEditor m_editor; + wxSheetDataTypeInfo(const wxString &typeName, const wxSheetCellRenderer &renderer, + const wxSheetCellEditor &editor) + : m_typeName(typeName), m_renderer(renderer), m_editor(editor) + { + } + + wxString m_typeName; + wxSheetCellRenderer m_renderer; + wxSheetCellEditor m_editor; }; // ---------------------------------------------------------------------------- // wxSheetTypeRegistry // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_SHEET wxSheetTypeRegistry -{ +class WXDLLIMPEXP_SHEET wxSheetTypeRegistry { public: - wxSheetTypeRegistry() {} - virtual ~wxSheetTypeRegistry(); + wxSheetTypeRegistry() {} + virtual ~wxSheetTypeRegistry(); - // register a new data type returning position - int RegisterDataType(const wxString& typeName, - const wxSheetCellRenderer& renderer, - const wxSheetCellEditor& editor); + // register a new data type returning position + int RegisterDataType(const wxString &typeName, const wxSheetCellRenderer &renderer, + const wxSheetCellEditor &editor); - // find one of already registered data types - int FindRegisteredDataType(const wxString& typeName); + // find one of already registered data types + int FindRegisteredDataType(const wxString &typeName); - // try to FindRegisteredDataType(), if this fails and typeName is one of - // standard typenames, register it and return its index - int FindDataType(const wxString& typeName); + // try to FindRegisteredDataType(), if this fails and typeName is one of + // standard typenames, register it and return its index + int FindDataType(const wxString &typeName); - // try to FindDataType(), if it fails, see if it is not one of already - // registered data types with some params in which case clone the - // registered data type and set params for it - int FindOrCloneDataType(const wxString& typeName); + // try to FindDataType(), if it fails, see if it is not one of already + // registered data types with some params in which case clone the + // registered data type and set params for it + int FindOrCloneDataType(const wxString &typeName); - const wxSheetCellRenderer& GetRenderer(int index); - const wxSheetCellEditor& GetEditor(int index); + const wxSheetCellRenderer &GetRenderer(int index); + const wxSheetCellEditor &GetEditor(int index); private: - wxArrayPtrVoid m_typeInfo; + wxArrayPtrVoid m_typeInfo; }; wxSheetTypeRegistry::~wxSheetTypeRegistry() { - size_t i, count = m_typeInfo.Count(); - for ( i = 0; i < count; i++ ) - delete (wxSheetDataTypeInfo*)m_typeInfo[i]; + size_t i, count = m_typeInfo.Count(); + for (i = 0; i < count; i++) { + delete (wxSheetDataTypeInfo *)m_typeInfo[i]; + } } -int wxSheetTypeRegistry::RegisterDataType(const wxString& typeName, - const wxSheetCellRenderer& renderer, - const wxSheetCellEditor& editor) +int wxSheetTypeRegistry::RegisterDataType(const wxString &typeName, + const wxSheetCellRenderer &renderer, + const wxSheetCellEditor &editor) { - wxSheetDataTypeInfo* info = new wxSheetDataTypeInfo(typeName, renderer, editor); + wxSheetDataTypeInfo *info = new wxSheetDataTypeInfo(typeName, renderer, editor); - // is it already registered? - int index = FindRegisteredDataType(typeName); - if ( index != wxNOT_FOUND ) - { - wxSheetDataTypeInfo *oldInfo = (wxSheetDataTypeInfo*)m_typeInfo[index]; - delete oldInfo; - m_typeInfo[index] = info; - return index; - } + // is it already registered? + int index = FindRegisteredDataType(typeName); + if (index != wxNOT_FOUND) { + wxSheetDataTypeInfo *oldInfo = (wxSheetDataTypeInfo *)m_typeInfo[index]; + delete oldInfo; + m_typeInfo[index] = info; + return index; + } - m_typeInfo.Add(info); - return m_typeInfo.GetCount() - 1; + m_typeInfo.Add(info); + return m_typeInfo.GetCount() - 1; } -int wxSheetTypeRegistry::FindRegisteredDataType(const wxString& typeName) +int wxSheetTypeRegistry::FindRegisteredDataType(const wxString &typeName) { - if (typeName.IsEmpty()) - return wxNOT_FOUND; + if (typeName.IsEmpty()) { + return wxNOT_FOUND; + } - size_t i, count = m_typeInfo.GetCount(); - for ( i = 0; i < count; i++ ) - { - if (typeName == ((wxSheetDataTypeInfo*)m_typeInfo[i])->m_typeName) - return i; + size_t i, count = m_typeInfo.GetCount(); + for (i = 0; i < count; i++) { + if (typeName == ((wxSheetDataTypeInfo *)m_typeInfo[i])->m_typeName) { + return i; } + } - return wxNOT_FOUND; + return wxNOT_FOUND; } -int wxSheetTypeRegistry::FindDataType(const wxString& typeName) +int wxSheetTypeRegistry::FindDataType(const wxString &typeName) { - int index = FindRegisteredDataType(typeName); - if (index != wxNOT_FOUND) - return index; + int index = FindRegisteredDataType(typeName); + if (index != wxNOT_FOUND) { + return index; + } - // if one of the standard ones, register it "on the fly" + // if one of the standard ones, register it "on the fly" #if wxUSE_TEXTCTRL - if ( typeName == wxSHEET_VALUE_STRING ) - { - wxSheetCellRenderer renderer(new wxSheetCellStringRendererRefData()); - wxSheetCellEditor editor(new wxSheetCellTextEditorRefData()); - return RegisterDataType(wxSHEET_VALUE_STRING, renderer, editor); - } - else if ( typeName == wxSHEET_VALUE_NUMBER ) - { - wxSheetCellRenderer renderer(new wxSheetCellNumberRendererRefData()); - wxSheetCellEditor editor(new wxSheetCellNumberEditorRefData()); - return RegisterDataType(wxSHEET_VALUE_NUMBER, renderer, editor); - } - else if ( typeName == wxSHEET_VALUE_FLOAT ) - { - wxSheetCellRenderer renderer(new wxSheetCellFloatRendererRefData()); - wxSheetCellEditor editor(new wxSheetCellFloatEditorRefData()); - return RegisterDataType(wxSHEET_VALUE_FLOAT, renderer, editor); - } - else if ( typeName == wxSHEET_VALUE_LABEL ) - { - wxSheetCellRenderer renderer(new wxSheetCellRolColLabelRendererRefData()); - wxSheetCellEditor editor(new wxSheetCellTextEditorRefData()); - return RegisterDataType(wxSHEET_VALUE_LABEL, renderer, editor); - } + if (typeName == wxSHEET_VALUE_STRING) { + wxSheetCellRenderer renderer(new wxSheetCellStringRendererRefData()); + wxSheetCellEditor editor(new wxSheetCellTextEditorRefData()); + return RegisterDataType(wxSHEET_VALUE_STRING, renderer, editor); + } + else if (typeName == wxSHEET_VALUE_NUMBER) { + wxSheetCellRenderer renderer(new wxSheetCellNumberRendererRefData()); + wxSheetCellEditor editor(new wxSheetCellNumberEditorRefData()); + return RegisterDataType(wxSHEET_VALUE_NUMBER, renderer, editor); + } + else if (typeName == wxSHEET_VALUE_FLOAT) { + wxSheetCellRenderer renderer(new wxSheetCellFloatRendererRefData()); + wxSheetCellEditor editor(new wxSheetCellFloatEditorRefData()); + return RegisterDataType(wxSHEET_VALUE_FLOAT, renderer, editor); + } + else if (typeName == wxSHEET_VALUE_LABEL) { + wxSheetCellRenderer renderer(new wxSheetCellRolColLabelRendererRefData()); + wxSheetCellEditor editor(new wxSheetCellTextEditorRefData()); + return RegisterDataType(wxSHEET_VALUE_LABEL, renderer, editor); + } #endif // wxUSE_TEXTCTRL #if wxUSE_CHECKBOX - else if ( typeName == wxSHEET_VALUE_BOOL ) - { - wxSheetCellRenderer renderer(new wxSheetCellBoolRendererRefData()); - wxSheetCellEditor editor(new wxSheetCellBoolEditorRefData()); - return RegisterDataType(wxSHEET_VALUE_BOOL, renderer, editor); - } + else if (typeName == wxSHEET_VALUE_BOOL) { + wxSheetCellRenderer renderer(new wxSheetCellBoolRendererRefData()); + wxSheetCellEditor editor(new wxSheetCellBoolEditorRefData()); + return RegisterDataType(wxSHEET_VALUE_BOOL, renderer, editor); + } #endif // wxUSE_CHECKBOX #if wxUSE_COMBOBOX - else if ( typeName == wxSHEET_VALUE_CHOICE ) - { - wxSheetCellRenderer renderer(new wxSheetCellStringRendererRefData()); - wxSheetCellEditor editor(new wxSheetCellChoiceEditorRefData()); - return RegisterDataType(wxSHEET_VALUE_CHOICE, renderer, editor); - } + else if (typeName == wxSHEET_VALUE_CHOICE) { + wxSheetCellRenderer renderer(new wxSheetCellStringRendererRefData()); + wxSheetCellEditor editor(new wxSheetCellChoiceEditorRefData()); + return RegisterDataType(wxSHEET_VALUE_CHOICE, renderer, editor); + } #endif // wxUSE_COMBOBOX - return wxNOT_FOUND; + return wxNOT_FOUND; } -int wxSheetTypeRegistry::FindOrCloneDataType(const wxString& typeName) +int wxSheetTypeRegistry::FindOrCloneDataType(const wxString &typeName) { - if (typeName.IsEmpty()) - return wxNOT_FOUND; - int index = FindDataType(typeName); - if ( index != wxNOT_FOUND ) - return index; - - // the first part of the typename is the "real" type, anything after ':' - // are the parameters for the renderer - index = FindDataType(typeName.BeforeFirst(_T(':'))); - if ( index == wxNOT_FOUND ) - return wxNOT_FOUND; + if (typeName.IsEmpty()) { + return wxNOT_FOUND; + } + int index = FindDataType(typeName); + if (index != wxNOT_FOUND) { + return index; + } + + // the first part of the typename is the "real" type, anything after ':' + // are the parameters for the renderer + index = FindDataType(typeName.BeforeFirst(_T(':'))); + if (index == wxNOT_FOUND) { + return wxNOT_FOUND; + } - wxSheetCellRenderer renderer(GetRenderer(index).Clone()); - wxSheetCellEditor editor(GetEditor(index).Clone()); + wxSheetCellRenderer renderer(GetRenderer(index).Clone()); + wxSheetCellEditor editor(GetEditor(index).Clone()); - // do it even if there are no parameters to reset them to defaults - wxString params = typeName.AfterFirst(_T(':')); - renderer.SetParameters(params); - editor.SetParameters(params); + // do it even if there are no parameters to reset them to defaults + wxString params = typeName.AfterFirst(_T(':')); + renderer.SetParameters(params); + editor.SetParameters(params); - return RegisterDataType(typeName, renderer, editor); + return RegisterDataType(typeName, renderer, editor); } -const wxSheetCellRenderer& wxSheetTypeRegistry::GetRenderer(int index) +const wxSheetCellRenderer &wxSheetTypeRegistry::GetRenderer(int index) { - wxCHECK_MSG((index >= 0) && (index < int(m_typeInfo.GetCount())), wxNullSheetCellRenderer, - wxT("Invalid index in wxSheetTypeRegistry::GetRenderer")); - return ((wxSheetDataTypeInfo*)m_typeInfo[index])->m_renderer; + wxCHECK_MSG((index >= 0) && (index < int(m_typeInfo.GetCount())), wxNullSheetCellRenderer, + wxT("Invalid index in wxSheetTypeRegistry::GetRenderer")); + return ((wxSheetDataTypeInfo *)m_typeInfo[index])->m_renderer; } -const wxSheetCellEditor& wxSheetTypeRegistry::GetEditor(int index) +const wxSheetCellEditor &wxSheetTypeRegistry::GetEditor(int index) { - wxCHECK_MSG((index >= 0) && (index < int(m_typeInfo.GetCount())), wxNullSheetCellEditor, - wxT("Invalid index in wxSheetTypeRegistry::GetEditor")); - return ((wxSheetDataTypeInfo*)m_typeInfo[index])->m_editor; + wxCHECK_MSG((index >= 0) && (index < int(m_typeInfo.GetCount())), wxNullSheetCellEditor, + wxT("Invalid index in wxSheetTypeRegistry::GetEditor")); + return ((wxSheetDataTypeInfo *)m_typeInfo[index])->m_editor; } // ---------------------------------------------------------------------------- // wxSheetChildWindow // ---------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS( wxSheetChildWindow, wxWindow ) - -BEGIN_EVENT_TABLE( wxSheetChildWindow, wxWindow ) - EVT_PAINT ( wxSheetChildWindow::OnPaint ) - EVT_MOUSEWHEEL ( wxSheetChildWindow::OnMouse ) - EVT_MOUSE_EVENTS ( wxSheetChildWindow::OnMouse ) - EVT_KEY_DOWN ( wxSheetChildWindow::OnKeyAndChar ) - EVT_KEY_UP ( wxSheetChildWindow::OnKeyAndChar ) - EVT_CHAR ( wxSheetChildWindow::OnKeyAndChar ) - EVT_SET_FOCUS ( wxSheetChildWindow::OnFocus ) - EVT_KILL_FOCUS ( wxSheetChildWindow::OnFocus ) +IMPLEMENT_ABSTRACT_CLASS(wxSheetChildWindow, wxWindow) + +BEGIN_EVENT_TABLE(wxSheetChildWindow, wxWindow) +EVT_PAINT(wxSheetChildWindow::OnPaint) +EVT_MOUSEWHEEL(wxSheetChildWindow::OnMouse) +EVT_MOUSE_EVENTS(wxSheetChildWindow::OnMouse) +EVT_KEY_DOWN(wxSheetChildWindow::OnKeyAndChar) +EVT_KEY_UP(wxSheetChildWindow::OnKeyAndChar) +EVT_CHAR(wxSheetChildWindow::OnKeyAndChar) +EVT_SET_FOCUS(wxSheetChildWindow::OnFocus) +EVT_KILL_FOCUS(wxSheetChildWindow::OnFocus) END_EVENT_TABLE() -wxSheetChildWindow::wxSheetChildWindow( wxSheet *parent, wxWindowID id, - const wxPoint &pos, const wxSize &size, - long style, const wxString& name ) - :wxWindow( parent, id, pos, size, style, name ), - m_owner(parent), m_mouseCursor(wxSheet::WXSHEET_CURSOR_SELECT_CELL) +wxSheetChildWindow::wxSheetChildWindow(wxSheet *parent, wxWindowID id, const wxPoint &pos, + const wxSize &size, long style, const wxString &name) + : wxWindow(parent, id, pos, size, style, name), m_owner(parent), + m_mouseCursor(wxSheet::WXSHEET_CURSOR_SELECT_CELL) { } -void wxSheetChildWindow::OnPaint( wxPaintEvent& event ) +void wxSheetChildWindow::OnPaint(wxPaintEvent &event) { - if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) - { - wxPaintDC dc(this); // MSW at least requires this - } + if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) { + wxPaintDC dc(this); // MSW at least requires this + } } -void wxSheetChildWindow::OnMouse( wxMouseEvent& event ) +void wxSheetChildWindow::OnMouse(wxMouseEvent &event) { - if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) - event.Skip(); + if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) { + event.Skip(); + } } // This seems to be required for wxMotif otherwise the mouse // cursor must be in the cell edit control to get key events -void wxSheetChildWindow::OnKeyAndChar( wxKeyEvent& event ) +void wxSheetChildWindow::OnKeyAndChar(wxKeyEvent &event) { - if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) - event.Skip(); + if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) { + event.Skip(); + } } -void wxSheetChildWindow::OnFocus( wxFocusEvent& event ) +void wxSheetChildWindow::OnFocus(wxFocusEvent &event) { - if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) - event.Skip(); + if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) { + event.Skip(); + } } -void wxSheetChildWindow::OnEraseBackground( wxEraseEvent& event) +void wxSheetChildWindow::OnEraseBackground(wxEraseEvent &event) { - if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) - event.Skip(false); + if (!m_owner || !m_owner->GetEventHandler()->ProcessEvent(event)) { + event.Skip(false); + } } //----------------------------------------------------------------------------- @@ -350,77 +352,77 @@ void wxSheetChildWindow::OnEraseBackground( wxEraseEvent& event) //----------------------------------------------------------------------------- wxSheetRefData::wxSheetRefData() { - m_table = NULL; - m_ownTable = false; + m_table = NULL; + m_ownTable = false; - m_typeRegistry = new wxSheetTypeRegistry; + m_typeRegistry = new wxSheetTypeRegistry; - m_rowEdges.SetDefaultSize(WXSHEET_DEFAULT_ROW_HEIGHT); - m_colEdges.SetDefaultSize(WXSHEET_DEFAULT_COL_WIDTH); - m_rowEdges.SetMinAllowedSize(WXSHEET_MIN_ROW_HEIGHT); - m_colEdges.SetMinAllowedSize(WXSHEET_MIN_COL_WIDTH); + m_rowEdges.SetDefaultSize(WXSHEET_DEFAULT_ROW_HEIGHT); + m_colEdges.SetDefaultSize(WXSHEET_DEFAULT_COL_WIDTH); + m_rowEdges.SetMinAllowedSize(WXSHEET_MIN_ROW_HEIGHT); + m_colEdges.SetMinAllowedSize(WXSHEET_MIN_COL_WIDTH); - m_rowLabelWidth = WXSHEET_DEFAULT_ROW_LABEL_WIDTH; - m_colLabelHeight = WXSHEET_DEFAULT_COL_LABEL_HEIGHT; + m_rowLabelWidth = WXSHEET_DEFAULT_ROW_LABEL_WIDTH; + m_colLabelHeight = WXSHEET_DEFAULT_COL_LABEL_HEIGHT; - m_equal_col_widths = 0; + m_equal_col_widths = 0; - m_gridLineColour = wxColour( 192, 192, 192 ); - m_gridLinesEnabled = wxBOTH; - m_cursorCellHighlightColour = *wxBLACK; - m_cursorCellHighlightPenWidth = 2; - m_cursorCellHighlightROPenWidth = 1; - m_labelOutlineColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW); + m_gridLineColour = wxColour(192, 192, 192); + m_gridLinesEnabled = wxBOTH; + m_cursorCellHighlightColour = *wxBLACK; + m_cursorCellHighlightPenWidth = 2; + m_cursorCellHighlightROPenWidth = 1; + m_labelOutlineColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW); - m_rowResizeCursor = wxCursor( wxCURSOR_SIZENS ); - m_colResizeCursor = wxCursor( wxCURSOR_SIZEWE ); + m_rowResizeCursor = wxCursor(wxCURSOR_SIZENS); + m_colResizeCursor = wxCursor(wxCURSOR_SIZEWE); - m_editable = true; // default for whole grid + m_editable = true; // default for whole grid - m_canDrag = wxSHEET_DragCellSize; + m_canDrag = wxSHEET_DragCellSize; - m_cursorCoords = wxNullSheetCoords; + m_cursorCoords = wxNullSheetCoords; - m_selectingAnchor = wxNullSheetCoords; - m_selectionMode = wxSHEET_SelectCells; - m_selection = new wxSheetSelection; - m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); - m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + m_selectingAnchor = wxNullSheetCoords; + m_selectionMode = wxSHEET_SelectCells; + m_selection = new wxSheetSelection; + m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); + m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); - m_cellEditorCoords = wxNullSheetCoords; + m_cellEditorCoords = wxNullSheetCoords; - m_pasting = false; + m_pasting = false; } wxSheetRefData::~wxSheetRefData() { - if (m_ownTable && m_table) - delete m_table; + if (m_ownTable && m_table) { + delete m_table; + } - delete m_typeRegistry; - delete m_selection; + delete m_typeRegistry; + delete m_selection; } -int wxSheetRefData::FindSheet(wxSheet* sheet) const +int wxSheetRefData::FindSheet(wxSheet *sheet) const { return m_sheets.Index(sheet); } +void wxSheetRefData::AddSheet(wxSheet *sheet) { - return m_sheets.Index(sheet); -} -void wxSheetRefData::AddSheet(wxSheet* sheet) -{ - wxCHECK_RET(sheet, wxT("Invalid sheet")); + wxCHECK_RET(sheet, wxT("Invalid sheet")); - // not an error, just let them do it to avoid having to check - if (!HasSheet(sheet)) - m_sheets.Add(sheet); + // not an error, just let them do it to avoid having to check + if (!HasSheet(sheet)) { + m_sheets.Add(sheet); + } } -void wxSheetRefData::RemoveSheet(wxSheet* sheet) +void wxSheetRefData::RemoveSheet(wxSheet *sheet) { - wxCHECK_RET(sheet, wxT("Invalid sheet")); + wxCHECK_RET(sheet, wxT("Invalid sheet")); - // not an error, if not found allows for this to be called in destructor - const int index = FindSheet(sheet); - if (index != wxNOT_FOUND) - m_sheets.RemoveAt(index); + // not an error, if not found allows for this to be called in destructor + const int index = FindSheet(sheet); + if (index != wxNOT_FOUND) { + m_sheets.RemoveAt(index); + } } //----------------------------------------------------------------------------- @@ -428,110 +430,98 @@ void wxSheetRefData::RemoveSheet(wxSheet* sheet) //----------------------------------------------------------------------------- #if wxUSE_EXTENDED_RTTI -WX_DEFINE_FLAGS( wxSheetStyle ) +WX_DEFINE_FLAGS(wxSheetStyle) -wxBEGIN_FLAGS( wxSheetStyle ) +wxBEGIN_FLAGS(wxSheetStyle) // new style border flags, we put them first to // use them for streaming out - wxFLAGS_MEMBER(wxBORDER_SIMPLE) - wxFLAGS_MEMBER(wxBORDER_SUNKEN) - wxFLAGS_MEMBER(wxBORDER_DOUBLE) - wxFLAGS_MEMBER(wxBORDER_RAISED) - wxFLAGS_MEMBER(wxBORDER_STATIC) - wxFLAGS_MEMBER(wxBORDER_NONE) + wxFLAGS_MEMBER(wxBORDER_SIMPLE) wxFLAGS_MEMBER(wxBORDER_SUNKEN) wxFLAGS_MEMBER(wxBORDER_DOUBLE) + wxFLAGS_MEMBER(wxBORDER_RAISED) wxFLAGS_MEMBER(wxBORDER_STATIC) + wxFLAGS_MEMBER(wxBORDER_NONE) // old style border flags - wxFLAGS_MEMBER(wxSIMPLE_BORDER) - wxFLAGS_MEMBER(wxSUNKEN_BORDER) - wxFLAGS_MEMBER(wxDOUBLE_BORDER) - wxFLAGS_MEMBER(wxRAISED_BORDER) - wxFLAGS_MEMBER(wxSTATIC_BORDER) - wxFLAGS_MEMBER(wxBORDER) + wxFLAGS_MEMBER(wxSIMPLE_BORDER) wxFLAGS_MEMBER(wxSUNKEN_BORDER) wxFLAGS_MEMBER(wxDOUBLE_BORDER) + wxFLAGS_MEMBER(wxRAISED_BORDER) wxFLAGS_MEMBER(wxSTATIC_BORDER) wxFLAGS_MEMBER(wxBORDER) // standard window styles - wxFLAGS_MEMBER(wxTAB_TRAVERSAL) - wxFLAGS_MEMBER(wxCLIP_CHILDREN) - wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW) - wxFLAGS_MEMBER(wxWANTS_CHARS) - wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE) - wxFLAGS_MEMBER(wxALWAYS_SHOW_SB ) - wxFLAGS_MEMBER(wxVSCROLL) - wxFLAGS_MEMBER(wxHSCROLL) + wxFLAGS_MEMBER(wxTAB_TRAVERSAL) wxFLAGS_MEMBER(wxCLIP_CHILDREN) + wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW) wxFLAGS_MEMBER(wxWANTS_CHARS) + wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE) wxFLAGS_MEMBER(wxALWAYS_SHOW_SB) + wxFLAGS_MEMBER(wxVSCROLL) wxFLAGS_MEMBER(wxHSCROLL) -wxEND_FLAGS( wxSheetStyle ) + wxEND_FLAGS(wxSheetStyle) -IMPLEMENT_DYNAMIC_CLASS_XTI(wxSheet, wxWindow,"wx/sheet/sheet.h") + IMPLEMENT_DYNAMIC_CLASS_XTI(wxSheet, wxWindow, "wx/sheet/sheet.h") -wxBEGIN_PROPERTIES_TABLE(wxSheet) - wxHIDE_PROPERTY( Children ) - wxPROPERTY_FLAGS( WindowStyle , wxSheetStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style -wxEND_PROPERTIES_TABLE() + wxBEGIN_PROPERTIES_TABLE(wxSheet) wxHIDE_PROPERTY(Children) + wxPROPERTY_FLAGS(WindowStyle, wxSheetStyle, long, + SetWindowStyleFlag, GetWindowStyleFlag, + EMPTY_MACROVALUE, 0 /*flags*/, wxT("Helpstring"), + wxT("group")) // style + wxEND_PROPERTIES_TABLE() -wxBEGIN_HANDLERS_TABLE(wxSheet) -wxEND_HANDLERS_TABLE() + wxBEGIN_HANDLERS_TABLE(wxSheet) wxEND_HANDLERS_TABLE() -wxCONSTRUCTOR_5( wxSheet , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle ) + wxCONSTRUCTOR_5(wxSheet, wxWindow *, Parent, wxWindowID, Id, wxPoint, Position, wxSize, + Size, long, WindowStyle) /* - TODO : Expose more information of a list's layout etc. via appropriate objects (a la NotebookPageInfo) + TODO : Expose more information of a list's layout etc. via appropriate objects (a la + NotebookPageInfo) */ #else -IMPLEMENT_DYNAMIC_CLASS( wxSheet, wxWindow ) +IMPLEMENT_DYNAMIC_CLASS(wxSheet, wxWindow) #endif -BEGIN_EVENT_TABLE( wxSheet, wxWindow ) - EVT_PAINT ( wxSheet::OnPaint ) - EVT_SIZE ( wxSheet::OnSize ) - //EVT_ERASE_BACKGROUND( wxSheet::OnEraseBackground ) - EVT_KEY_DOWN ( wxSheet::OnKeyDown ) - EVT_KEY_UP ( wxSheet::OnKeyUp ) - EVT_CHAR ( wxSheet::OnChar ) - EVT_MOUSEWHEEL ( wxSheet::OnMouseWheel ) - EVT_MOUSE_EVENTS ( wxSheet::OnMouse ) - EVT_COMMAND_SCROLL ( wxSheet::ID_HORIZ_SCROLLBAR, wxSheet::OnScroll ) - EVT_COMMAND_SCROLL ( wxSheet::ID_VERT_SCROLLBAR, wxSheet::OnScroll ) - EVT_TIMER ( wxSheet::ID_MOUSE_DRAG_TIMER, wxSheet::OnMouseTimer ) -END_EVENT_TABLE() + BEGIN_EVENT_TABLE(wxSheet, wxWindow) EVT_PAINT(wxSheet::OnPaint) + EVT_SIZE(wxSheet::OnSize) + // EVT_ERASE_BACKGROUND( wxSheet::OnEraseBackground ) + EVT_KEY_DOWN(wxSheet::OnKeyDown) EVT_KEY_UP(wxSheet::OnKeyUp) EVT_CHAR(wxSheet::OnChar) + EVT_MOUSEWHEEL(wxSheet::OnMouseWheel) EVT_MOUSE_EVENTS(wxSheet::OnMouse) + EVT_COMMAND_SCROLL(wxSheet::ID_HORIZ_SCROLLBAR, wxSheet::OnScroll) + EVT_COMMAND_SCROLL(wxSheet::ID_VERT_SCROLLBAR, wxSheet::OnScroll) + EVT_TIMER(wxSheet::ID_MOUSE_DRAG_TIMER, wxSheet::OnMouseTimer) + END_EVENT_TABLE() -void wxSheet::Init() + void wxSheet::Init() { - m_cornerLabelWin = NULL; - m_rowLabelWin = NULL; - m_colLabelWin = NULL; - m_gridWin = NULL; - m_horizScrollBar = NULL; - m_vertScrollBar = NULL; + m_cornerLabelWin = NULL; + m_rowLabelWin = NULL; + m_colLabelWin = NULL; + m_gridWin = NULL; + m_horizScrollBar = NULL; + m_vertScrollBar = NULL; - m_scrollBarMode = wxSheet::SB_AS_NEEDED; + m_scrollBarMode = wxSheet::SB_AS_NEEDED; - m_keySelecting = false; + m_keySelecting = false; - // init attr cache - m_cacheAttr = wxNullSheetCellAttr; - m_cacheAttrCoords = wxNullSheetCoords; - m_cacheAttrType = -1; + // init attr cache + m_cacheAttr = wxNullSheetCellAttr; + m_cacheAttrCoords = wxNullSheetCoords; + m_cacheAttrType = -1; - m_inOnKeyDown = false; - m_batchCount = 0; - m_resizing = false; + m_inOnKeyDown = false; + m_batchCount = 0; + m_resizing = false; - m_mouseCursorMode = WXSHEET_CURSOR_SELECT_CELL; - m_mouseCursor = WXSHEET_CURSOR_SELECT_CELL; + m_mouseCursorMode = WXSHEET_CURSOR_SELECT_CELL; + m_mouseCursor = WXSHEET_CURSOR_SELECT_CELL; - m_winCapture = (wxWindow *)NULL; + m_winCapture = (wxWindow *)NULL; - m_dragLastPos = -1; - m_dragRowOrCol = -1; - m_isDragging = false; - m_startDragPos = wxDefaultPosition; + m_dragLastPos = -1; + m_dragRowOrCol = -1; + m_isDragging = false; + m_startDragPos = wxDefaultPosition; - m_waitForSlowClick = false; - m_mouseTimer = NULL; + m_waitForSlowClick = false; + m_mouseTimer = NULL; - m_enable_split_vert = false; - m_enable_split_horiz = false; + m_enable_split_vert = false; + m_enable_split_horiz = false; - m_refData = new wxSheetRefData; // ALWAYS CREATED and ALWAYS EXISTS! + m_refData = new wxSheetRefData; // ALWAYS CREATED and ALWAYS EXISTS! } // NOTE: If using the default visual attributes works everywhere then this can @@ -542,553 +532,582 @@ void wxSheet::Init() #include "wx/listbox.h" #endif -bool wxSheet::Create( wxWindow *parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - long style, const wxString& name ) +bool wxSheet::Create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, + long style, const wxString &name) { - if (!wxWindow::Create(parent, id, pos, size, style | wxWANTS_CHARS, name)) - return false; - -#if wxCHECK_VERSION(2,5,2) && _USE_VISATTR - wxVisualAttributes gva = wxListBox::GetClassDefaultAttributes(); - wxVisualAttributes lva = wxPanel::GetClassDefaultAttributes(); - - wxColour gfg = gva.colFg; // grid foreground - wxColour gbg = gva.colBg; // grid background - wxColour lfg = lva.colFg; // label foreground - wxColour lbg = lva.colBg; // label background -#else // 2.4.x - wxColour gfg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); - wxColour gbg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ); - wxColour lfg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); - wxColour lbg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ); -#endif //wxCHECK_VERSION(2,5,2) - - // Set default cell attributes - wxSheetCellAttr *attr = &GetSheetRefData()->m_defaultGridCellAttr; - attr->Create(); - attr->SetKind(wxSHEET_AttrDefault); - attr->SetFont(GetFont()); // need window created for this - attr->SetAlignment(wxALIGN_LEFT | wxALIGN_TOP); - attr->SetOrientation(wxHORIZONTAL); - attr->SetLevel(wxSHEET_AttrLevelBottom); - attr->SetOverflow(true); - attr->SetOverflowMarker(true); - attr->SetShowEditor(false); - attr->SetReadOnly(false); - attr->SetForegroundColour(gfg); - attr->SetBackgroundColour(gbg); - attr->SetRenderer(GetDefaultRendererForType(wxSHEET_VALUE_STRING)); - attr->SetEditor(GetDefaultEditorForType(wxSHEET_VALUE_STRING)); - - wxFont labelFont = wxWindow::GetFont(); - labelFont.SetWeight( wxFONTWEIGHT_BOLD ); - - // default row label attr - attr = &GetSheetRefData()->m_defaultRowLabelAttr; - attr->Create(); - attr->SetKind(wxSHEET_AttrDefault); - attr->SetFont(labelFont); // need window created for this - attr->SetAlignment(wxALIGN_CENTRE); - attr->SetOrientation(wxHORIZONTAL); - attr->SetLevel(wxSHEET_AttrLevelBottom); - attr->SetOverflow(false); - attr->SetOverflowMarker(false); // just cutoff, looks better? - attr->SetShowEditor(false); - attr->SetReadOnly(true); - attr->SetForegroundColour(lfg); - attr->SetBackgroundColour(lbg); - attr->SetRenderer(GetDefaultRendererForType(wxSHEET_VALUE_LABEL)); - attr->SetEditor(GetDefaultEditorForType(wxSHEET_VALUE_STRING)); - - // default col and corner label attr are identical to row label attr - GetSheetRefData()->m_defaultColLabelAttr = attr->Clone(); - GetSheetRefData()->m_defaultCornerLabelAttr = attr->Clone(); - - // subwindow components that make up the wxSheet - m_gridWin = new wxSheetChildWindow( this, ID_GRID_WINDOW ); - m_rowLabelWin = new wxSheetChildWindow( this, ID_ROW_LABEL_WINDOW ); - m_colLabelWin = new wxSheetChildWindow( this, ID_COL_LABEL_WINDOW ); - m_cornerLabelWin = new wxSheetChildWindow( this, ID_CORNER_LABEL_WINDOW ); - m_horizScrollBar = new wxScrollBar(this, ID_HORIZ_SCROLLBAR, wxDefaultPosition, - wxDefaultSize, wxSB_HORIZONTAL); - m_vertScrollBar = new wxScrollBar(this, ID_VERT_SCROLLBAR, wxDefaultPosition, - wxDefaultSize, wxSB_VERTICAL); - - // det the default colours for each window - m_cornerLabelWin->SetOwnForegroundColour(lfg); - m_cornerLabelWin->SetOwnBackgroundColour(lbg); - m_rowLabelWin->SetOwnForegroundColour(lfg); - m_rowLabelWin->SetOwnBackgroundColour(lbg); - m_colLabelWin->SetOwnForegroundColour(lfg); - m_colLabelWin->SetOwnBackgroundColour(lbg); - - m_gridWin->SetOwnForegroundColour(gfg); - m_gridWin->SetOwnBackgroundColour(gbg); - - // figure out what a reasonable size would be - int char_w = 5, char_h = 10; - GetTextExtent(wxT("W1!(jJ"), &char_w, &char_h, NULL, NULL, &labelFont); - -#if defined(__WXMOTIF__) || defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl() - char_h += 8; + if (!wxWindow::Create(parent, id, pos, size, style | wxWANTS_CHARS, name)) { + return false; + } + +#if wxCHECK_VERSION(2, 5, 2) && _USE_VISATTR + wxVisualAttributes gva = wxListBox::GetClassDefaultAttributes(); + wxVisualAttributes lva = wxPanel::GetClassDefaultAttributes(); + + wxColour gfg = gva.colFg; // grid foreground + wxColour gbg = gva.colBg; // grid background + wxColour lfg = lva.colFg; // label foreground + wxColour lbg = lva.colBg; // label background +#else // 2.4.x + wxColour gfg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + wxColour gbg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + wxColour lfg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + wxColour lbg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); +#endif // wxCHECK_VERSION(2,5,2) + + // Set default cell attributes + wxSheetCellAttr *attr = &GetSheetRefData()->m_defaultGridCellAttr; + attr->Create(); + attr->SetKind(wxSHEET_AttrDefault); + attr->SetFont(GetFont()); // need window created for this + attr->SetAlignment(wxALIGN_LEFT | wxALIGN_TOP); + attr->SetOrientation(wxHORIZONTAL); + attr->SetLevel(wxSHEET_AttrLevelBottom); + attr->SetOverflow(true); + attr->SetOverflowMarker(true); + attr->SetShowEditor(false); + attr->SetReadOnly(false); + attr->SetForegroundColour(gfg); + attr->SetBackgroundColour(gbg); + attr->SetRenderer(GetDefaultRendererForType(wxSHEET_VALUE_STRING)); + attr->SetEditor(GetDefaultEditorForType(wxSHEET_VALUE_STRING)); + + wxFont labelFont = wxWindow::GetFont(); + labelFont.SetWeight(wxFONTWEIGHT_BOLD); + + // default row label attr + attr = &GetSheetRefData()->m_defaultRowLabelAttr; + attr->Create(); + attr->SetKind(wxSHEET_AttrDefault); + attr->SetFont(labelFont); // need window created for this + attr->SetAlignment(wxALIGN_CENTRE); + attr->SetOrientation(wxHORIZONTAL); + attr->SetLevel(wxSHEET_AttrLevelBottom); + attr->SetOverflow(false); + attr->SetOverflowMarker(false); // just cutoff, looks better? + attr->SetShowEditor(false); + attr->SetReadOnly(true); + attr->SetForegroundColour(lfg); + attr->SetBackgroundColour(lbg); + attr->SetRenderer(GetDefaultRendererForType(wxSHEET_VALUE_LABEL)); + attr->SetEditor(GetDefaultEditorForType(wxSHEET_VALUE_STRING)); + + // default col and corner label attr are identical to row label attr + GetSheetRefData()->m_defaultColLabelAttr = attr->Clone(); + GetSheetRefData()->m_defaultCornerLabelAttr = attr->Clone(); + + // subwindow components that make up the wxSheet + m_gridWin = new wxSheetChildWindow(this, ID_GRID_WINDOW); + m_rowLabelWin = new wxSheetChildWindow(this, ID_ROW_LABEL_WINDOW); + m_colLabelWin = new wxSheetChildWindow(this, ID_COL_LABEL_WINDOW); + m_cornerLabelWin = new wxSheetChildWindow(this, ID_CORNER_LABEL_WINDOW); + m_horizScrollBar = + new wxScrollBar(this, ID_HORIZ_SCROLLBAR, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL); + m_vertScrollBar = + new wxScrollBar(this, ID_VERT_SCROLLBAR, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL); + + // det the default colours for each window + m_cornerLabelWin->SetOwnForegroundColour(lfg); + m_cornerLabelWin->SetOwnBackgroundColour(lbg); + m_rowLabelWin->SetOwnForegroundColour(lfg); + m_rowLabelWin->SetOwnBackgroundColour(lbg); + m_colLabelWin->SetOwnForegroundColour(lfg); + m_colLabelWin->SetOwnBackgroundColour(lbg); + + m_gridWin->SetOwnForegroundColour(gfg); + m_gridWin->SetOwnBackgroundColour(gbg); + + // figure out what a reasonable size would be + int char_w = 5, char_h = 10; + GetTextExtent(wxT("W1!(jJ"), &char_w, &char_h, NULL, NULL, &labelFont); + +#if defined(__WXMOTIF__) || \ + defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl() + char_h += 8; #else - char_h += 6; // test in wx24 + char_h += 6; // test in wx24 #endif - GetSheetRefData()->m_rowEdges.SetDefaultSize(char_h); + GetSheetRefData()->m_rowEdges.SetDefaultSize(char_h); - GetSheetRefData()->AddSheet(this); + GetSheetRefData()->AddSheet(this); -#if wxCHECK_VERSION(2,7,2) - SetInitialSize(size); -#elif wxCHECK_VERSION(2,5,2) - SetBestFittingSize(size); +#if wxCHECK_VERSION(2, 7, 2) + SetInitialSize(size); +#elif wxCHECK_VERSION(2, 5, 2) + SetBestFittingSize(size); #endif // wxCHECK_VERSION(2,5,2) - return true; + return true; } wxSheet::~wxSheet() { - SetCaptureWindow(NULL); - StopMouseTimer(); - GetSheetRefData()->RemoveSheet(this); + SetCaptureWindow(NULL); + StopMouseTimer(); + GetSheetRefData()->RemoveSheet(this); - // destroy the edit control if this is the "parent" - if (GetEditControl().Ok() && GetEditControl().GetControl()) - { - wxWindowID win_id = GetEditControl().GetControl()->GetId(); - if (FindWindow(win_id) == GetEditControl().GetControl()) - { - GetSheetRefData()->m_cellEditor.DestroyControl(); - GetSheetRefData()->m_cellEditor.Destroy(); - GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; - } + // destroy the edit control if this is the "parent" + if (GetEditControl().Ok() && GetEditControl().GetControl()) { + wxWindowID win_id = GetEditControl().GetControl()->GetId(); + if (FindWindow(win_id) == GetEditControl().GetControl()) { + GetSheetRefData()->m_cellEditor.DestroyControl(); + GetSheetRefData()->m_cellEditor.Destroy(); + GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; } + } #ifdef DEBUG_ATTR_CACHE - size_t total = gs_nAttrCacheHits + gs_nAttrCacheMisses; - wxPrintf(_T("wxSheet attribute cache statistics: " - "total: %u, hits: %u (%u%%)\n"), - total, gs_nAttrCacheHits, - total ? (gs_nAttrCacheHits*100) / total : 0); + size_t total = gs_nAttrCacheHits + gs_nAttrCacheMisses; + wxPrintf(_T("wxSheet attribute cache statistics: " + "total: %u, hits: %u (%u%%)\n"), + total, gs_nAttrCacheHits, total ? (gs_nAttrCacheHits * 100) / total : 0); #endif } bool wxSheet::Destroy() { - SetCaptureWindow(NULL); - StopMouseTimer(); - GetSheetRefData()->RemoveSheet(this); - return wxWindow::Destroy(); + SetCaptureWindow(NULL); + StopMouseTimer(); + GetSheetRefData()->RemoveSheet(this); + return wxWindow::Destroy(); } -void wxSheet::RefSheet(wxSheet* sheet) +void wxSheet::RefSheet(wxSheet *sheet) { - wxCHECK_RET(sheet, wxT("Invalid wxSheet")); - SetCaptureWindow(NULL); - StopMouseTimer(); - GetSheetRefData()->RemoveSheet(this); // remove from old data - UnRef(); - Ref(*sheet); - GetSheetRefData()->AddSheet(this); - CalcWindowSizes(); + wxCHECK_RET(sheet, wxT("Invalid wxSheet")); + SetCaptureWindow(NULL); + StopMouseTimer(); + GetSheetRefData()->RemoveSheet(this); // remove from old data + UnRef(); + Ref(*sheet); + GetSheetRefData()->AddSheet(this); + CalcWindowSizes(); } -wxSheet* wxSheet::Clone(wxWindowID id) +wxSheet *wxSheet::Clone(wxWindowID id) { - wxSheet *sheet = (wxSheet*)GetClassInfo()->CreateObject(); - sheet->Create(GetParent(), id); - return sheet; + wxSheet *sheet = (wxSheet *)GetClassInfo()->CreateObject(); + sheet->Create(GetParent(), id); + return sheet; } bool wxSheet::Enable(bool enable) { - if ( !wxWindow::Enable(enable) ) - return false; + if (!wxWindow::Enable(enable)) { + return false; + } - // redraw in the new state - Refresh(); + // redraw in the new state + Refresh(); - return true; + return true; } // ------------------------------------------------------------------------ -bool wxSheet::SetTable( wxSheetTable *table, bool takeOwnership ) +bool wxSheet::SetTable(wxSheetTable *table, bool takeOwnership) { - if ( GetSheetRefData()->m_table ) - { - if (GetSheetRefData()->m_ownTable) - delete GetSheetRefData()->m_table; - - if (GetSelection()) - GetSelection()->Clear(); + if (GetSheetRefData()->m_table) { + if (GetSheetRefData()->m_ownTable) { + delete GetSheetRefData()->m_table; + } - GetSheetRefData()->m_table = NULL; - GetSheetRefData()->m_rowEdges.Clear(); - GetSheetRefData()->m_colEdges.Clear(); + if (GetSelection()) { + GetSelection()->Clear(); } - if (table) - { - GetSheetRefData()->m_rowEdges.UpdatePos(0, table->GetNumberRows()); - GetSheetRefData()->m_colEdges.UpdatePos(0, table->GetNumberCols()); + GetSheetRefData()->m_table = NULL; + GetSheetRefData()->m_rowEdges.Clear(); + GetSheetRefData()->m_colEdges.Clear(); + } - GetSheetRefData()->m_table = table; - GetSheetRefData()->m_table->SetView( this ); - GetSheetRefData()->m_ownTable = takeOwnership; + if (table) { + GetSheetRefData()->m_rowEdges.UpdatePos(0, table->GetNumberRows()); + GetSheetRefData()->m_colEdges.UpdatePos(0, table->GetNumberCols()); - CalcWindowSizes(); - } + GetSheetRefData()->m_table = table; + GetSheetRefData()->m_table->SetView(this); + GetSheetRefData()->m_ownTable = takeOwnership; - return true; + CalcWindowSizes(); + } + + return true; } -bool wxSheet::CreateGrid( int numRows, int numCols, int options ) +bool wxSheet::CreateGrid(int numRows, int numCols, int options) { - // Create a table and assign it's data structures - wxSheetTable *table = new wxSheetTable( this ); - table->SetGridCellValueProvider(new wxSheetValueProviderString(numRows, numCols, options), true); - //table->SetGridCellValueProvider(new wxSheetValueProviderSparseString(numRows, numCols, options), true); + // Create a table and assign it's data structures + wxSheetTable *table = new wxSheetTable(this); + table->SetGridCellValueProvider(new wxSheetValueProviderString(numRows, numCols, options), true); + // table->SetGridCellValueProvider(new wxSheetValueProviderSparseString(numRows, numCols, + // options), true); - // label data containers are optional and needed only if you Set values for them - // we create both of them. - // NB. They're the same as the grid data but only have one row or col each. - // NB. wxSHEET_ValueProviderColPref is used for the col labels since - // we expect more cols than rows - table->SetRowLabelValueProvider(new wxSheetValueProviderString(numRows, 1), true); - table->SetColLabelValueProvider(new wxSheetValueProviderString(1, numCols, wxSHEET_ValueProviderColPref), true); - // Set the attribute provider if you plan to "Set" attributes for particular - // cells/rows/cols, otherwise the default attributes will suffice - table->SetAttrProvider(new wxSheetCellAttrProvider, true); + // label data containers are optional and needed only if you Set values for them + // we create both of them. + // NB. They're the same as the grid data but only have one row or col each. + // NB. wxSHEET_ValueProviderColPref is used for the col labels since + // we expect more cols than rows + table->SetRowLabelValueProvider(new wxSheetValueProviderString(numRows, 1), true); + table->SetColLabelValueProvider( + new wxSheetValueProviderString(1, numCols, wxSHEET_ValueProviderColPref), true); + // Set the attribute provider if you plan to "Set" attributes for particular + // cells/rows/cols, otherwise the default attributes will suffice + table->SetAttrProvider(new wxSheetCellAttrProvider, true); - return SetTable(table, true); + return SetTable(table, true); } // ------------------------------------------------------------------------ // Dimensions of the sheet -wxSheetCell_Type wxSheet::GetCellCoordsType(const wxSheetCoords& coords) +wxSheetCell_Type wxSheet::GetCellCoordsType(const wxSheetCoords &coords) { - if ((coords.m_row >= 0) && (coords.m_col >= 0)) - { - return wxSHEET_CELL_GRID; + if ((coords.m_row >= 0) && (coords.m_col >= 0)) { + return wxSHEET_CELL_GRID; + } + else if (coords.m_row == -1) { + if (coords.m_col == -1) { + return wxSHEET_CELL_CORNERLABEL; } - else if (coords.m_row == -1) - { - if (coords.m_col == -1) - return wxSHEET_CELL_CORNERLABEL; - if (coords.m_col >= 0) - return wxSHEET_CELL_COLLABEL; + if (coords.m_col >= 0) { + return wxSHEET_CELL_COLLABEL; } - else if (coords.m_col == -1) - { - if (coords.m_row >= 0) - return wxSHEET_CELL_ROWLABEL; + } + else if (coords.m_col == -1) { + if (coords.m_row >= 0) { + return wxSHEET_CELL_ROWLABEL; } + } - return wxSHEET_CELL_UNKNOWN; + return wxSHEET_CELL_UNKNOWN; } void wxSheet::ClearValues(int update) { - if ( GetTable() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(false); - - GetTable()->ClearValues(update); - RefreshGridWindow(); + if (GetTable()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(false); } -} -bool wxSheet::UpdateRows( size_t row, int numRows, int update ) -{ - wxCHECK_MSG(GetTable(), false, wxT("Called wxSheet::UpdateRows() before calling CreateGrid()")); - // the table should then call DoUpdateRows back on the sheet before returning - return GetTable()->UpdateRows(row, numRows, update); + GetTable()->ClearValues(update); + RefreshGridWindow(); + } } -bool wxSheet::UpdateCols( size_t col, int numCols, int update ) + +bool wxSheet::UpdateRows(size_t row, int numRows, int update) { - wxCHECK_MSG(GetTable(), false, wxT("Called wxSheet::UpdateCols() before calling CreateGrid()")); - // the table should then call DoUpdateRows back on the sheet before returning - return GetTable()->UpdateCols(col, numCols, update); + wxCHECK_MSG(GetTable(), false, wxT("Called wxSheet::UpdateRows() before calling CreateGrid()")); + // the table should then call DoUpdateRows back on the sheet before returning + return GetTable()->UpdateRows(row, numRows, update); } - -bool wxSheet::SetNumberCols( size_t cols, int update ) +bool wxSheet::UpdateCols(size_t col, int numCols, int update) { - const int n_cols = int(cols) - GetNumberCols(); - if (n_cols > 0) - return AppendCols(n_cols, update); - else if (n_cols < 0) - return DeleteCols(cols, -n_cols, update); - - return false; + wxCHECK_MSG(GetTable(), false, wxT("Called wxSheet::UpdateCols() before calling CreateGrid()")); + // the table should then call DoUpdateRows back on the sheet before returning + return GetTable()->UpdateCols(col, numCols, update); } -bool wxSheet::SetNumberRows( size_t rows, int update ) +bool wxSheet::SetNumberCols(size_t cols, int update) { - const int n_rows = int(rows) - GetNumberRows(); - if (n_rows > 0) - return AppendRows(n_rows, update); - else if (n_rows < 0) - return DeleteRows(rows, -n_rows, update); + const int n_cols = int(cols) - GetNumberCols(); + if (n_cols > 0) { + return AppendCols(n_cols, update); + } + else if (n_cols < 0) { + return DeleteCols(cols, -n_cols, update); + } - return false; + return false; } -bool wxSheet::DoUpdateRows( size_t row, int numRows, int update) +bool wxSheet::SetNumberRows(size_t rows, int update) { - // Clear the attribute cache as the attribute might refer to a invalid cell - ClearAttrCache(); - if (numRows == 0) return false; + const int n_rows = int(rows) - GetNumberRows(); + if (n_rows > 0) { + return AppendRows(n_rows, update); + } + else if (n_rows < 0) { + return DeleteRows(rows, -n_rows, update); + } - // By the same reasoning, the editor should be dismissed if columns are - // added or removed. And for consistency, it should IMHO always be - // removed, not only if the cell "underneath" it actually changes. - // For now, I intentionally do not save the editor's content as the - // cell it might want to save that stuff to might no longer exist. - if (IsCellEditControlCreated()) - DisableCellEditControl(false); - - // FIXME - do I want to UpdateRows/Cols for selection or just clear them - // the event it would send would be confusing at best - // first a deselect and then a select... should sel follow insert? - // I don't think it's worth the confusion and since a click on - // a cell is deselect all, the selection is not that precious. - //ClearSelection(true); - - GetSheetRefData()->m_rowEdges.UpdatePos(row, numRows); - - // Update any data structures - if ( ((update & wxSHEET_UpdateSelection) != 0) && GetSelection() ) - GetSelection()->UpdateRows( row, numRows ); - - GetSheetRefData()->m_cursorCoords.UpdateRows(row, numRows); - // try to force the cursor to a valid cell - if ( !ContainsGridCell(GetGridCursorCell()) && ContainsGridCell(wxSheetCoords(0,0)) ) - SetGridCursorCell( wxSheetCoords(0, 0) ); - else - GetSheetRefData()->m_cursorCoords = wxNullSheetCoords; - - AdjustScrollbars(); - RefreshRowLabelWindow(true); - RefreshGridWindow(); - return true; + return false; } -bool wxSheet::DoUpdateCols( size_t col, int numCols, int update) +bool wxSheet::DoUpdateRows(size_t row, int numRows, int update) { - ClearAttrCache(); - if (numCols == 0) return false; + // Clear the attribute cache as the attribute might refer to a invalid cell + ClearAttrCache(); + if (numRows == 0) { + return false; + } + + // By the same reasoning, the editor should be dismissed if columns are + // added or removed. And for consistency, it should IMHO always be + // removed, not only if the cell "underneath" it actually changes. + // For now, I intentionally do not save the editor's content as the + // cell it might want to save that stuff to might no longer exist. + if (IsCellEditControlCreated()) { + DisableCellEditControl(false); + } + + // FIXME - do I want to UpdateRows/Cols for selection or just clear them + // the event it would send would be confusing at best + // first a deselect and then a select... should sel follow insert? + // I don't think it's worth the confusion and since a click on + // a cell is deselect all, the selection is not that precious. + // ClearSelection(true); + + GetSheetRefData()->m_rowEdges.UpdatePos(row, numRows); + + // Update any data structures + if (((update & wxSHEET_UpdateSelection) != 0) && GetSelection()) { + GetSelection()->UpdateRows(row, numRows); + } + + GetSheetRefData()->m_cursorCoords.UpdateRows(row, numRows); + // try to force the cursor to a valid cell + if (!ContainsGridCell(GetGridCursorCell()) && ContainsGridCell(wxSheetCoords(0, 0))) { + SetGridCursorCell(wxSheetCoords(0, 0)); + } + else { + GetSheetRefData()->m_cursorCoords = wxNullSheetCoords; + } + + AdjustScrollbars(); + RefreshRowLabelWindow(true); + RefreshGridWindow(); + return true; +} + +bool wxSheet::DoUpdateCols(size_t col, int numCols, int update) +{ + ClearAttrCache(); + if (numCols == 0) { + return false; + } - if (IsCellEditControlCreated()) - DisableCellEditControl(false); + if (IsCellEditControlCreated()) { + DisableCellEditControl(false); + } - GetSheetRefData()->m_colEdges.UpdatePos(col, numCols); + GetSheetRefData()->m_colEdges.UpdatePos(col, numCols); - if ( ((update & wxSHEET_UpdateSelection) != 0) && GetSelection() ) - GetSelection()->UpdateCols( col, numCols ); + if (((update & wxSHEET_UpdateSelection) != 0) && GetSelection()) { + GetSelection()->UpdateCols(col, numCols); + } - GetSheetRefData()->m_cursorCoords.UpdateCols(col, numCols); - if ( !ContainsGridCell(GetGridCursorCell()) && ContainsGridCell(wxSheetCoords(0,0)) ) - SetGridCursorCell( wxSheetCoords(0, 0) ); - else - GetSheetRefData()->m_cursorCoords = wxNullSheetCoords; + GetSheetRefData()->m_cursorCoords.UpdateCols(col, numCols); + if (!ContainsGridCell(GetGridCursorCell()) && ContainsGridCell(wxSheetCoords(0, 0))) { + SetGridCursorCell(wxSheetCoords(0, 0)); + } + else { + GetSheetRefData()->m_cursorCoords = wxNullSheetCoords; + } - AdjustScrollbars(); - RefreshColLabelWindow(true); - RefreshGridWindow(); - return true; + AdjustScrollbars(); + RefreshColLabelWindow(true); + RefreshGridWindow(); + return true; } // ---------------------------------------------------------------------------- // Dimensions of the row and column sizes -void wxSheet::SetDefaultRowHeight( int height, bool resizeExistingRows ) +void wxSheet::SetDefaultRowHeight(int height, bool resizeExistingRows) { - GetSheetRefData()->m_rowEdges.SetDefaultSize(height, resizeExistingRows); - if ( resizeExistingRows && !GetBatchCount() ) - CalcWindowSizes(true); + GetSheetRefData()->m_rowEdges.SetDefaultSize(height, resizeExistingRows); + if (resizeExistingRows && !GetBatchCount()) { + CalcWindowSizes(true); + } } -void wxSheet::SetDefaultColWidth( int width, bool resizeExistingCols ) +void wxSheet::SetDefaultColWidth(int width, bool resizeExistingCols) { - GetSheetRefData()->m_colEdges.SetDefaultSize(width, resizeExistingCols); - if ( resizeExistingCols && !GetBatchCount() ) - CalcWindowSizes(true); + GetSheetRefData()->m_colEdges.SetDefaultSize(width, resizeExistingCols); + if (resizeExistingCols && !GetBatchCount()) { + CalcWindowSizes(true); + } } -void wxSheet::SetRowHeight( int row, int height ) +void wxSheet::SetRowHeight(int row, int height) { - if (row == -1) - { - SetColLabelHeight(height); - return; - } + if (row == -1) { + SetColLabelHeight(height); + return; + } - wxCHECK_RET(ContainsGridRow(row), _T("invalid row index") ); + wxCHECK_RET(ContainsGridRow(row), _T("invalid row index")); - const int old_height = GetRowHeight(row); + const int old_height = GetRowHeight(row); - // if < 0 calc new height from label - if ( height < 0 ) - height = GetCellBestSize(wxSheetCoords(row, -1)).y + 6; // FIXME test this + // if < 0 calc new height from label + if (height < 0) { + height = GetCellBestSize(wxSheetCoords(row, -1)).y + 6; // FIXME test this + } - // should we check that it's bigger than GetMinimalRowHeight(row) here? - // (VZ) - // No, because it is reasonable to assume the library user know's - // what he is doing. However whe should test against the weaker - // constariant of minimalAcceptableHeight, as this breaks rendering - if ( height == old_height ) - return; - if (height < GetMinimalAcceptableRowHeight()) - height = GetMinimalAcceptableRowHeight(); + // should we check that it's bigger than GetMinimalRowHeight(row) here? + // (VZ) + // No, because it is reasonable to assume the library user know's + // what he is doing. However whe should test against the weaker + // constariant of minimalAcceptableHeight, as this breaks rendering + if (height == old_height) { + return; + } + if (height < GetMinimalAcceptableRowHeight()) { + height = GetMinimalAcceptableRowHeight(); + } - GetSheetRefData()->m_rowEdges.SetSize(row, height); + GetSheetRefData()->m_rowEdges.SetSize(row, height); - if ( !GetBatchCount() ) - { - CalcWindowSizes(true); - SetGridOrigin(GetGridOrigin(), true); - RefreshBlock(wxSheetBlock(row, -1, GetNumberRows()-row+1, GetNumberCols()+1)); - } + if (!GetBatchCount()) { + CalcWindowSizes(true); + SetGridOrigin(GetGridOrigin(), true); + RefreshBlock(wxSheetBlock(row, -1, GetNumberRows() - row + 1, GetNumberCols() + 1)); + } } -void wxSheet::SetColWidth( int col, int width ) +void wxSheet::SetColWidth(int col, int width) { - if (col == -1) - { - SetRowLabelWidth(width); - return; - } + if (col == -1) { + SetRowLabelWidth(width); + return; + } - wxCHECK_RET(ContainsGridCol(col), _T("invalid column index") ); + wxCHECK_RET(ContainsGridCol(col), _T("invalid column index")); - const int old_width = GetColWidth(col); + const int old_width = GetColWidth(col); - if ( width < 0 ) - width = GetCellBestSize(wxSheetCoords(-1, col)).x + 6; + if (width < 0) { + width = GetCellBestSize(wxSheetCoords(-1, col)).x + 6; + } - if ( width == old_width ) - return; - if ( width < GetMinimalAcceptableColWidth() ) - width = GetMinimalAcceptableColWidth(); + if (width == old_width) { + return; + } + if (width < GetMinimalAcceptableColWidth()) { + width = GetMinimalAcceptableColWidth(); + } - GetSheetRefData()->m_colEdges.SetSize(col, width); + GetSheetRefData()->m_colEdges.SetSize(col, width); - if ( !GetBatchCount() ) - { - CalcWindowSizes(true); - SetGridOrigin(GetGridOrigin(), true); - RefreshBlock(wxSheetBlock(-1, col, GetNumberRows()+1, GetNumberCols()-col+1)); - } + if (!GetBatchCount()) { + CalcWindowSizes(true); + SetGridOrigin(GetGridOrigin(), true); + RefreshBlock(wxSheetBlock(-1, col, GetNumberRows() + 1, GetNumberCols() - col + 1)); + } } int wxSheet::GetColWidth(int col) const { - if (col == -1) - return GetRowLabelWidth(); + if (col == -1) { + return GetRowLabelWidth(); + } - return GetSheetRefData()->m_colEdges.GetSize(col); + return GetSheetRefData()->m_colEdges.GetSize(col); } int wxSheet::GetColLeft(int col) const { - if (col == -1) - return 1; // 1 for border + if (col == -1) { + return 1; // 1 for border + } - return GetSheetRefData()->m_colEdges.GetMin(col); + return GetSheetRefData()->m_colEdges.GetMin(col); } int wxSheet::GetColRight(int col) const { - if (col == -1) - return GetRowLabelWidth(); + if (col == -1) { + return GetRowLabelWidth(); + } - return GetSheetRefData()->m_colEdges.GetMax(col); + return GetSheetRefData()->m_colEdges.GetMax(col); } int wxSheet::GetRowHeight(int row) const { - if (row == -1) - return GetColLabelHeight(); + if (row == -1) { + return GetColLabelHeight(); + } - return GetSheetRefData()->m_rowEdges.GetSize(row); + return GetSheetRefData()->m_rowEdges.GetSize(row); } int wxSheet::GetRowTop(int row) const { - if (row == -1) - return 1; // 1 for border + if (row == -1) { + return 1; // 1 for border + } - return GetSheetRefData()->m_rowEdges.GetMin(row); + return GetSheetRefData()->m_rowEdges.GetMin(row); } int wxSheet::GetRowBottom(int row) const { - if (row == -1) - return GetColLabelHeight(); + if (row == -1) { + return GetColLabelHeight(); + } - return GetSheetRefData()->m_rowEdges.GetMax(row); + return GetSheetRefData()->m_rowEdges.GetMax(row); } -wxSize wxSheet::GetCellSize(const wxSheetCoords& coords) const +wxSize wxSheet::GetCellSize(const wxSheetCoords &coords) const { - return wxSize(GetColWidth(coords.m_row), GetRowHeight(coords.m_row)); + return wxSize(GetColWidth(coords.m_row), GetRowHeight(coords.m_row)); } -bool wxSheet::IsCellShown( const wxSheetCoords& coords ) const +bool wxSheet::IsCellShown(const wxSheetCoords &coords) const { - wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords in wxSheet::IsCellShown")); - return (GetColWidth(coords.GetCol()) > 0) && (GetRowHeight(coords.GetRow()) > 0); + wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords in wxSheet::IsCellShown")); + return (GetColWidth(coords.GetCol()) > 0) && (GetRowHeight(coords.GetRow()) > 0); } -wxSize wxSheet::GetCellBestSize(const wxSheetCoords& coords, wxDC *dc) const +wxSize wxSheet::GetCellBestSize(const wxSheetCoords &coords, wxDC *dc) const { - wxCHECK_MSG(ContainsCell(coords), wxSize(GetDefaultColWidth(), GetDefaultRowHeight()), wxT("Invalid coords")); - wxSheetCellAttr attr(GetAttr(coords)); - wxSheet *sheet = (wxSheet*)this; - wxSheetCellRenderer renderer(attr.GetRenderer(sheet, coords)); - if (!dc) - { - wxClientDC cdc(sheet); - return renderer.GetBestSize(*sheet, attr, cdc, coords); - } + wxCHECK_MSG(ContainsCell(coords), wxSize(GetDefaultColWidth(), GetDefaultRowHeight()), + wxT("Invalid coords")); + wxSheetCellAttr attr(GetAttr(coords)); + wxSheet *sheet = (wxSheet *)this; + wxSheetCellRenderer renderer(attr.GetRenderer(sheet, coords)); + if (!dc) { + wxClientDC cdc(sheet); + return renderer.GetBestSize(*sheet, attr, cdc, coords); + } - return renderer.GetBestSize(*sheet, attr, *dc, coords); + return renderer.GetBestSize(*sheet, attr, *dc, coords); } int wxSheet::GetRowBestHeight(int row) const { - wxCHECK_MSG(ContainsGridRow(row), GetDefaultRowHeight(), wxT("Invalid coords in wxSheet::GetRowBestHeight")); - wxClientDC dc(m_gridWin); - wxCoord bestHeight = 0; - const int numCols = GetNumberCols(); - wxSheetCoords coords( row, row ); - for ( coords.m_col = -1; coords.m_col < numCols; coords.m_col++ ) - { - const int height = GetCellBestSize(coords, &dc).GetHeight(); - if ( height > bestHeight ) - bestHeight = height; + wxCHECK_MSG(ContainsGridRow(row), GetDefaultRowHeight(), + wxT("Invalid coords in wxSheet::GetRowBestHeight")); + wxClientDC dc(m_gridWin); + wxCoord bestHeight = 0; + const int numCols = GetNumberCols(); + wxSheetCoords coords(row, row); + for (coords.m_col = -1; coords.m_col < numCols; coords.m_col++) { + const int height = GetCellBestSize(coords, &dc).GetHeight(); + if (height > bestHeight) { + bestHeight = height; } + } - return bestHeight; + return bestHeight; } int wxSheet::GetColBestWidth(int col) const { - wxCHECK_MSG(ContainsGridCol(col), GetDefaultColWidth(), wxT("Invalid col in wxSheet::GetColBestWidth")); - wxClientDC dc(m_gridWin); - wxCoord bestWidth = 0; - const int numRows = GetNumberRows(); - wxSheetCoords coords( col, col ); - for ( coords.m_row = -1; coords.m_row < numRows; coords.m_row++ ) - { - const int width = GetCellBestSize(coords, &dc).GetWidth(); - if ( width > bestWidth ) - bestWidth = width; + wxCHECK_MSG(ContainsGridCol(col), GetDefaultColWidth(), + wxT("Invalid col in wxSheet::GetColBestWidth")); + wxClientDC dc(m_gridWin); + wxCoord bestWidth = 0; + const int numRows = GetNumberRows(); + wxSheetCoords coords(col, col); + for (coords.m_row = -1; coords.m_row < numRows; coords.m_row++) { + const int width = GetCellBestSize(coords, &dc).GetWidth(); + if (width > bestWidth) { + bestWidth = width; } + } - return bestWidth; + return bestWidth; } // ---------------------------------------------------------------------------- @@ -1096,1132 +1115,1145 @@ int wxSheet::GetColBestWidth(int col) const int wxSheet::GetRowLabelWidth(bool zero_not_shown) const { - if (zero_not_shown && !m_cornerLabelWin->IsShown() && !m_rowLabelWin->IsShown()) - return 0; + if (zero_not_shown && !m_cornerLabelWin->IsShown() && !m_rowLabelWin->IsShown()) { + return 0; + } - return GetSheetRefData()->m_rowLabelWidth; + return GetSheetRefData()->m_rowLabelWidth; } int wxSheet::GetColLabelHeight(bool zero_not_shown) const { - if (zero_not_shown && !m_cornerLabelWin->IsShown() && !m_colLabelWin->IsShown()) - return 0; + if (zero_not_shown && !m_cornerLabelWin->IsShown() && !m_colLabelWin->IsShown()) { + return 0; + } - return GetSheetRefData()->m_colLabelHeight; + return GetSheetRefData()->m_colLabelHeight; } -void wxSheet::SetRowLabelWidth( int width ) +void wxSheet::SetRowLabelWidth(int width) { - width = wxMax( width, 0 ); + width = wxMax(width, 0); - if ( width == 0 ) - { - m_rowLabelWin->Show( false ); - m_cornerLabelWin->Show( false ); - } - else if ( GetRowLabelWidth(false) > 0 ) - { - GetSheetRefData()->m_rowLabelWidth = width; + if (width == 0) { + m_rowLabelWin->Show(false); + m_cornerLabelWin->Show(false); + } + else if (GetRowLabelWidth(false) > 0) { + GetSheetRefData()->m_rowLabelWidth = width; - m_rowLabelWin->Show( true ); - if ( GetColLabelHeight() > 0 ) - m_cornerLabelWin->Show( true ); + m_rowLabelWin->Show(true); + if (GetColLabelHeight() > 0) { + m_cornerLabelWin->Show(true); } + } - CalcWindowSizes(); + CalcWindowSizes(); } -void wxSheet::SetColLabelHeight( int height ) +void wxSheet::SetColLabelHeight(int height) { - height = wxMax( height, 0 ); + height = wxMax(height, 0); - if ( height == 0 ) - { - m_colLabelWin->Show( false ); - m_cornerLabelWin->Show( false ); - } - else if ( GetColLabelHeight(false) > 0 ) - { - GetSheetRefData()->m_colLabelHeight = height; + if (height == 0) { + m_colLabelWin->Show(false); + m_cornerLabelWin->Show(false); + } + else if (GetColLabelHeight(false) > 0) { + GetSheetRefData()->m_colLabelHeight = height; - m_colLabelWin->Show( true ); - if ( GetRowLabelWidth() > 0 ) - m_cornerLabelWin->Show( true ); + m_colLabelWin->Show(true); + if (GetRowLabelWidth() > 0) { + m_cornerLabelWin->Show(true); } + } - CalcWindowSizes(); + CalcWindowSizes(); } // ---------------------------------------------------------------------------- // Auto sizing of the row/col widths/heights -int wxSheet::AutoSizeRow( int row, bool setAsMin ) +int wxSheet::AutoSizeRow(int row, bool setAsMin) { - wxCHECK_MSG(ContainsGridRow(row), 0, wxT("Invalid coords in wxSheet::AutoSizeRow")); - int bestHeight = GetRowBestHeight(row); + wxCHECK_MSG(ContainsGridRow(row), 0, wxT("Invalid coords in wxSheet::AutoSizeRow")); + int bestHeight = GetRowBestHeight(row); - // if empty row - give default extent (notice that if extentMax is less - // than default extent but != 0, it's ok) - if ( bestHeight == 0 ) - bestHeight = GetDefaultRowHeight(); - else - bestHeight += 6; // leave some space around text + // if empty row - give default extent (notice that if extentMax is less + // than default extent but != 0, it's ok) + if (bestHeight == 0) { + bestHeight = GetDefaultRowHeight(); + } + else { + bestHeight += 6; // leave some space around text + } - if (GetRowHeight(row) != bestHeight) - SetRowHeight(row, bestHeight); - if ( setAsMin ) - SetMinimalRowHeight(row, bestHeight); + if (GetRowHeight(row) != bestHeight) { + SetRowHeight(row, bestHeight); + } + if (setAsMin) { + SetMinimalRowHeight(row, bestHeight); + } - return bestHeight; + return bestHeight; } -int wxSheet::AutoSizeCol( int col, bool setAsMin ) +int wxSheet::AutoSizeCol(int col, bool setAsMin) { - wxCHECK_MSG(ContainsGridCol(col), 0, wxT("Invalid col in wxSheet::AutoSizeCol")); - int bestWidth = GetColBestWidth(col); + wxCHECK_MSG(ContainsGridCol(col), 0, wxT("Invalid col in wxSheet::AutoSizeCol")); + int bestWidth = GetColBestWidth(col); - if ( bestWidth == 0 ) - bestWidth = GetDefaultColWidth(); - else - bestWidth += 10; // leave some space around text + if (bestWidth == 0) { + bestWidth = GetDefaultColWidth(); + } + else { + bestWidth += 10; // leave some space around text + } - if (GetColWidth(col) != bestWidth) - SetColWidth(col, bestWidth); - if ( setAsMin ) - SetMinimalColWidth(col, bestWidth); + if (GetColWidth(col) != bestWidth) { + SetColWidth(col, bestWidth); + } + if (setAsMin) { + SetMinimalColWidth(col, bestWidth); + } - return bestWidth; + return bestWidth; } void wxSheet::AutoSizeRows(bool setAsMin) { - BeginBatch(); + BeginBatch(); - const int numRows = GetNumberRows(); - for ( int row = 0; row < numRows; row++ ) - AutoSizeRow(row, setAsMin); + const int numRows = GetNumberRows(); + for (int row = 0; row < numRows; row++) { + AutoSizeRow(row, setAsMin); + } - EndBatch(); + EndBatch(); } void wxSheet::AutoSizeCols(bool setAsMin) { - BeginBatch(); + BeginBatch(); - const int numCols = GetNumberCols(); - for ( int col = 0; col < numCols; col++ ) - AutoSizeCol(col, setAsMin); + const int numCols = GetNumberCols(); + for (int col = 0; col < numCols; col++) { + AutoSizeCol(col, setAsMin); + } - EndBatch(); + EndBatch(); } void wxSheet::AutoSize(bool setAsMin) { - BeginBatch(); + BeginBatch(); - SetMargins(0, 0); - AutoSizeRows(setAsMin); - AutoSizeCols(setAsMin); + SetMargins(0, 0); + AutoSizeRows(setAsMin); + AutoSizeCols(setAsMin); - wxSize sizeFit(GetGridVirtualSize()); - sizeFit.x += GetRowLabelWidth(); - sizeFit.y += GetColLabelHeight(); + wxSize sizeFit(GetGridVirtualSize()); + sizeFit.x += GetRowLabelWidth(); + sizeFit.y += GetColLabelHeight(); - wxSize winSize(GetClientSize()); + wxSize winSize(GetClientSize()); - // distribute the extra space between the columns/rows to avoid having - // extra white space - const int numCols = GetNumberCols(); - const int numRows = GetNumberRows(); + // distribute the extra space between the columns/rows to avoid having + // extra white space + const int numCols = GetNumberCols(); + const int numRows = GetNumberRows(); - // Remove the extra m_extraWidth + 1 added above - wxCoord diff = winSize.x - sizeFit.x; - if ( diff && numCols ) - { - // try to resize the columns uniformly - wxCoord diffPerCol = diff / numCols; - if ( diffPerCol != 0 ) - { - for ( int col = 0; col < numCols; col++ ) - SetColWidth(col, GetColWidth(col) + diffPerCol); - } + // Remove the extra m_extraWidth + 1 added above + wxCoord diff = winSize.x - sizeFit.x; + if (diff && numCols) { + // try to resize the columns uniformly + wxCoord diffPerCol = diff / numCols; + if (diffPerCol != 0) { + for (int col = 0; col < numCols; col++) { + SetColWidth(col, GetColWidth(col) + diffPerCol); + } + } - // add remaining amount to the last columns - diff -= diffPerCol * numCols; - if ( diff != 0 ) - { - for ( int col = numCols - 1; col >= numCols - diff; col-- ) - SetColWidth(col, GetColWidth(col) + 1); - } + // add remaining amount to the last columns + diff -= diffPerCol * numCols; + if (diff != 0) { + for (int col = numCols - 1; col >= numCols - diff; col--) { + SetColWidth(col, GetColWidth(col) + 1); + } } + } - // same for rows - diff = winSize.y - sizeFit.y; - if ( diff && numRows ) - { - // try to resize the columns uniformly - wxCoord diffPerRow = diff / numRows; - if ( diffPerRow != 0 ) - { - for ( int row = 0; row < numRows; row++ ) - SetRowHeight(row, GetRowHeight(row) + diffPerRow); - } + // same for rows + diff = winSize.y - sizeFit.y; + if (diff && numRows) { + // try to resize the columns uniformly + wxCoord diffPerRow = diff / numRows; + if (diffPerRow != 0) { + for (int row = 0; row < numRows; row++) { + SetRowHeight(row, GetRowHeight(row) + diffPerRow); + } + } - // add remaining amount to the last rows - diff -= diffPerRow * numRows; - if ( diff != 0 ) - { - for ( int row = numRows - 1; row >= numRows - diff; row-- ) - SetRowHeight(row, GetRowHeight(row) + 1); - } + // add remaining amount to the last rows + diff -= diffPerRow * numRows; + if (diff != 0) { + for (int row = numRows - 1; row >= numRows - diff; row--) { + SetRowHeight(row, GetRowHeight(row) + 1); + } } + } - sizeFit = GetGridVirtualSize(); - sizeFit.x += GetRowLabelWidth(); - sizeFit.y += GetColLabelHeight(); + sizeFit = GetGridVirtualSize(); + sizeFit.x += GetRowLabelWidth(); + sizeFit.y += GetColLabelHeight(); - SetClientSize(sizeFit + wxSize(2,2)); // FIXME ? Where's the extra 2 from in wxGTK - EndBatch(); + SetClientSize(sizeFit + wxSize(2, 2)); // FIXME ? Where's the extra 2 from in wxGTK + EndBatch(); } -void wxSheet::AutoSizeRowLabelHeight( int row ) +void wxSheet::AutoSizeRowLabelHeight(int row) { - wxCHECK_RET(ContainsGridRow(row), wxT("Invalid row in wxSheet::AutoSizeRowLabelHeight")); + wxCHECK_RET(ContainsGridRow(row), wxT("Invalid row in wxSheet::AutoSizeRowLabelHeight")); - // Hide the edit control, so it won't interfer with drag-shrinking. - if ( IsCellEditControlShown() ) - DisableCellEditControl(true); + // Hide the edit control, so it won't interfer with drag-shrinking. + if (IsCellEditControlShown()) { + DisableCellEditControl(true); + } - // autosize row height depending on label text - const wxSheetCoords coords(row, -1); - wxSize size(GetCellBestSize(coords)); + // autosize row height depending on label text + const wxSheetCoords coords(row, -1); + wxSize size(GetCellBestSize(coords)); - if (size.y < GetDefaultRowHeight()) - size.y = GetDefaultRowHeight(); + if (size.y < GetDefaultRowHeight()) { + size.y = GetDefaultRowHeight(); + } - SetRowHeight(row, size.y); + SetRowHeight(row, size.y); } -void wxSheet::AutoSizeColLabelWidth( int col ) +void wxSheet::AutoSizeColLabelWidth(int col) { - wxCHECK_RET(ContainsGridCol(col), wxT("Invalid col in wxSheet::AutoSizeColLabelWidth")); + wxCHECK_RET(ContainsGridCol(col), wxT("Invalid col in wxSheet::AutoSizeColLabelWidth")); - // Hide the edit control, so it won't interfer with drag-shrinking. - if ( IsCellEditControlShown() ) - DisableCellEditControl(true); + // Hide the edit control, so it won't interfer with drag-shrinking. + if (IsCellEditControlShown()) { + DisableCellEditControl(true); + } - // autosize column width depending on label text - const wxSheetCoords coords(-1, col); - wxSize size(GetCellBestSize(coords)); + // autosize column width depending on label text + const wxSheetCoords coords(-1, col); + wxSize size(GetCellBestSize(coords)); - if (size.x < GetDefaultColWidth()) - size.x = GetDefaultColWidth(); + if (size.x < GetDefaultColWidth()) { + size.x = GetDefaultColWidth(); + } - SetColWidth(col, size.x); + SetColWidth(col, size.x); } void wxSheet::SetEqualColWidths(int min_width) { - GetSheetRefData()->m_equal_col_widths = wxMax(min_width, 0); - const int numCols = GetNumberCols(); + GetSheetRefData()->m_equal_col_widths = wxMax(min_width, 0); + const int numCols = GetNumberCols(); - // don't fail here, since EVT_SIZEs are generated before the grid is - if ((min_width > 0) && (numCols > 0) && GetTable() && m_gridWin) - { - const int colwidth = m_gridWin->GetClientSize().GetWidth()/numCols; - SetDefaultColWidth( colwidth, true ); - } + // don't fail here, since EVT_SIZEs are generated before the grid is + if ((min_width > 0) && (numCols > 0) && GetTable() && m_gridWin) { + const int colwidth = m_gridWin->GetClientSize().GetWidth() / numCols; + SetDefaultColWidth(colwidth, true); + } } // ---------------------------------------------------------------------------- // Grid line and cell highlight colouring -void wxSheet::EnableGridLines( int dir ) +void wxSheet::EnableGridLines(int dir) { - GetSheetRefData()->m_gridLinesEnabled = dir; - RefreshGridWindow(false); + GetSheetRefData()->m_gridLinesEnabled = dir; + RefreshGridWindow(false); } -void wxSheet::SetGridLineColour( const wxColour& colour ) +void wxSheet::SetGridLineColour(const wxColour &colour) { - wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetGridLineColour")); - GetSheetRefData()->m_gridLineColour = colour; - RefreshGridWindow(false); + wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetGridLineColour")); + GetSheetRefData()->m_gridLineColour = colour; + RefreshGridWindow(false); } -void wxSheet::SetCursorCellHighlightColour( const wxColour& colour ) +void wxSheet::SetCursorCellHighlightColour(const wxColour &colour) { - wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetGridLineColour")); - GetSheetRefData()->m_cursorCellHighlightColour = colour; + wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetGridLineColour")); + GetSheetRefData()->m_cursorCellHighlightColour = colour; - if (ContainsCell(GetGridCursorCell())) - RefreshCell(GetGridCursorCell(), true); + if (ContainsCell(GetGridCursorCell())) { + RefreshCell(GetGridCursorCell(), true); + } } void wxSheet::SetCursorCellHighlightPenWidth(int width) { - wxCHECK_RET(width >= 0, wxT("Invalid pen width in wxSheet::SetGridLineColour")); - GetSheetRefData()->m_cursorCellHighlightPenWidth = width; + wxCHECK_RET(width >= 0, wxT("Invalid pen width in wxSheet::SetGridLineColour")); + GetSheetRefData()->m_cursorCellHighlightPenWidth = width; - if (ContainsCell(GetGridCursorCell())) - RefreshCell(GetGridCursorCell(), true); + if (ContainsCell(GetGridCursorCell())) { + RefreshCell(GetGridCursorCell(), true); + } } void wxSheet::SetCursorCellHighlightROPenWidth(int width) { - wxCHECK_RET(width >= 0, wxT("Invalid pen width in wxSheet::SetCursorCellHighlightROPenWidth")); - GetSheetRefData()->m_cursorCellHighlightROPenWidth = width; + wxCHECK_RET(width >= 0, wxT("Invalid pen width in wxSheet::SetCursorCellHighlightROPenWidth")); + GetSheetRefData()->m_cursorCellHighlightROPenWidth = width; - if (ContainsCell(GetGridCursorCell())) - RefreshCell(GetGridCursorCell(), true); + if (ContainsCell(GetGridCursorCell())) { + RefreshCell(GetGridCursorCell(), true); + } } -void wxSheet::SetLabelOutlineColour( const wxColour& colour ) +void wxSheet::SetLabelOutlineColour(const wxColour &colour) { - wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetLabelOutlineColour")); - GetSheetRefData()->m_labelOutlineColour = colour; + wxCHECK_RET(colour.Ok(), wxT("Invalid colour in wxSheet::SetLabelOutlineColour")); + GetSheetRefData()->m_labelOutlineColour = colour; - RefreshColLabelWindow(true); - RefreshRowLabelWindow(true); - RefreshCornerLabelWindow(true); + RefreshColLabelWindow(true); + RefreshRowLabelWindow(true); + RefreshCornerLabelWindow(true); } // ---------------------------------------------------------------------------- // Spanned cells -bool wxSheet::HasSpannedCells() const +bool wxSheet::HasSpannedCells() const { return GetTable() && GetTable()->HasSpannedCells(); } +wxSheetCoords wxSheet::GetCellOwner(const wxSheetCoords &coords) const { - return GetTable() && GetTable()->HasSpannedCells(); + return GetCellBlock(coords).GetLeftTop(); } -wxSheetCoords wxSheet::GetCellOwner( const wxSheetCoords& coords ) const +wxSheetBlock wxSheet::GetCellBlock(const wxSheetCoords &coords) const { - return GetCellBlock(coords).GetLeftTop(); + return GetTable() ? GetTable()->GetCellBlock(coords) : wxSheetBlock(coords, 1, 1); } -wxSheetBlock wxSheet::GetCellBlock( const wxSheetCoords& coords ) const +wxSheetCoords wxSheet::GetCellSpan(const wxSheetCoords &coords) const { - return GetTable() ? GetTable()->GetCellBlock(coords) : wxSheetBlock(coords, 1, 1); + const wxSheetBlock block(GetCellBlock(coords)); + if (coords == block.GetLeftTop()) { + return block.GetSize(); + } + else { + return block.GetLeftTop() - coords; + } } -wxSheetCoords wxSheet::GetCellSpan( const wxSheetCoords& coords ) const +void wxSheet::SetCellSpan(const wxSheetBlock &block) { - const wxSheetBlock block(GetCellBlock(coords)); - if (coords == block.GetLeftTop()) - return block.GetSize(); - else - return block.GetLeftTop() - coords; -} -void wxSheet::SetCellSpan( const wxSheetBlock& block ) -{ - wxCHECK_RET(GetTable(), wxT("The wxSheetTable doesn't exist to SetCellSpan")); - GetTable()->SetCellSpan(block); + wxCHECK_RET(GetTable(), wxT("The wxSheetTable doesn't exist to SetCellSpan")); + GetTable()->SetCellSpan(block); } // **************************************************************************** -wxSheetCellAttr wxSheet::GetOrCreateAttr(const wxSheetCoords& coords, wxSheetAttr_Type type) const -{ - wxSheetCellAttr attr; - wxCHECK_MSG( type != wxSHEET_AttrAny, attr, wxT("Cannot create attribute of type wxSHEET_AttrAny") ); - - if (IsGridCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : return DoGetDefaultGridAttr(); - case wxSHEET_AttrCell : - case wxSHEET_AttrRow : - case wxSHEET_AttrCol : - { - wxCHECK_MSG(GetTable() && ContainsGridCell(coords), attr, wxT("Invalid table or attr coords")); - attr = GetTable()->GetAttr(coords, type); - if ( !attr.Ok() ) - { - attr.Create(); - attr.SetKind(type); - attr.SetDefaultAttr(DoGetDefaultGridAttr()); - GetTable()->SetAttr(coords, attr, type); - } - else - InitAttr(attr, DoGetDefaultGridAttr()); +wxSheetCellAttr wxSheet::GetOrCreateAttr(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + wxSheetCellAttr attr; + wxCHECK_MSG(type != wxSHEET_AttrAny, attr, + wxT("Cannot create attribute of type wxSHEET_AttrAny")); + + if (IsGridCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: + return DoGetDefaultGridAttr(); + case wxSHEET_AttrCell: + case wxSHEET_AttrRow: + case wxSHEET_AttrCol: { + wxCHECK_MSG(GetTable() && ContainsGridCell(coords), attr, + wxT("Invalid table or attr coords")); + attr = GetTable()->GetAttr(coords, type); + if (!attr.Ok()) { + attr.Create(); + attr.SetKind(type); + attr.SetDefaultAttr(DoGetDefaultGridAttr()); + GetTable()->SetAttr(coords, attr, type); + } + else { + InitAttr(attr, DoGetDefaultGridAttr()); + } + + return attr; + } + default: { + wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); + return attr; + } + } + } + else if (IsCornerLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: // only one of these, ever + case wxSHEET_AttrCell: + return DoGetDefaultCornerLabelAttr(); + default: { + wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); + return attr; + } + } + } + else if (IsRowLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: + return DoGetDefaultRowLabelAttr(); + case wxSHEET_AttrCell: { + wxCHECK_MSG(GetTable() && ContainsRowLabelCell(coords), attr, + wxT("Invalid table or attr coords")); + attr = GetTable()->GetAttr(coords, type); + if (!attr.Ok()) { + attr.Create(); + attr.SetKind(type); + attr.SetDefaultAttr(DoGetDefaultRowLabelAttr()); + GetTable()->SetAttr(coords, attr, type); + } + else { + InitAttr(attr, DoGetDefaultRowLabelAttr()); + } + + return attr; + } + default: { + wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); + return attr; + } + } + } + else if (IsColLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: + return DoGetDefaultColLabelAttr(); + case wxSHEET_AttrCell: { + wxCHECK_MSG(GetTable() && ContainsColLabelCell(coords), attr, + wxT("Invalid table or attr coords")); + attr = GetTable()->GetAttr(coords, type); + if (!attr.Ok()) { + attr.Create(); + attr.SetKind(type); + attr.SetDefaultAttr(DoGetDefaultColLabelAttr()); + GetTable()->SetAttr(coords, attr, type); + } + else { + InitAttr(attr, DoGetDefaultColLabelAttr()); + } + + return attr; + } + default: { + wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); + return attr; + } + } + } + + wxFAIL_MSG(wxString::Format(wxT("Unable to get or create attribute for cell(%d,%d)"), + coords.m_row, coords.m_col)); + return wxSheetCellAttr(); +} + +wxSheetCellAttr wxSheet::GetAttr(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + if (IsGridCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: + return DoGetDefaultGridAttr(); + case wxSHEET_AttrCell: + case wxSHEET_AttrRow: + case wxSHEET_AttrCol: + case wxSHEET_AttrAny: + default: { + wxCHECK_MSG(ContainsGridCell(coords), DoGetDefaultGridAttr(), wxT("Invalid attr coords")); + wxSheetCellAttr attr; + + if (!LookupAttr(coords, type, attr)) { + if (GetTable()) { + attr = GetTable()->GetAttr(coords, type); + if (attr.Ok()) { + CacheAttr(coords, attr, type); + } + } + } + + if ((type == wxSHEET_AttrAny) && !attr.Ok()) { + attr = DoGetDefaultGridAttr(); + } + + return attr; + } + } + } + else if (IsCornerLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: + case wxSHEET_AttrCell: // only one of these, ever + case wxSHEET_AttrAny: + return DoGetDefaultCornerLabelAttr(); + default: { + wxFAIL_MSG(wxT("Invalid attr type for corner label")); + } + } + + return wxNullSheetCellAttr; + } + else if (IsRowLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: + return DoGetDefaultRowLabelAttr(); + case wxSHEET_AttrCell: + case wxSHEET_AttrAny: { + wxCHECK_MSG(ContainsRowLabelCell(coords), DoGetDefaultRowLabelAttr(), + wxT("Invalid attr coords")); + wxSheetCellAttr attr; + if (GetTable()) { + attr = GetTable()->GetAttr(coords, type); + } + if ((type == wxSHEET_AttrAny) && !attr.Ok()) { + attr = DoGetDefaultRowLabelAttr(); + } + + return attr; + } + default: { + wxFAIL_MSG(wxT("Invalid attr type for row label")); + } + } + } + else if (IsColLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: + return DoGetDefaultColLabelAttr(); + case wxSHEET_AttrCell: + case wxSHEET_AttrAny: { + wxCHECK_MSG(ContainsColLabelCell(coords), DoGetDefaultColLabelAttr(), + wxT("Invalid attr coords")); + wxSheetCellAttr attr; + if (GetTable()) { + attr = GetTable()->GetAttr(coords, type); + } + if ((type == wxSHEET_AttrAny) && !attr.Ok()) { + attr = DoGetDefaultColLabelAttr(); + } + + return attr; + } + default: { + wxFAIL_MSG(wxT("Invalid attr type for col label")); + } + } + } + + // return garbage, maybe they can hobble along for a bit this way + wxFAIL_MSG(wxString::Format(wxT("Unable to get attribute for cell(%d,%d)"), coords.m_row, + coords.m_col)); + return wxSheetCellAttr(true); +} + +void wxSheet::SetAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr_, + wxSheetAttr_Type type) +{ + wxCHECK_RET(attr_.Ok(), wxT("Invalid attribute in wxSheet::SetDefaultAttr")); + wxCHECK_RET(type != wxSHEET_AttrAny, wxT("Cannot create attribute of type wxSHEET_AttrAny")); + wxSheetCellAttr attr(attr_); + ClearAttrCache(); + + if (IsGridCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: { + wxSheetCellAttr defAttr(DoGetDefaultGridAttr()); + defAttr.UpdateWith(attr); + // force good vals after update + defAttr.SetDefaultAttr(wxNullSheetCellAttr); + defAttr.SetKind(wxSHEET_AttrDefault); + return; + } + case wxSHEET_AttrCell: + case wxSHEET_AttrRow: + case wxSHEET_AttrCol: { + wxCHECK_RET(GetTable() && ContainsGridCell(coords), wxT("Invalid table or attr coords")); + if (attr.Ok()) { + InitAttr(attr, DoGetDefaultGridAttr()); + } + + GetTable()->SetAttr(coords, attr, type); + return; + } + default: { + wxFAIL_MSG(wxT("Invalid attr type for grid cell")); + return; + } + } + } + else if (IsCornerLabelCell(coords)) { + // only one attr for the corner window + switch (type) { + case wxSHEET_AttrDefault: + case wxSHEET_AttrCell: { + wxSheetCellAttr defAttr(DoGetDefaultCornerLabelAttr()); + defAttr.UpdateWith(attr); + // force good vals after update + defAttr.SetDefaultAttr(wxNullSheetCellAttr); + defAttr.SetKind(wxSHEET_AttrDefault); + return; + } + default: { + wxFAIL_MSG(wxT("Invalid attr type for corner label")); + return; + } + } + } + else if (IsRowLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: { + wxSheetCellAttr defAttr(DoGetDefaultRowLabelAttr()); + defAttr.UpdateWith(attr); + // force good vals after update + defAttr.SetDefaultAttr(wxNullSheetCellAttr); + defAttr.SetKind(wxSHEET_AttrDefault); + return; + } + case wxSHEET_AttrCell: { + wxCHECK_RET(GetTable() && ContainsRowLabelCell(coords), wxT("Invalid table or attr coords")); + if (attr.Ok()) { + InitAttr(attr, DoGetDefaultRowLabelAttr()); + } + + GetTable()->SetAttr(coords, attr, type); + return; + } + default: { + wxFAIL_MSG(wxT("Invalid attr type for row label")); + return; + } + } + } + else if (IsColLabelCell(coords)) { + switch (type) { + case wxSHEET_AttrDefault: { + wxSheetCellAttr defAttr(DoGetDefaultRowLabelAttr()); + defAttr.UpdateWith(attr); + // force good vals after update + defAttr.SetDefaultAttr(wxNullSheetCellAttr); + defAttr.SetKind(wxSHEET_AttrDefault); + return; + } + case wxSHEET_AttrCell: { + wxCHECK_RET(GetTable() && ContainsColLabelCell(coords), wxT("Invalid table or attr coords")); + if (attr.Ok()) { + InitAttr(attr, DoGetDefaultColLabelAttr()); + } + + GetTable()->SetAttr(coords, attr, type); + return; + } + default: { + wxFAIL_MSG(wxT("Invalid attr type for col label")); + return; + } + } + } + + wxFAIL_MSG(wxString::Format(wxT("Unable to set attribute for cell(%d,%d)"), coords.m_row, + coords.m_col)); +} + +bool wxSheet::InitAttr(wxSheetCellAttr &initAttr, const wxSheetCellAttr &defAttr) const +{ + if (initAttr == defAttr) { + return false; + } - return attr; - } - default : - { - wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); - return attr; - } - } + wxSheetCellAttr attr(initAttr); + wxSheetCellAttr attrDef(attr.GetDefaultAttr()); + // only 100000 def attr, should be enough? + for (int n = 0; n < 100000; n++) { + if (!attrDef.Ok()) { + attr.SetDefaultAttr(defAttr); + return true; } - else if (IsCornerLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : // only one of these, ever - case wxSHEET_AttrCell : return DoGetDefaultCornerLabelAttr(); - default : - { - wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); - return attr; - } - } + else if (attrDef == defAttr) { + return false; // already set } - else if (IsRowLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : return DoGetDefaultRowLabelAttr(); - case wxSHEET_AttrCell : - { - wxCHECK_MSG(GetTable() && ContainsRowLabelCell(coords), attr, wxT("Invalid table or attr coords")); - attr = GetTable()->GetAttr(coords, type); - if ( !attr.Ok() ) - { - attr.Create(); - attr.SetKind(type); - attr.SetDefaultAttr(DoGetDefaultRowLabelAttr()); - GetTable()->SetAttr(coords, attr, type); - } - else - InitAttr(attr, DoGetDefaultRowLabelAttr()); - return attr; - } - default : - { - wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); - return attr; - } - } - } - else if (IsColLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : return DoGetDefaultColLabelAttr(); - case wxSHEET_AttrCell : - { - wxCHECK_MSG(GetTable() && ContainsColLabelCell(coords), attr, wxT("Invalid table or attr coords")); - attr = GetTable()->GetAttr(coords, type); - if ( !attr.Ok() ) - { - attr.Create(); - attr.SetKind(type); - attr.SetDefaultAttr(DoGetDefaultColLabelAttr()); - GetTable()->SetAttr(coords, attr, type); - } - else - InitAttr(attr, DoGetDefaultColLabelAttr()); + attr = attrDef; + attrDef = attr.GetDefaultAttr(); + } - return attr; - } - default : - { - wxFAIL_MSG(wxT("Grid cell attribute kind invalid for GetOrCreateAttr")); - return attr; - } - } - } + wxFAIL_MSG(wxT("Unable to set default attribute for cell")); + return false; +} - wxFAIL_MSG(wxString::Format(wxT("Unable to get or create attribute for cell(%d,%d)"), coords.m_row, coords.m_col)); - return wxSheetCellAttr(); +const wxColour &wxSheet::GetAttrBackgroundColour(const wxSheetCoords &coords, + wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetBackgroundColour(); +} +const wxColour &wxSheet::GetAttrForegoundColour(const wxSheetCoords &coords, + wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetForegroundColour(); +} +const wxFont &wxSheet::GetAttrFont(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetFont(); +} +int wxSheet::GetAttrAlignment(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetAlignment(); +} +int wxSheet::GetAttrOrientation(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetOrientation(); +} +int wxSheet::GetAttrLevel(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetLevel(); +} +bool wxSheet::GetAttrOverflow(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetOverflow(); +} +bool wxSheet::GetAttrOverflowMarker(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetOverflowMarker(); +} +bool wxSheet::GetAttrShowEditor(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetShowEditor(); +} +bool wxSheet::GetAttrReadOnly(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetReadOnly(); +} +wxSheetCellRenderer wxSheet::GetAttrRenderer(const wxSheetCoords &coords, + wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetRenderer((wxSheet *)this, coords); +} +wxSheetCellEditor wxSheet::GetAttrEditor(const wxSheetCoords &coords, wxSheetAttr_Type type) const +{ + return GetAttr(coords, type).GetEditor((wxSheet *)this, coords); } -wxSheetCellAttr wxSheet::GetAttr(const wxSheetCoords& coords, wxSheetAttr_Type type) const +void wxSheet::SetAttrBackgroundColour(const wxSheetCoords &coords, const wxColour &colour, + wxSheetAttr_Type type) { - if (IsGridCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : return DoGetDefaultGridAttr(); - case wxSHEET_AttrCell : - case wxSHEET_AttrRow : - case wxSHEET_AttrCol : - case wxSHEET_AttrAny : - default : - { - wxCHECK_MSG(ContainsGridCell(coords), DoGetDefaultGridAttr(), wxT("Invalid attr coords")); - wxSheetCellAttr attr; + GetOrCreateAttr(coords, type).SetBackgroundColour(colour); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrForegroundColour(const wxSheetCoords &coords, const wxColour &colour, + wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetForegroundColour(colour); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrFont(const wxSheetCoords &coords, const wxFont &font, wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetFont(font); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrAlignment(const wxSheetCoords &coords, int align, wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetAlignment(align); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrOrientation(const wxSheetCoords &coords, int orient, wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetOrientation(orient); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrLevel(const wxSheetCoords &coords, int level, wxSheetAttr_Type type) +{ + wxCHECK_RET(type != wxSHEET_AttrDefault, wxT("Unable to change level of default attribute")); + GetOrCreateAttr(coords, type).SetLevel(wxSheetAttrLevel_Type(level)); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrOverflow(const wxSheetCoords &coords, bool allow, wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetOverflow(allow); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrOverflowMarker(const wxSheetCoords &coords, bool draw_marker, + wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetOverflowMarker(draw_marker); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrShowEditor(const wxSheetCoords &coords, bool show_editor, + wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetShowEditor(show_editor); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrReadOnly(const wxSheetCoords &coords, bool isReadOnly, wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetReadOnly(isReadOnly); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrRenderer(const wxSheetCoords &coords, const wxSheetCellRenderer &renderer, + wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetRenderer(renderer); + RefreshAttrChange(coords, type); +} +void wxSheet::SetAttrEditor(const wxSheetCoords &coords, const wxSheetCellEditor &editor, + wxSheetAttr_Type type) +{ + GetOrCreateAttr(coords, type).SetEditor(editor); + RefreshAttrChange(coords, type); +} - if ( !LookupAttr(coords, type, attr) ) - { - if (GetTable()) - { - attr = GetTable()->GetAttr(coords, type); - if (attr.Ok()) - CacheAttr(coords, attr, type); - } - } +// ---------------------------------------------------------------------------- +// Get/Set the attributes for individual sheet cells/rows/cols - if ((type == wxSHEET_AttrAny) && !attr.Ok()) - attr = DoGetDefaultGridAttr(); +void wxSheet::SetColFormatFloat(int col, int width, int precision) +{ + wxString typeName = wxSHEET_VALUE_FLOAT; + if ((width != -1) || (precision != -1)) { + typeName << _T(':') << width << _T(',') << precision; + } - return attr; - } - } - } - else if (IsCornerLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : - case wxSHEET_AttrCell : // only one of these, ever - case wxSHEET_AttrAny : return DoGetDefaultCornerLabelAttr(); - default : - { - wxFAIL_MSG(wxT("Invalid attr type for corner label")); - } - } - - return wxNullSheetCellAttr; - } - else if (IsRowLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : return DoGetDefaultRowLabelAttr(); - case wxSHEET_AttrCell : - case wxSHEET_AttrAny : - { - wxCHECK_MSG(ContainsRowLabelCell(coords), DoGetDefaultRowLabelAttr(), wxT("Invalid attr coords")); - wxSheetCellAttr attr; - if (GetTable()) - attr = GetTable()->GetAttr(coords, type); - if ((type == wxSHEET_AttrAny) && !attr.Ok()) - attr = DoGetDefaultRowLabelAttr(); - - return attr; - } - default : - { - wxFAIL_MSG(wxT("Invalid attr type for row label")); - } - } - } - else if (IsColLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : return DoGetDefaultColLabelAttr(); - case wxSHEET_AttrCell : - case wxSHEET_AttrAny : - { - wxCHECK_MSG(ContainsColLabelCell(coords), DoGetDefaultColLabelAttr(), wxT("Invalid attr coords")); - wxSheetCellAttr attr; - if (GetTable()) - attr = GetTable()->GetAttr(coords, type); - if ((type == wxSHEET_AttrAny) && !attr.Ok()) - attr = DoGetDefaultColLabelAttr(); - - return attr; - } - default : - { - wxFAIL_MSG(wxT("Invalid attr type for col label")); - } - } - } - - // return garbage, maybe they can hobble along for a bit this way - wxFAIL_MSG(wxString::Format(wxT("Unable to get attribute for cell(%d,%d)"), coords.m_row, coords.m_col)); - return wxSheetCellAttr(true); -} - -void wxSheet::SetAttr(const wxSheetCoords& coords, - const wxSheetCellAttr& attr_, wxSheetAttr_Type type) -{ - wxCHECK_RET(attr_.Ok(), wxT("Invalid attribute in wxSheet::SetDefaultAttr")); - wxCHECK_RET( type != wxSHEET_AttrAny, wxT("Cannot create attribute of type wxSHEET_AttrAny") ); - wxSheetCellAttr attr(attr_); - ClearAttrCache(); - - if (IsGridCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : - { - wxSheetCellAttr defAttr(DoGetDefaultGridAttr()); - defAttr.UpdateWith(attr); - // force good vals after update - defAttr.SetDefaultAttr(wxNullSheetCellAttr); - defAttr.SetKind(wxSHEET_AttrDefault); - return; - } - case wxSHEET_AttrCell : - case wxSHEET_AttrRow : - case wxSHEET_AttrCol : - { - wxCHECK_RET(GetTable() && ContainsGridCell(coords), wxT("Invalid table or attr coords")); - if (attr.Ok()) - InitAttr(attr, DoGetDefaultGridAttr()); - - GetTable()->SetAttr(coords, attr, type); - return; - } - default : - { - wxFAIL_MSG(wxT("Invalid attr type for grid cell")); - return; - } - } - } - else if (IsCornerLabelCell(coords)) - { - // only one attr for the corner window - switch (type) - { - case wxSHEET_AttrDefault : - case wxSHEET_AttrCell : - { - wxSheetCellAttr defAttr(DoGetDefaultCornerLabelAttr()); - defAttr.UpdateWith(attr); - // force good vals after update - defAttr.SetDefaultAttr(wxNullSheetCellAttr); - defAttr.SetKind(wxSHEET_AttrDefault); - return; - } - default : - { - wxFAIL_MSG(wxT("Invalid attr type for corner label")); - return; - } - } - } - else if (IsRowLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : - { - wxSheetCellAttr defAttr(DoGetDefaultRowLabelAttr()); - defAttr.UpdateWith(attr); - // force good vals after update - defAttr.SetDefaultAttr(wxNullSheetCellAttr); - defAttr.SetKind(wxSHEET_AttrDefault); - return; - } - case wxSHEET_AttrCell : - { - wxCHECK_RET(GetTable() && ContainsRowLabelCell(coords), wxT("Invalid table or attr coords")); - if (attr.Ok()) - InitAttr(attr, DoGetDefaultRowLabelAttr()); - - GetTable()->SetAttr(coords, attr, type); - return; - } - default : - { - wxFAIL_MSG(wxT("Invalid attr type for row label")); - return; - } - } - } - else if (IsColLabelCell(coords)) - { - switch (type) - { - case wxSHEET_AttrDefault : - { - wxSheetCellAttr defAttr(DoGetDefaultRowLabelAttr()); - defAttr.UpdateWith(attr); - // force good vals after update - defAttr.SetDefaultAttr(wxNullSheetCellAttr); - defAttr.SetKind(wxSHEET_AttrDefault); - return; - } - case wxSHEET_AttrCell : - { - wxCHECK_RET(GetTable() && ContainsColLabelCell(coords), wxT("Invalid table or attr coords")); - if (attr.Ok()) - InitAttr(attr, DoGetDefaultColLabelAttr()); - - GetTable()->SetAttr(coords, attr, type); - return; - } - default : - { - wxFAIL_MSG(wxT("Invalid attr type for col label")); - return; - } - } - } - - wxFAIL_MSG(wxString::Format(wxT("Unable to set attribute for cell(%d,%d)"), coords.m_row, coords.m_col)); -} - -bool wxSheet::InitAttr( wxSheetCellAttr& initAttr, const wxSheetCellAttr& defAttr ) const -{ - if (initAttr == defAttr) - return false; - - wxSheetCellAttr attr(initAttr); - wxSheetCellAttr attrDef(attr.GetDefaultAttr()); - // only 100000 def attr, should be enough? - for (int n=0; n<100000; n++) - { - if (!attrDef.Ok()) - { - attr.SetDefaultAttr(defAttr); - return true; - } - else if (attrDef == defAttr) - { - return false; // already set - } - - attr = attrDef; - attrDef = attr.GetDefaultAttr(); - } - - wxFAIL_MSG(wxT("Unable to set default attribute for cell")); - return false; -} - -const wxColour& wxSheet::GetAttrBackgroundColour( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetBackgroundColour(); -} -const wxColour& wxSheet::GetAttrForegoundColour( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetForegroundColour(); -} -const wxFont& wxSheet::GetAttrFont( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetFont(); -} -int wxSheet::GetAttrAlignment( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetAlignment(); -} -int wxSheet::GetAttrOrientation( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetOrientation(); -} -int wxSheet::GetAttrLevel( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetLevel(); -} -bool wxSheet::GetAttrOverflow( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetOverflow(); -} -bool wxSheet::GetAttrOverflowMarker( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetOverflowMarker(); -} -bool wxSheet::GetAttrShowEditor( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetShowEditor(); -} -bool wxSheet::GetAttrReadOnly( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetReadOnly(); -} -wxSheetCellRenderer wxSheet::GetAttrRenderer( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetRenderer((wxSheet*)this, coords); -} -wxSheetCellEditor wxSheet::GetAttrEditor( const wxSheetCoords& coords, wxSheetAttr_Type type ) const -{ - return GetAttr(coords, type).GetEditor((wxSheet*)this, coords); -} - -void wxSheet::SetAttrBackgroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetBackgroundColour(colour); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrForegroundColour( const wxSheetCoords& coords, const wxColour& colour, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetForegroundColour(colour); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrFont( const wxSheetCoords& coords, const wxFont& font, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetFont(font); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrAlignment( const wxSheetCoords& coords, int align, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetAlignment(align); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrOrientation( const wxSheetCoords& coords, int orient, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetOrientation(orient); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrLevel( const wxSheetCoords& coords, int level, wxSheetAttr_Type type ) -{ - wxCHECK_RET(type != wxSHEET_AttrDefault, wxT("Unable to change level of default attribute")); - GetOrCreateAttr(coords, type).SetLevel(wxSheetAttrLevel_Type(level)); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrOverflow( const wxSheetCoords& coords, bool allow, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetOverflow(allow); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrOverflowMarker( const wxSheetCoords& coords, bool draw_marker, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetOverflowMarker(draw_marker); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrShowEditor( const wxSheetCoords& coords, bool show_editor, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetShowEditor(show_editor); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrReadOnly( const wxSheetCoords& coords, bool isReadOnly, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetReadOnly(isReadOnly); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrRenderer( const wxSheetCoords& coords, const wxSheetCellRenderer& renderer, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetRenderer(renderer); - RefreshAttrChange(coords, type); -} -void wxSheet::SetAttrEditor( const wxSheetCoords& coords, const wxSheetCellEditor& editor, wxSheetAttr_Type type ) -{ - GetOrCreateAttr(coords, type).SetEditor(editor); - RefreshAttrChange(coords, type); -} - -// ---------------------------------------------------------------------------- -// Get/Set the attributes for individual sheet cells/rows/cols - -void wxSheet::SetColFormatFloat(int col, int width, int precision) -{ - wxString typeName = wxSHEET_VALUE_FLOAT; - if ( (width != -1) || (precision != -1) ) - typeName << _T(':') << width << _T(',') << precision; - - SetColFormatCustom(col, typeName); -} -void wxSheet::SetColFormatCustom(int col, const wxString& typeName) -{ - wxCHECK_RET(ContainsGridCol(col), wxT("Invalid col in wxSheet::SetColFormatCustom")); - wxSheetCellRenderer ren(GetDefaultRendererForType(typeName)); - wxCHECK_RET(ren.Ok(), wxT("Invalid renderer in wxSheet::SetColFormatCustom")); - SetAttrRenderer(wxSheetCoords(0,col), ren.Clone(), wxSHEET_AttrCol); -} + SetColFormatCustom(col, typeName); +} +void wxSheet::SetColFormatCustom(int col, const wxString &typeName) +{ + wxCHECK_RET(ContainsGridCol(col), wxT("Invalid col in wxSheet::SetColFormatCustom")); + wxSheetCellRenderer ren(GetDefaultRendererForType(typeName)); + wxCHECK_RET(ren.Ok(), wxT("Invalid renderer in wxSheet::SetColFormatCustom")); + SetAttrRenderer(wxSheetCoords(0, col), ren.Clone(), wxSHEET_AttrCol); +} // ---------------------------------------------------------------------------- // Get/Set cell value -wxString wxSheet::GetCellValue( const wxSheetCoords& coords ) +wxString wxSheet::GetCellValue(const wxSheetCoords &coords) { - if ( GetTable() ) - return GetTable()->GetValue( coords ); + if (GetTable()) { + return GetTable()->GetValue(coords); + } - return wxEmptyString; + return wxEmptyString; } -void wxSheet::SetCellValue( const wxSheetCoords& coords, const wxString& s ) +void wxSheet::SetCellValue(const wxSheetCoords &coords, const wxString &s) { - wxCHECK_RET( GetTable(), wxT("Invalid sheet table for SetCellValue")); - GetTable()->SetValue( coords, s ); + wxCHECK_RET(GetTable(), wxT("Invalid sheet table for SetCellValue")); + GetTable()->SetValue(coords, s); - // Note: If we are using IsCellEditControlEnabled, - // this interacts badly with calling SetCellValue from - // an EVT_SHEET_CELL_CHANGE handler. - if ((GetEditControlCoords() == coords) && IsCellEditControlShown()) - { - HideCellEditControl(); - ShowCellEditControl(); // will reread data from table - } - else - RefreshCell(coords, false); + // Note: If we are using IsCellEditControlEnabled, + // this interacts badly with calling SetCellValue from + // an EVT_SHEET_CELL_CHANGE handler. + if ((GetEditControlCoords() == coords) && IsCellEditControlShown()) { + HideCellEditControl(); + ShowCellEditControl(); // will reread data from table + } + else { + RefreshCell(coords, false); + } } -bool wxSheet::HasCellValue( const wxSheetCoords& coords ) +bool wxSheet::HasCellValue(const wxSheetCoords &coords) { - if ( GetTable() ) - return GetTable()->HasValue( coords ); + if (GetTable()) { + return GetTable()->HasValue(coords); + } - // this tries the table too, but maybe they've only overridden GetCellValue - return !GetCellValue(coords).IsEmpty(); + // this tries the table too, but maybe they've only overridden GetCellValue + return !GetCellValue(coords).IsEmpty(); } // ---------------------------------------------------------------------------- // Register mapping between data types to Renderers/Editors -void wxSheet::RegisterDataType(const wxString& typeName, - const wxSheetCellRenderer& renderer, - const wxSheetCellEditor& editor) +void wxSheet::RegisterDataType(const wxString &typeName, const wxSheetCellRenderer &renderer, + const wxSheetCellEditor &editor) { - GetSheetRefData()->m_typeRegistry->RegisterDataType(typeName, renderer, editor); + GetSheetRefData()->m_typeRegistry->RegisterDataType(typeName, renderer, editor); } -wxSheetCellEditor wxSheet::GetDefaultEditorForType(const wxString& typeName) const +wxSheetCellEditor wxSheet::GetDefaultEditorForType(const wxString &typeName) const { - int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(typeName); - wxCHECK_MSG(index != wxNOT_FOUND, wxNullSheetCellEditor, wxT("Unknown data type name")); + int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(typeName); + wxCHECK_MSG(index != wxNOT_FOUND, wxNullSheetCellEditor, wxT("Unknown data type name")); - return GetSheetRefData()->m_typeRegistry->GetEditor(index); + return GetSheetRefData()->m_typeRegistry->GetEditor(index); } -wxSheetCellRenderer wxSheet::GetDefaultRendererForType(const wxString& typeName) const +wxSheetCellRenderer wxSheet::GetDefaultRendererForType(const wxString &typeName) const { - int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(typeName); - wxCHECK_MSG(index != wxNOT_FOUND, wxNullSheetCellRenderer, wxT("Unknown data type name")); + int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(typeName); + wxCHECK_MSG(index != wxNOT_FOUND, wxNullSheetCellRenderer, wxT("Unknown data type name")); - return GetSheetRefData()->m_typeRegistry->GetRenderer(index); + return GetSheetRefData()->m_typeRegistry->GetRenderer(index); } -wxSheetCellEditor wxSheet::GetDefaultEditorForCell(const wxSheetCoords& coords) const +wxSheetCellEditor wxSheet::GetDefaultEditorForCell(const wxSheetCoords &coords) const { - wxCHECK_MSG(GetTable(), wxNullSheetCellEditor, wxT("Grid table is not created")); - //return GetDefaultEditorForType(GetTable()->GetTypeName(coords)); - - // Default is to NOT use this as a default, but the defAttr's editor - int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(GetTable()->GetTypeName(coords)); - if (index == wxNOT_FOUND) - return wxNullSheetCellEditor; + wxCHECK_MSG(GetTable(), wxNullSheetCellEditor, wxT("Grid table is not created")); + // return GetDefaultEditorForType(GetTable()->GetTypeName(coords)); - return GetSheetRefData()->m_typeRegistry->GetEditor(index); + // Default is to NOT use this as a default, but the defAttr's editor + int index = + GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(GetTable()->GetTypeName(coords)); + if (index == wxNOT_FOUND) { + return wxNullSheetCellEditor; + } + return GetSheetRefData()->m_typeRegistry->GetEditor(index); } -wxSheetCellRenderer wxSheet::GetDefaultRendererForCell(const wxSheetCoords& coords) const +wxSheetCellRenderer wxSheet::GetDefaultRendererForCell(const wxSheetCoords &coords) const { - if (!GetTable()) return wxNullSheetCellRenderer; - //return GetDefaultRendererForType(GetTable()->GetTypeName(coords)); + if (!GetTable()) { + return wxNullSheetCellRenderer; + } + // return GetDefaultRendererForType(GetTable()->GetTypeName(coords)); - // Default is to NOT use this as a default, but the defAttr's renderer - int index = GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(GetTable()->GetTypeName(coords)); - if (index == wxNOT_FOUND) - return wxNullSheetCellRenderer; + // Default is to NOT use this as a default, but the defAttr's renderer + int index = + GetSheetRefData()->m_typeRegistry->FindOrCloneDataType(GetTable()->GetTypeName(coords)); + if (index == wxNOT_FOUND) { + return wxNullSheetCellRenderer; + } - return GetSheetRefData()->m_typeRegistry->GetRenderer(index); + return GetSheetRefData()->m_typeRegistry->GetRenderer(index); } // ---------------------------------------------------------------------------- // Cursor movement and visibility functions -bool wxSheet::IsCellVisible( const wxSheetCoords& coords, bool wholeCellVisible ) const +bool wxSheet::IsCellVisible(const wxSheetCoords &coords, bool wholeCellVisible) const { - wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords in wxSheet::IsCellVisible")); + wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords in wxSheet::IsCellVisible")); - const wxRect clientRect(wxPoint(0,0), GetWindowForCoords(coords)->GetClientSize()); - const wxRect devRect(CellToRect(coords, true)); // rect in device coords + const wxRect clientRect(wxPoint(0, 0), GetWindowForCoords(coords)->GetClientSize()); + const wxRect devRect(CellToRect(coords, true)); // rect in device coords - if ( wholeCellVisible ) // is the whole cell visible? - { - wxRect intersectRect( devRect.Intersect(clientRect) ); - return intersectRect == devRect; - } + if (wholeCellVisible) // is the whole cell visible? + { + wxRect intersectRect(devRect.Intersect(clientRect)); + return intersectRect == devRect; + } - return devRect.Intersects(clientRect); // is the cell partly visible ? + return devRect.Intersects(clientRect); // is the cell partly visible ? } -bool wxSheet::IsRowVisible( int row, bool wholeRowVisible ) const +bool wxSheet::IsRowVisible(int row, bool wholeRowVisible) const { - if (row == -1) - return m_colLabelWin && m_colLabelWin->IsShown(); + if (row == -1) { + return m_colLabelWin && m_colLabelWin->IsShown(); + } - wxCHECK_MSG(ContainsGridRow(row), false, wxT("Invalid row in wxSheet::IsRowVisible")); + wxCHECK_MSG(ContainsGridRow(row), false, wxT("Invalid row in wxSheet::IsRowVisible")); - const wxRect clientRect(wxPoint(0,0), m_gridWin->GetClientSize()); - const wxRect logRect(0, GetRowTop(row), clientRect.width, GetRowHeight(row)); - const wxRect devRect(clientRect.x, CalcScrolledRect(logRect).y, logRect.width, logRect.height); + const wxRect clientRect(wxPoint(0, 0), m_gridWin->GetClientSize()); + const wxRect logRect(0, GetRowTop(row), clientRect.width, GetRowHeight(row)); + const wxRect devRect(clientRect.x, CalcScrolledRect(logRect).y, logRect.width, logRect.height); - if (wholeRowVisible) // is the whole row visible? - { - wxRect intersectRect( devRect.Intersect(clientRect) ); - return intersectRect == devRect; - } + if (wholeRowVisible) // is the whole row visible? + { + wxRect intersectRect(devRect.Intersect(clientRect)); + return intersectRect == devRect; + } - return devRect.Intersects(clientRect); // is the cell partly visible ? + return devRect.Intersects(clientRect); // is the cell partly visible ? } -bool wxSheet::IsColVisible( int col, bool wholeColVisible ) const +bool wxSheet::IsColVisible(int col, bool wholeColVisible) const { - if (col == -1) - return m_rowLabelWin && m_rowLabelWin->IsShown(); + if (col == -1) { + return m_rowLabelWin && m_rowLabelWin->IsShown(); + } - wxCHECK_MSG(ContainsGridCol(col), false, wxT("Invalid row in wxSheet::IsColVisible")); + wxCHECK_MSG(ContainsGridCol(col), false, wxT("Invalid row in wxSheet::IsColVisible")); - const wxRect clientRect(wxPoint(0,0), m_gridWin->GetClientSize()); - const wxRect logRect(GetColLeft(col), 0, GetColWidth(col), clientRect.height); - const wxRect devRect(CalcScrolledRect(logRect).x, clientRect.y, logRect.width, logRect.height); + const wxRect clientRect(wxPoint(0, 0), m_gridWin->GetClientSize()); + const wxRect logRect(GetColLeft(col), 0, GetColWidth(col), clientRect.height); + const wxRect devRect(CalcScrolledRect(logRect).x, clientRect.y, logRect.width, logRect.height); - if (wholeColVisible) // is the whole row visible? - { - wxRect intersectRect( devRect.Intersect(clientRect) ); - return intersectRect == devRect; - } + if (wholeColVisible) // is the whole row visible? + { + wxRect intersectRect(devRect.Intersect(clientRect)); + return intersectRect == devRect; + } - return devRect.Intersects(clientRect); // is the cell partly visible ? + return devRect.Intersects(clientRect); // is the cell partly visible ? } -void wxSheet::MakeCellVisible( const wxSheetCoords& coords ) +void wxSheet::MakeCellVisible(const wxSheetCoords &coords) { - wxCHECK_RET(ContainsCell(coords), wxT("Invalid coords in wxSheet::MakeCellVisible")); + wxCHECK_RET(ContainsCell(coords), wxT("Invalid coords in wxSheet::MakeCellVisible")); - if (IsCornerLabelCell(coords)) - return; + if (IsCornerLabelCell(coords)) { + return; + } - int xpos = -1, ypos = -1; + int xpos = -1, ypos = -1; - const wxRect logRect( CellToRect(coords) ); // cell rect in logical coords - const wxRect devRect( CalcScrolledRect(logRect) ); // rect in device coords + const wxRect logRect(CellToRect(coords)); // cell rect in logical coords + const wxRect devRect(CalcScrolledRect(logRect)); // rect in device coords - int x0, y0, cw, ch; - m_gridWin->GetClientSize( &cw, &ch ); - CalcUnscrolledPosition(0, 0, &x0, &y0); + int x0, y0, cw, ch; + m_gridWin->GetClientSize(&cw, &ch); + CalcUnscrolledPosition(0, 0, &x0, &y0); - if (!IsColLabelCell(coords)) - { - if ( devRect.GetTop() < 0 ) - { - ypos = logRect.GetTop(); - ypos -= SHEET_SCROLL_LINE_Y; // add a little padding - if (ypos < 0) ypos = 0; - } - else if ( devRect.GetBottom() > ch ) - { - ypos = y0 + (devRect.GetBottom() - ch); - ypos += SHEET_SCROLL_LINE_Y; - if (ypos < 0) ypos = 0; - } + if (!IsColLabelCell(coords)) { + if (devRect.GetTop() < 0) { + ypos = logRect.GetTop(); + ypos -= SHEET_SCROLL_LINE_Y; // add a little padding + if (ypos < 0) { + ypos = 0; + } } + else if (devRect.GetBottom() > ch) { + ypos = y0 + (devRect.GetBottom() - ch); + ypos += SHEET_SCROLL_LINE_Y; + if (ypos < 0) { + ypos = 0; + } + } + } - if (!IsRowLabelCell(coords)) - { - if ( devRect.GetLeft() < 0 ) - { - xpos = logRect.GetLeft(); - xpos -= SHEET_SCROLL_LINE_X; - if (xpos < 0) xpos = 0; - } - else if ( devRect.GetRight() > cw ) - { - xpos = x0 + (devRect.GetRight() - cw); - xpos += SHEET_SCROLL_LINE_X; - if (xpos < 0) xpos = 0; - } - + if (!IsRowLabelCell(coords)) { + if (devRect.GetLeft() < 0) { + xpos = logRect.GetLeft(); + xpos -= SHEET_SCROLL_LINE_X; + if (xpos < 0) { + xpos = 0; + } } + else if (devRect.GetRight() > cw) { + xpos = x0 + (devRect.GetRight() - cw); + xpos += SHEET_SCROLL_LINE_X; + if (xpos < 0) { + xpos = 0; + } + } + } - // -1 means leave that postion the same, see if (x/ypos < 0) x/ypos = 0 above - if ((xpos != -1) || (ypos != -1)) - SetGridOrigin( xpos, ypos, true, true ); + // -1 means leave that postion the same, see if (x/ypos < 0) x/ypos = 0 above + if ((xpos != -1) || (ypos != -1)) { + SetGridOrigin(xpos, ypos, true, true); + } } -void wxSheet::SetGridCursorCell( const wxSheetCoords& coords ) +void wxSheet::SetGridCursorCell(const wxSheetCoords &coords) { - // Note: can set to invalid coords < 0 to hide cursor, but not out of range - wxCHECK_RET((coords.GetRow() < GetNumberRows()) && - (coords.GetCol() < GetNumberCols()), - wxT("Invalid coords in wxSheet::SetGridCursorCell")); - - if (GetGridCursorCell() == coords) - return; + // Note: can set to invalid coords < 0 to hide cursor, but not out of range + wxCHECK_RET((coords.GetRow() < GetNumberRows()) && (coords.GetCol() < GetNumberCols()), + wxT("Invalid coords in wxSheet::SetGridCursorCell")); - m_waitForSlowClick = false; + if (GetGridCursorCell() == coords) { + return; + } - // the event has been intercepted - do nothing - if (SendEvent(wxEVT_SHEET_SELECTING_CELL, coords) != EVT_SKIPPED) - return; + m_waitForSlowClick = false; - const wxSheetCoords oldCursorCell(GetGridCursorCell()); - if ( ContainsGridCell(oldCursorCell) ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); + // the event has been intercepted - do nothing + if (SendEvent(wxEVT_SHEET_SELECTING_CELL, coords) != EVT_SKIPPED) { + return; + } - // Otherwise refresh redraws the highlight! - GetSheetRefData()->m_cursorCoords = coords; - RefreshCell(oldCursorCell, true); + const wxSheetCoords oldCursorCell(GetGridCursorCell()); + if (ContainsGridCell(oldCursorCell)) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } + // Otherwise refresh redraws the highlight! GetSheetRefData()->m_cursorCoords = coords; + RefreshCell(oldCursorCell, true); + } + + GetSheetRefData()->m_cursorCoords = coords; - if (ContainsGridCell(GetGridCursorCell())) - RefreshCell(GetGridCursorCell(), true); + if (ContainsGridCell(GetGridCursorCell())) { + RefreshCell(GetGridCursorCell(), true); + } - SendEvent(wxEVT_SHEET_SELECTED_CELL, coords); + SendEvent(wxEVT_SHEET_SELECTED_CELL, coords); } -bool wxSheet::DoMoveCursor( const wxSheetCoords& relCoords, bool expandSelection ) +bool wxSheet::DoMoveCursor(const wxSheetCoords &relCoords, bool expandSelection) { - const wxSheetCoords cursorCoords(GetGridCursorCell()); - const wxSheetCoords coords( cursorCoords + relCoords ); - if ( (relCoords == wxSheetCoords(0,0)) || - !ContainsGridCell(cursorCoords) || !ContainsGridCell(coords) ) - return false; + const wxSheetCoords cursorCoords(GetGridCursorCell()); + const wxSheetCoords coords(cursorCoords + relCoords); + if ((relCoords == wxSheetCoords(0, 0)) || !ContainsGridCell(cursorCoords) || + !ContainsGridCell(coords)) { + return false; + } - if ( expandSelection) - { - m_keySelecting = true; - if ( !ContainsGridCell(GetSelectingAnchor()) ) - SetSelectingAnchor(cursorCoords); + if (expandSelection) { + m_keySelecting = true; + if (!ContainsGridCell(GetSelectingAnchor())) { + SetSelectingAnchor(cursorCoords); } - else - ClearSelection(true); + } + else { + ClearSelection(true); + } - MakeCellVisible( coords ); - SetGridCursorCell( coords ); - if (expandSelection && !HasSelectionMode(wxSHEET_SelectNone)) - HighlightSelectingBlock( GetSelectingAnchor(), GetGridCursorCell() ); + MakeCellVisible(coords); + SetGridCursorCell(coords); + if (expandSelection && !HasSelectionMode(wxSHEET_SelectNone)) { + HighlightSelectingBlock(GetSelectingAnchor(), GetGridCursorCell()); + } - return true; + return true; } -bool wxSheet::DoMoveCursorBlock( const wxSheetCoords& relDir, bool expandSelection ) +bool wxSheet::DoMoveCursorBlock(const wxSheetCoords &relDir, bool expandSelection) { - const wxSheetCoords cursorCoords(GetGridCursorCell()); - wxSheetCoords coords(cursorCoords + relDir); - if ( !ContainsGridCell(cursorCoords) || !ContainsGridCell(coords) ) - return false; + const wxSheetCoords cursorCoords(GetGridCursorCell()); + wxSheetCoords coords(cursorCoords + relDir); + if (!ContainsGridCell(cursorCoords) || !ContainsGridCell(coords)) { + return false; + } - if ( !HasCellValue(cursorCoords) ) - { - // starting in an empty cell: find the next block of non-empty cells - while ( ContainsGridCell(coords) ) - { - if (HasCellValue(coords) || !ContainsGridCell(coords + relDir)) - break; + if (!HasCellValue(cursorCoords)) { + // starting in an empty cell: find the next block of non-empty cells + while (ContainsGridCell(coords)) { + if (HasCellValue(coords) || !ContainsGridCell(coords + relDir)) { + break; + } - coords += relDir; - } + coords += relDir; } - else if ( !HasCellValue(coords) ) - { - // starting at the edge of a block: find the next block - while ( ContainsGridCell(coords + relDir) ) - { - coords += relDir; - if ( HasCellValue(coords) ) - break; - } + } + else if (!HasCellValue(coords)) { + // starting at the edge of a block: find the next block + while (ContainsGridCell(coords + relDir)) { + coords += relDir; + if (HasCellValue(coords)) { + break; + } } - else - { - // starting within a block with value: find the edge of the block - while ( ContainsGridCell(coords + relDir) ) - { - if ( !HasCellValue(coords + relDir) ) - break; + } + else { + // starting within a block with value: find the edge of the block + while (ContainsGridCell(coords + relDir)) { + if (!HasCellValue(coords + relDir)) { + break; + } - coords += relDir; - } + coords += relDir; } + } - return DoMoveCursor(coords-cursorCoords, expandSelection); + return DoMoveCursor(coords - cursorCoords, expandSelection); } -bool wxSheet::DoMoveCursorUpDownPage( bool page_up, bool expandSelection ) +bool wxSheet::DoMoveCursorUpDownPage(bool page_up, bool expandSelection) { - if (!ContainsGridCell(GetGridCursorCell())) - return false; + if (!ContainsGridCell(GetGridCursorCell())) { + return false; + } - const int row = GetGridCursorRow(); + const int row = GetGridCursorRow(); - if ((page_up && (row < 1)) || (!page_up && (row >= GetNumberRows() - 1))) - return false; + if ((page_up && (row < 1)) || (!page_up && (row >= GetNumberRows() - 1))) { + return false; + } - int cw, ch; - m_gridWin->GetClientSize( &cw, &ch ); + int cw, ch; + m_gridWin->GetClientSize(&cw, &ch); - int y = GetRowTop(row) + (page_up ? (-ch + 1) : ch); - const int newRow = YToGridRow( y, true ); - return DoMoveCursor(wxSheetCoords(newRow - row, 0), expandSelection); + int y = GetRowTop(row) + (page_up ? (-ch + 1) : ch); + const int newRow = YToGridRow(y, true); + return DoMoveCursor(wxSheetCoords(newRow - row, 0), expandSelection); } // ---------------------------------------------------------------------------- @@ -2229,237 +2261,253 @@ bool wxSheet::DoMoveCursorUpDownPage( bool page_up, bool expandSelection ) bool wxSheet::HasSelection(bool selecting) const { - if (selecting) - return (!GetSelectingBlock().IsEmpty() || - (GetSelection() && GetSelection()->HasSelection())); + if (selecting) { + return (!GetSelectingBlock().IsEmpty() || (GetSelection() && GetSelection()->HasSelection())); + } - return GetSelection() && GetSelection()->HasSelection(); + return GetSelection() && GetSelection()->HasSelection(); } -bool wxSheet::IsCellSelected( const wxSheetCoords& coords ) const +bool wxSheet::IsCellSelected(const wxSheetCoords &coords) const { - return ( GetSelectingBlock().Contains(coords) || - (GetSelection() && GetSelection()->Contains(coords)) ); + return (GetSelectingBlock().Contains(coords) || + (GetSelection() && GetSelection()->Contains(coords))); } -bool wxSheet::IsRowSelected( int row ) const +bool wxSheet::IsRowSelected(int row) const { - wxSheetBlock rowBlock(row, 0, 1, GetNumberCols()); // not +1 - return ( GetSelectingBlock().Contains(rowBlock) || - (GetSelection() && GetSelection()->Contains(rowBlock)) ); + wxSheetBlock rowBlock(row, 0, 1, GetNumberCols()); // not +1 + return (GetSelectingBlock().Contains(rowBlock) || + (GetSelection() && GetSelection()->Contains(rowBlock))); } -bool wxSheet::IsColSelected( int col ) const +bool wxSheet::IsColSelected(int col) const { - wxSheetBlock colBlock(0, col, GetNumberRows(), 1); // not +1 - return ( GetSelectingBlock().Contains(colBlock) || - (GetSelection() && GetSelection()->Contains(colBlock)) ); + wxSheetBlock colBlock(0, col, GetNumberRows(), 1); // not +1 + return (GetSelectingBlock().Contains(colBlock) || + (GetSelection() && GetSelection()->Contains(colBlock))); } void wxSheet::SetSelectionMode(wxSheetSelectionMode_Type selmode) { - wxCHECK_RET( GetSelection(), - wxT("Called wxSheet::SetSelectionMode() before calling CreateGrid()") ); + wxCHECK_RET(GetSelection(), + wxT("Called wxSheet::SetSelectionMode() before calling CreateGrid()")); - // yes we could patch up the selection, but does it really make sense? - // like you'd have to send a slew of confusing (de)selection events - ClearSelection(true); - GetSheetRefData()->m_selectionMode = selmode; + // yes we could patch up the selection, but does it really make sense? + // like you'd have to send a slew of confusing (de)selection events + ClearSelection(true); + GetSheetRefData()->m_selectionMode = selmode; } -bool wxSheet::SelectRow( int row, bool addToSelected, bool sendEvt ) +bool wxSheet::SelectRow(int row, bool addToSelected, bool sendEvt) { - if (HasSelectionMode(wxSHEET_SelectCols)) - return false; + if (HasSelectionMode(wxSHEET_SelectCols)) { + return false; + } - // selection to # of cols means whole row is selected - return SelectBlock( wxSheetBlock(row, 0, 1, GetNumberCols()+1), - addToSelected, sendEvt ); + // selection to # of cols means whole row is selected + return SelectBlock(wxSheetBlock(row, 0, 1, GetNumberCols() + 1), addToSelected, sendEvt); } -bool wxSheet::SelectRows( int rowTop, int rowBottom, bool addToSelected, bool sendEvt ) +bool wxSheet::SelectRows(int rowTop, int rowBottom, bool addToSelected, bool sendEvt) { - if (HasSelectionMode(wxSHEET_SelectCols) || (rowTop > rowBottom)) - return false; + if (HasSelectionMode(wxSHEET_SelectCols) || (rowTop > rowBottom)) { + return false; + } - // selection to # of cols means whole row is selected - return SelectBlock( wxSheetBlock(rowTop, 0, rowBottom-rowTop+1, GetNumberCols()+1), - addToSelected, sendEvt ); + // selection to # of cols means whole row is selected + return SelectBlock(wxSheetBlock(rowTop, 0, rowBottom - rowTop + 1, GetNumberCols() + 1), + addToSelected, sendEvt); } -bool wxSheet::SelectCol( int col, bool addToSelected, bool sendEvt ) +bool wxSheet::SelectCol(int col, bool addToSelected, bool sendEvt) { - if (HasSelectionMode(wxSHEET_SelectRows)) - return false; + if (HasSelectionMode(wxSHEET_SelectRows)) { + return false; + } - // selection to # of rows means whole col is selected - return SelectBlock( wxSheetBlock(0, col, GetNumberRows()+1, 1), - addToSelected, sendEvt ); + // selection to # of rows means whole col is selected + return SelectBlock(wxSheetBlock(0, col, GetNumberRows() + 1, 1), addToSelected, sendEvt); } -bool wxSheet::SelectCols( int colLeft, int colRight, bool addToSelected, bool sendEvt ) +bool wxSheet::SelectCols(int colLeft, int colRight, bool addToSelected, bool sendEvt) { - if (HasSelectionMode(wxSHEET_SelectRows) || (colLeft > colRight)) - return false; + if (HasSelectionMode(wxSHEET_SelectRows) || (colLeft > colRight)) { + return false; + } - // selection to # of rows means whole col is selected - return SelectBlock( wxSheetBlock(0, colLeft, GetNumberRows()+1, colRight-colLeft+1), - addToSelected, sendEvt ); + // selection to # of rows means whole col is selected + return SelectBlock(wxSheetBlock(0, colLeft, GetNumberRows() + 1, colRight - colLeft + 1), + addToSelected, sendEvt); } -bool wxSheet::SelectCell( const wxSheetCoords& coords, bool addToSelected, bool sendEvt ) +bool wxSheet::SelectCell(const wxSheetCoords &coords, bool addToSelected, bool sendEvt) { - return SelectBlock(wxSheetBlock(coords, 1, 1), addToSelected, sendEvt); + return SelectBlock(wxSheetBlock(coords, 1, 1), addToSelected, sendEvt); } -bool wxSheet::SelectBlock( const wxSheetBlock& block, bool addToSelected, bool sendEvt ) +bool wxSheet::SelectBlock(const wxSheetBlock &block, bool addToSelected, bool sendEvt) { - if (!GetSelection()) - return false; - - if ( !addToSelected ) - ClearSelection(sendEvt); + if (!GetSelection()) { + return false; + } - wxArraySheetBlock addedBlocks; - if (!GetSelection()->SelectBlock( block, true, &addedBlocks )) - return false; + if (!addToSelected) { + ClearSelection(sendEvt); + } - if (!GetBatchCount()) - { - wxSheetBlock bounds; + wxArraySheetBlock addedBlocks; + if (!GetSelection()->SelectBlock(block, true, &addedBlocks)) { + return false; + } - for (size_t n=0; n rowBottom)) - return false; + if (HasSelectionMode(wxSHEET_SelectCols) || (rowTop > rowBottom)) { + return false; + } - // selection to # of cols means whole row is deselected - return DeselectBlock( wxSheetBlock(rowTop, 0, rowBottom-rowTop+1, GetNumberCols()+1), - sendEvt ); + // selection to # of cols means whole row is deselected + return DeselectBlock(wxSheetBlock(rowTop, 0, rowBottom - rowTop + 1, GetNumberCols() + 1), + sendEvt); } -bool wxSheet::DeselectCol( int col, bool sendEvt ) +bool wxSheet::DeselectCol(int col, bool sendEvt) { - if (HasSelectionMode(wxSHEET_SelectRows)) - return false; + if (HasSelectionMode(wxSHEET_SelectRows)) { + return false; + } - // deselection to # of rows means whole col is deselected - return DeselectBlock( wxSheetBlock(0, col, GetNumberRows(), 1), sendEvt ); + // deselection to # of rows means whole col is deselected + return DeselectBlock(wxSheetBlock(0, col, GetNumberRows(), 1), sendEvt); } -bool wxSheet::DeselectCols( int colLeft, int colRight, bool sendEvt ) +bool wxSheet::DeselectCols(int colLeft, int colRight, bool sendEvt) { - if (HasSelectionMode(wxSHEET_SelectRows) || (colLeft > colRight)) - return false; + if (HasSelectionMode(wxSHEET_SelectRows) || (colLeft > colRight)) { + return false; + } - // selection to # of rows means whole col is deselected - return DeselectBlock( wxSheetBlock(0, colLeft, GetNumberRows()+1, colRight-colLeft+1), - sendEvt ); + // selection to # of rows means whole col is deselected + return DeselectBlock(wxSheetBlock(0, colLeft, GetNumberRows() + 1, colRight - colLeft + 1), + sendEvt); } -bool wxSheet::DeselectCell( const wxSheetCoords& coords, bool sendEvt ) +bool wxSheet::DeselectCell(const wxSheetCoords &coords, bool sendEvt) { - return DeselectBlock(wxSheetBlock(coords, 1, 1), sendEvt); + return DeselectBlock(wxSheetBlock(coords, 1, 1), sendEvt); } -bool wxSheet::DeselectBlock( const wxSheetBlock& block, bool sendEvt ) +bool wxSheet::DeselectBlock(const wxSheetBlock &block, bool sendEvt) { - if (!GetSelection()) - return false; - - // do they want to clear the whole grid - wxSheetBlock gridBlock(0, 0, GetNumberRows(), GetNumberCols()); - if (gridBlock.Intersect(block) == gridBlock) - return ClearSelection(sendEvt); + if (!GetSelection()) { + return false; + } - wxArraySheetBlock deletedBlocks; - if (!GetSelection()->DeselectBlock( block, true, &deletedBlocks )) - return false; + // do they want to clear the whole grid + wxSheetBlock gridBlock(0, 0, GetNumberRows(), GetNumberCols()); + if (gridBlock.Intersect(block) == gridBlock) { + return ClearSelection(sendEvt); + } - if (!GetBatchCount()) - { - wxSheetBlock bounds; + wxArraySheetBlock deletedBlocks; + if (!GetSelection()->DeselectBlock(block, true, &deletedBlocks)) { + return false; + } - for (size_t n=0; nGetBoundingBlock())); - SetSelectingBlock(wxNullSheetBlock); - GetSelection()->Clear(); + wxSheetBlock bounds(GetSelectingBlock().ExpandUnion(GetSelection()->GetBoundingBlock())); + SetSelectingBlock(wxNullSheetBlock); + GetSelection()->Clear(); - RefreshGridCellBlock(bounds); + RefreshGridCellBlock(bounds); - if (send_event) - { - // One deselection event, indicating deselection of _all_ cells. - SendRangeEvent( wxEVT_SHEET_RANGE_SELECTED, - wxSheetBlock(0, 0, GetNumberRows(), GetNumberCols()), - false, false ); - } + if (send_event) { + // One deselection event, indicating deselection of _all_ cells. + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTED, + wxSheetBlock(0, 0, GetNumberRows(), GetNumberCols()), false, false); + } - return true; + return true; } -bool wxSheet::ToggleCellSelection( const wxSheetCoords& coords, bool addToSelected, bool sendEvt ) +bool wxSheet::ToggleCellSelection(const wxSheetCoords &coords, bool addToSelected, bool sendEvt) { - int sel = IsCellSelected(coords); - if (!sel) - return SelectCell(coords, addToSelected, sendEvt); + int sel = IsCellSelected(coords); + if (!sel) { + return SelectCell(coords, addToSelected, sendEvt); + } - return DeselectCell(coords, sendEvt ); + return DeselectCell(coords, sendEvt); } -bool wxSheet::ToggleRowSelection( int row, bool addToSelected, bool sendEvt ) +bool wxSheet::ToggleRowSelection(int row, bool addToSelected, bool sendEvt) { - int sel = IsRowSelected(row); - if (!sel) - return SelectRow(row, addToSelected, sendEvt); + int sel = IsRowSelected(row); + if (!sel) { + return SelectRow(row, addToSelected, sendEvt); + } - return DeselectRow(row, sendEvt ); + return DeselectRow(row, sendEvt); } -bool wxSheet::ToggleColSelection( int col, bool addToSelected, bool sendEvt ) +bool wxSheet::ToggleColSelection(int col, bool addToSelected, bool sendEvt) { - int sel = IsColSelected(col); - if (!sel) - return SelectCol(col, addToSelected, sendEvt); + int sel = IsColSelected(col); + if (!sel) { + return SelectCol(col, addToSelected, sendEvt); + } - return DeselectCol(col, sendEvt ); + return DeselectCol(col, sendEvt); } // ---------------------------------------------------------------------------- @@ -2467,40 +2515,46 @@ bool wxSheet::ToggleColSelection( int col, bool addToSelected, bool sendEvt ) #include "wx/dataobj.h" -//#define wxDF_wxSHEET (wxDF_MAX+1001) // works w/ GTK 1.2 non unicode -const wxChar* wxDF_wxSHEET = wxT("wxDF_wxSHEET"); +// #define wxDF_wxSHEET (wxDF_MAX+1001) // works w/ GTK 1.2 non unicode +const wxChar *wxDF_wxSHEET = wxT("wxDF_wxSHEET"); -class wxSheetDataObject : public wxDataObjectSimple -{ +class wxSheetDataObject : public wxDataObjectSimple { public: - wxSheetDataObject() : wxDataObjectSimple(wxDF_wxSHEET) {} - wxSheetDataObject(const wxSheetValueProviderSparseString &values) - : wxDataObjectSimple(wxDF_wxSHEET), m_values(values) - { - CreateDataString(); - m_values.ClearValues(); - } + wxSheetDataObject() : wxDataObjectSimple(wxDF_wxSHEET) {} + wxSheetDataObject(const wxSheetValueProviderSparseString &values) + : wxDataObjectSimple(wxDF_wxSHEET), m_values(values) + { + CreateDataString(); + m_values.ClearValues(); + } - virtual size_t GetDataSize() const { return (m_data.Len()+1)*sizeof(wxChar); } - virtual bool GetDataHere(void *buf) const; - virtual bool SetData(size_t len, const void *buf); + virtual size_t GetDataSize() const { return (m_data.Len() + 1) * sizeof(wxChar); } + virtual bool GetDataHere(void *buf) const; + virtual bool SetData(size_t len, const void *buf); - const wxSheetValueProviderSparseString& GetValues() const { return m_values; } + const wxSheetValueProviderSparseString &GetValues() const { return m_values; } - void CreateDataString(); + void CreateDataString(); protected: - wxSheetValueProviderSparseString m_values; - wxString m_data; + wxSheetValueProviderSparseString m_values; + wxString m_data; + private: - // I don't understand these? from include/wx/gtk/dataobj2.h - // virtual function hiding supression - size_t GetDataSize(const wxDataFormat& format) const - { return(wxDataObjectSimple::GetDataSize(format)); } - bool GetDataHere(const wxDataFormat& format, void* pBuf) const - { return(wxDataObjectSimple::GetDataHere(format, pBuf)); } - bool SetData(const wxDataFormat& format, size_t nLen, const void* pBuf) - { return(wxDataObjectSimple::SetData(format, nLen, pBuf)); } + // I don't understand these? from include/wx/gtk/dataobj2.h + // virtual function hiding supression + size_t GetDataSize(const wxDataFormat &format) const + { + return (wxDataObjectSimple::GetDataSize(format)); + } + bool GetDataHere(const wxDataFormat &format, void *pBuf) const + { + return (wxDataObjectSimple::GetDataHere(format, pBuf)); + } + bool SetData(const wxDataFormat &format, size_t nLen, const void *pBuf) + { + return (wxDataObjectSimple::SetData(format, nLen, pBuf)); + } }; // FIXME! this is just a hack and kinda works @@ -2509,16 +2563,16 @@ const wxString s_nextCol(wxT("\1\2"), 2); // end of value marker const wxString s_newRow(wxT("\1\3"), 2); // specify a row number const wxString s_newCol(wxT("\1\4"), 2); // specify a col number -//const wxString s_nextRow(wxT("s")); // just increment row number -//const wxString s_nextCol(wxT("d")); // end of value marker -//const wxString s_newRow(wxT("r")); // specify a row number -//const wxString s_newCol(wxT("c")); // specify a col number -// Data string looks like this: `r23c12:size:some data string` -// 'r' followed by a number specifies a row # -// without a number means next row -// 'c' followed by a number specifies a col # -// without a number means next col -// size is the number of chars of the data string +// const wxString s_nextRow(wxT("s")); // just increment row number +// const wxString s_nextCol(wxT("d")); // end of value marker +// const wxString s_newRow(wxT("r")); // specify a row number +// const wxString s_newCol(wxT("c")); // specify a col number +// Data string looks like this: `r23c12:size:some data string` +// 'r' followed by a number specifies a row # +// without a number means next row +// 'c' followed by a number specifies a col # +// without a number means next col +// size is the number of chars of the data string // Data string looks like this: start by specifying the row and col number // then data and end data marker (s_nextCol) more data, if you skip cols @@ -2527,557 +2581,587 @@ const wxString s_newCol(wxT("\1\4"), 2); // specify a col number void wxSheetDataObject::CreateDataString() { - m_data.Clear(); - wxPairArrayIntPairArraySheetString &values = m_values.GetData(); - m_values.RemoveEmpty(); + m_data.Clear(); + wxPairArrayIntPairArraySheetString &values = m_values.GetData(); + m_values.RemoveEmpty(); - if (values.GetCount() == 0u) - return; + if (values.GetCount() == 0u) { + return; + } - int c, ncols, r, nrows = values.GetCount(); - int row, col; - int last_row = values.GetItemKey(0) - 10, last_col; + int c, ncols, r, nrows = values.GetCount(); + int row, col; + int last_row = values.GetItemKey(0) - 10, last_col; - for (r=0; rOpen()) - return false; + if (!wxTheClipboard->Open()) { + return false; + } - // save data to clipboard, we want the internal data back if possible - wxDataObjectComposite *data = new wxDataObjectComposite; - data->Add(new wxSheetDataObject(GetSheetRefData()->m_copiedData), true); - data->Add(new wxTextDataObject(CopyInternalSelectionToString(colSep)), false); - wxTheClipboard->SetData( data ); + // save data to clipboard, we want the internal data back if possible + wxDataObjectComposite *data = new wxDataObjectComposite; + data->Add(new wxSheetDataObject(GetSheetRefData()->m_copiedData), true); + data->Add(new wxTextDataObject(CopyInternalSelectionToString(colSep)), false); + wxTheClipboard->SetData(data); - wxTheClipboard->Close(); - return true; + wxTheClipboard->Close(); + return true; } -bool wxSheet::CopyCurrentSelectionToClipboard(bool copy_cursor, const wxChar& colSep) +bool wxSheet::CopyCurrentSelectionToClipboard(bool copy_cursor, const wxChar &colSep) { - CopyCurrentSelectionInternal(copy_cursor); - return CopyInternalSelectionToClipboard(colSep); + CopyCurrentSelectionInternal(copy_cursor); + return CopyInternalSelectionToClipboard(colSep); } -bool wxSheet::PasteFromClipboard( const wxSheetCoords &topLeft, - const wxChar& colSep ) +bool wxSheet::PasteFromClipboard(const wxSheetCoords &topLeft, const wxChar &colSep) { - if ( !wxTheClipboard->Open() ) - return false; + if (!wxTheClipboard->Open()) { + return false; + } - bool ret = false; + bool ret = false; - wxSheetDataObject sheetData; - if (wxTheClipboard->IsSupported(wxDF_wxSHEET) && wxTheClipboard->GetData(sheetData)) - { - GetSheetRefData()->m_copiedData = sheetData.GetValues(); - ret = PasteInternalCopiedSelection( topLeft ); - } - else if (wxTheClipboard->IsSupported(wxDF_TEXT)) - { - wxTextDataObject textData; - if (wxTheClipboard->GetData(textData)) - { - CopyStringToSelection(textData.GetText(), colSep); - ret = PasteInternalCopiedSelection( topLeft ); - } + wxSheetDataObject sheetData; + if (wxTheClipboard->IsSupported(wxDF_wxSHEET) && wxTheClipboard->GetData(sheetData)) { + GetSheetRefData()->m_copiedData = sheetData.GetValues(); + ret = PasteInternalCopiedSelection(topLeft); + } + else if (wxTheClipboard->IsSupported(wxDF_TEXT)) { + wxTextDataObject textData; + if (wxTheClipboard->GetData(textData)) { + CopyStringToSelection(textData.GetText(), colSep); + ret = PasteInternalCopiedSelection(topLeft); } + } - wxTheClipboard->Close(); - return ret; + wxTheClipboard->Close(); + return ret; } bool wxSheet::CopyCurrentSelectionInternal(bool copy_cursor) { - wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); - copiedData.Clear(); + wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); + copiedData.Clear(); - wxSheetSelection sel = *GetSelection(); - if (!GetSelectingBlock().IsEmpty()) - sel.SelectBlock(GetSelectingBlock()); + wxSheetSelection sel = *GetSelection(); + if (!GetSelectingBlock().IsEmpty()) { + sel.SelectBlock(GetSelectingBlock()); + } - sel.SetBoundingBlock(wxSheetBlock(0, 0, GetNumberRows(), GetNumberCols())); + sel.SetBoundingBlock(wxSheetBlock(0, 0, GetNumberRows(), GetNumberCols())); - if (!sel.HasSelection()) - { - if (copy_cursor && ContainsGridCell(GetGridCursorCell())) - sel.SelectBlock(wxSheetBlock(GetGridCursorCell(), 1, 1)); - else - return false; + if (!sel.HasSelection()) { + if (copy_cursor && ContainsGridCell(GetGridCursorCell())) { + sel.SelectBlock(wxSheetBlock(GetGridCursorCell(), 1, 1)); + } + else { + return false; } + } - wxSheetSelectionIterator selIter(sel); - wxSheetCoords cell; - while (selIter.GetNext(cell)) - copiedData.GetOrCreateValue(cell.m_row).SetValue(cell.m_col, GetCellValue(cell)); + wxSheetSelectionIterator selIter(sel); + wxSheetCoords cell; + while (selIter.GetNext(cell)) { + copiedData.GetOrCreateValue(cell.m_row).SetValue(cell.m_col, GetCellValue(cell)); + } - return copiedData.GetCount() > 0; + return copiedData.GetCount() > 0; } -wxString wxSheet::CopyInternalSelectionToString(const wxChar& colSep) +wxString wxSheet::CopyInternalSelectionToString(const wxChar &colSep) { - wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); - wxString value; - GetSheetRefData()->m_copiedData.RemoveEmpty(); - if (copiedData.GetCount() == 0) - return value; + wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); + wxString value; + GetSheetRefData()->m_copiedData.RemoveEmpty(); + if (copiedData.GetCount() == 0) { + return value; + } - int i, r, c; - int row, col; - int nrows = copiedData.GetCount(); + int i, r, c; + int row, col; + int nrows = copiedData.GetCount(); - // find leftmost col - int left_col = copiedData.GetItemValue(0).GetItemKey(0); - for (r=1; r copiedData.GetItemValue(r).GetItemKey(0)) - left_col = copiedData.GetItemValue(r).GetItemKey(0); + // find leftmost col + int left_col = copiedData.GetItemValue(0).GetItemKey(0); + for (r = 1; r < nrows; r++) { + if (left_col > copiedData.GetItemValue(r).GetItemKey(0)) { + left_col = copiedData.GetItemValue(r).GetItemKey(0); } + } - int last_row=copiedData.GetItemKey(0), last_col=left_col; - for (r=0; rm_copiedData.GetData(); - copiedData.Clear(); + wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); + copiedData.Clear(); - if (string.IsEmpty()) - return false; + if (string.IsEmpty()) { + return false; + } - const wxChar *c = string.GetData(); - int n, len = string.Length(); + const wxChar *c = string.GetData(); + int n, len = string.Length(); - int row = 0, col = 0; - wxString buf; + int row = 0, col = 0; + wxString buf; - for (n=0; nm_copiedData.GetData(); - // clean up, shouldn't happen but don't want to have to check it later - GetSheetRefData()->m_copiedData.RemoveEmpty(); - if (copiedData.GetCount() == 0) return false; + wxPairArrayIntPairArraySheetString &copiedData = GetSheetRefData()->m_copiedData.GetData(); + // clean up, shouldn't happen but don't want to have to check it later + GetSheetRefData()->m_copiedData.RemoveEmpty(); + if (copiedData.GetCount() == 0) { + return false; + } - wxSheetBlock currentBlock = GetSelection()->GetBoundingBlock().ExpandUnion(GetSelectingBlock()); - bool is_selection = !currentBlock.IsEmpty(); + wxSheetBlock currentBlock = GetSelection()->GetBoundingBlock().ExpandUnion(GetSelectingBlock()); + bool is_selection = !currentBlock.IsEmpty(); - wxSheetCoords topLeft(topLeft_); - if (topLeft == wxNullSheetCoords) - { - if (is_selection) - topLeft = currentBlock.GetLeftTop(); - else - topLeft = GetGridCursorCell(); + wxSheetCoords topLeft(topLeft_); + if (topLeft == wxNullSheetCoords) { + if (is_selection) { + topLeft = currentBlock.GetLeftTop(); } + else { + topLeft = GetGridCursorCell(); + } + } - if (!ContainsGridCell(topLeft)) - return false; + if (!ContainsGridCell(topLeft)) { + return false; + } - wxSheetCoords copiedTopLeft( copiedData.GetItemKey(0), - copiedData.GetItemValue(0).GetItemKey(0) ); + wxSheetCoords copiedTopLeft(copiedData.GetItemKey(0), copiedData.GetItemValue(0).GetItemKey(0)); - wxSheetCoords shiftCell = topLeft - copiedTopLeft; + wxSheetCoords shiftCell = topLeft - copiedTopLeft; - GetSheetRefData()->m_pasting = true; + GetSheetRefData()->m_pasting = true; - wxSheetCoords cell, pasteCell; - size_t r, nrows = copiedData.GetCount(); - size_t c, ncols; - for (r=0; r= GetNumberRows()) - break; + // all done + if (cell.m_row + shiftCell.m_row >= GetNumberRows()) { + break; + } - for (c=0; c= GetNumberCols()) - break; - - const wxString& value = copiedData.GetItemValue(r).GetItemValue(c); - // only paste into selected cells if selection - if (is_selection && IsCellSelected(pasteCell)) - SetCellValue(pasteCell, value); - else - SetCellValue(pasteCell, value); - } + for (c = 0; c < ncols; c++) { + cell.m_col = copiedData.GetItemValue(r).GetItemKey(c); + pasteCell = cell + shiftCell; + if (pasteCell.m_col >= GetNumberCols()) { + break; + } + + const wxString &value = copiedData.GetItemValue(r).GetItemValue(c); + // only paste into selected cells if selection + if (is_selection && IsCellSelected(pasteCell)) { + SetCellValue(pasteCell, value); + } + else { + SetCellValue(pasteCell, value); + } } + } - GetSheetRefData()->m_pasting = false; - return true; + GetSheetRefData()->m_pasting = false; + return true; } // ---------------------------------------------------------------------------- // Edit control functions (mostly used internally) -void wxSheet::EnableEditing( bool edit ) +void wxSheet::EnableEditing(bool edit) { - // TODO: improve this ? - if ( edit != IsEditable() ) - { - if (!edit && IsCellEditControlCreated()) - DisableCellEditControl(true); - - GetSheetRefData()->m_editable = edit; + // TODO: improve this ? + if (edit != IsEditable()) { + if (!edit && IsCellEditControlCreated()) { + DisableCellEditControl(true); } + + GetSheetRefData()->m_editable = edit; + } } -bool wxSheet::EnableCellEditControl( const wxSheetCoords& coords_ ) +bool wxSheet::EnableCellEditControl(const wxSheetCoords &coords_) { - // move to owner cell since that's where the editor is - const wxSheetCoords coords(GetCellOwner(coords_)); - //wxCHECK_MSG(CanEnableCellControl(coords), false, _T("can't enable editing for this cell!")); - if (!CanEnableCellControl(coords)) { - return false; - } + // move to owner cell since that's where the editor is + const wxSheetCoords coords(GetCellOwner(coords_)); + // wxCHECK_MSG(CanEnableCellControl(coords), false, _T("can't enable editing for this cell!")); + if (!CanEnableCellControl(coords)) { + return false; + } - // already editing elsewhere, disable it - if (IsCellEditControlCreated() && !DisableCellEditControl(true)) - return false; + // already editing elsewhere, disable it + if (IsCellEditControlCreated() && !DisableCellEditControl(true)) { + return false; + } - if (SendEvent( wxEVT_SHEET_EDITOR_ENABLED, coords ) == EVT_VETOED) - return false; + if (SendEvent(wxEVT_SHEET_EDITOR_ENABLED, coords) == EVT_VETOED) { + return false; + } - // guarantee that it's visible - MakeCellVisible(coords); - GetSheetRefData()->m_cellEditorCoords = coords; + // guarantee that it's visible + MakeCellVisible(coords); + GetSheetRefData()->m_cellEditorCoords = coords; - // Get the appropriate editor for this cell - wxSheetCellAttr attr(GetAttr(coords)); - GetSheetRefData()->m_cellEditor = attr.GetEditor(this, coords); - if (!GetEditControl().Ok()) - { - GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; - wxFAIL_MSG(wxT("Unable to get cell edit control")); - return false; - } + // Get the appropriate editor for this cell + wxSheetCellAttr attr(GetAttr(coords)); + GetSheetRefData()->m_cellEditor = attr.GetEditor(this, coords); + if (!GetEditControl().Ok()) { + GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; + wxFAIL_MSG(wxT("Unable to get cell edit control")); + return false; + } - return ShowCellEditControl(); + return ShowCellEditControl(); } -bool wxSheet::DisableCellEditControl( bool save_value ) +bool wxSheet::DisableCellEditControl(bool save_value) { - //wxCHECK_RET(, wxT("Edit control not enabled in wxSheet::DisableCellEditControl")); - if (!IsCellEditControlCreated()) - { - // just in case something failed earlier, make sure it's gone - if (GetEditControl().Ok()) - GetSheetRefData()->m_cellEditor.Destroy(); - - GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; - return true; + // wxCHECK_RET(, wxT("Edit control not enabled in wxSheet::DisableCellEditControl")); + if (!IsCellEditControlCreated()) { + // just in case something failed earlier, make sure it's gone + if (GetEditControl().Ok()) { + GetSheetRefData()->m_cellEditor.Destroy(); } - if (SendEvent(wxEVT_SHEET_EDITOR_DISABLED, GetEditControlCoords()) == EVT_VETOED) - return false; - - if (save_value) - SaveEditControlValue(); - - HideCellEditControl(); - // FIXME always destroy it else memory leak, maybe fixed with handler OnDestroy - GetSheetRefData()->m_cellEditor.DestroyControl(); - GetSheetRefData()->m_cellEditor.Destroy(); GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; return true; + } + + if (SendEvent(wxEVT_SHEET_EDITOR_DISABLED, GetEditControlCoords()) == EVT_VETOED) { + return false; + } + + if (save_value) { + SaveEditControlValue(); + } + + HideCellEditControl(); + // FIXME always destroy it else memory leak, maybe fixed with handler OnDestroy + GetSheetRefData()->m_cellEditor.DestroyControl(); + GetSheetRefData()->m_cellEditor.Destroy(); + GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; + return true; } -bool wxSheet::CanEnableCellControl(const wxSheetCoords& coords) const +bool wxSheet::CanEnableCellControl(const wxSheetCoords &coords) const { - wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords")); - return IsEditable() && !GetAttr(coords).GetReadOnly(); + wxCHECK_MSG(ContainsCell(coords), false, wxT("Invalid coords")); + return IsEditable() && !GetAttr(coords).GetReadOnly(); } bool wxSheet::IsCellEditControlCreated() const { - return GetEditControl().Ok() && GetEditControl().IsCreated(); + return GetEditControl().Ok() && GetEditControl().IsCreated(); } bool wxSheet::IsCellEditControlShown() const { - return GetEditControl().Ok() && GetEditControl().IsCreated() && - GetEditControl().IsShown(); + return GetEditControl().Ok() && GetEditControl().IsCreated() && GetEditControl().IsShown(); } bool wxSheet::ShowCellEditControl() { - wxCHECK_MSG(CanEnableCellControl(GetEditControlCoords()), false, // also checks coords - wxT("Editor not enabled in wxSheet::ShowCellEditControl")); + wxCHECK_MSG(CanEnableCellControl(GetEditControlCoords()), false, // also checks coords + wxT("Editor not enabled in wxSheet::ShowCellEditControl")); - wxWindow *win = GetWindowForCoords(GetEditControlCoords()); + wxWindow *win = GetWindowForCoords(GetEditControlCoords()); - // If the control's parent is not correct we must recreate it - if (GetEditControl().GetControl() && (GetEditControl().GetControl()->GetParent() != win)) - GetSheetRefData()->m_cellEditor.DestroyControl(); + // If the control's parent is not correct we must recreate it + if (GetEditControl().GetControl() && (GetEditControl().GetControl()->GetParent() != win)) { + GetSheetRefData()->m_cellEditor.DestroyControl(); + } - // Make sure the editor is created - if (!GetEditControl().IsCreated()) - { - GetSheetRefData()->m_cellEditor.CreateEditor(win, -1, - new wxSheetCellEditorEvtHandler(this, GetEditControl()), - this); + // Make sure the editor is created + if (!GetEditControl().IsCreated()) { + GetSheetRefData()->m_cellEditor.CreateEditor( + win, -1, new wxSheetCellEditorEvtHandler(this, GetEditControl()), this); - wxSheetEditorCreatedEvent evt(GetId(), wxEVT_SHEET_EDITOR_CREATED, - this, GetEditControlCoords(), - GetSheetRefData()->m_cellEditor.GetControl()); - GetEventHandler()->ProcessEvent(evt); + wxSheetEditorCreatedEvent evt(GetId(), wxEVT_SHEET_EDITOR_CREATED, this, + GetEditControlCoords(), + GetSheetRefData()->m_cellEditor.GetControl()); + GetEventHandler()->ProcessEvent(evt); - if (!GetEditControl().IsCreated()) - { - // kill it all off, something went wrong - if (GetEditControl().GetControl()) - GetSheetRefData()->m_cellEditor.DestroyControl(); - - GetSheetRefData()->m_cellEditor.Destroy(); - GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; - wxFAIL_MSG(wxT("Unable to create edit control")); - return false; - } + if (!GetEditControl().IsCreated()) { + // kill it all off, something went wrong + if (GetEditControl().GetControl()) { + GetSheetRefData()->m_cellEditor.DestroyControl(); + } + + GetSheetRefData()->m_cellEditor.Destroy(); + GetSheetRefData()->m_cellEditorCoords = wxNullSheetCoords; + wxFAIL_MSG(wxT("Unable to create edit control")); + return false; } + } - wxSheetCellAttr attr(GetAttr(GetEditControlCoords())); + wxSheetCellAttr attr(GetAttr(GetEditControlCoords())); - // the rectangle bounding the cell - wxRect rect( CellToRect(GetEditControlCoords(), true) ); + // the rectangle bounding the cell + wxRect rect(CellToRect(GetEditControlCoords(), true)); - // FIXME use GetBestSize + // FIXME use GetBestSize - // resize editor to overflow into righthand cells if wider than cell - wxString value = GetCellValue(GetEditControlCoords()); - int clientWidth = win->GetClientSize().GetWidth(); - if (!value.IsEmpty() && attr.GetOverflow() && - (GetEditControlCoords().m_col < GetNumberCols())) - { - int w=rect.width, h=0; - // expand width if text only if text is wider than cell width - GetTextExtent(value, &w, &h, NULL, NULL, &attr.GetFont()); + // resize editor to overflow into righthand cells if wider than cell + wxString value = GetCellValue(GetEditControlCoords()); + int clientWidth = win->GetClientSize().GetWidth(); + if (!value.IsEmpty() && attr.GetOverflow() && (GetEditControlCoords().m_col < GetNumberCols())) { + int w = rect.width, h = 0; + // expand width if text only if text is wider than cell width + GetTextExtent(value, &w, &h, NULL, NULL, &attr.GetFont()); - if (w > rect.width) - { - wxSheetCoords cellSize(GetCellSpan(GetEditControlCoords())); - wxSheetCoords c(GetEditControlCoords()); - wxSheetCoords oneCell(1,1); - int numCols = GetNumberCols(); - for (c.m_col = c.m_col + cellSize.m_col; c.m_col < numCols; c.m_col++) - { - cellSize = GetCellSpan(c); - // looks weird going over a spanned cell - if ((rect.width < w) && (rect.GetRight() < clientWidth) && (cellSize == oneCell)) - rect.width += GetColWidth(c.m_col); - else - break; - } + if (w > rect.width) { + wxSheetCoords cellSize(GetCellSpan(GetEditControlCoords())); + wxSheetCoords c(GetEditControlCoords()); + wxSheetCoords oneCell(1, 1); + int numCols = GetNumberCols(); + for (c.m_col = c.m_col + cellSize.m_col; c.m_col < numCols; c.m_col++) { + cellSize = GetCellSpan(c); + // looks weird going over a spanned cell + if ((rect.width < w) && (rect.GetRight() < clientWidth) && (cellSize == oneCell)) { + rect.width += GetColWidth(c.m_col); + } + else { + break; } + } } + } - // clip width to window size - rect.width = wxMin(rect.width, clientWidth - rect.x); + // clip width to window size + rect.width = wxMin(rect.width, clientWidth - rect.x); - GetSheetRefData()->m_cellEditor.SetSize( rect, attr ); - GetSheetRefData()->m_cellEditor.Show( true, attr ); + GetSheetRefData()->m_cellEditor.SetSize(rect, attr); + GetSheetRefData()->m_cellEditor.Show(true, attr); - // recalc dimensions, maybe expand the scrolled window to account for editor - CalcWindowSizes(); + // recalc dimensions, maybe expand the scrolled window to account for editor + CalcWindowSizes(); - GetSheetRefData()->m_cellEditor.BeginEdit(GetEditControlCoords(), this); + GetSheetRefData()->m_cellEditor.BeginEdit(GetEditControlCoords(), this); - // FIXME other spreadsheets don't clear cells to right, it looks weird? why not? - // if this is empty, cell to right maybe overflowed into from left, clear it - //if (value.IsEmpty() && (m_cellEditorCoords.m_col < m_numCols - 1)) - // RefreshCell(m_cellEditorCoords+wxSheetCoords(0, 1)); + // FIXME other spreadsheets don't clear cells to right, it looks weird? why not? + // if this is empty, cell to right maybe overflowed into from left, clear it + // if (value.IsEmpty() && (m_cellEditorCoords.m_col < m_numCols - 1)) + // RefreshCell(m_cellEditorCoords+wxSheetCoords(0, 1)); - return true; + return true; } bool wxSheet::HideCellEditControl() { - wxCHECK_MSG(IsCellEditControlShown(), false, wxT("Edit control not shown in wxSheet::HideCellEditControl")); + wxCHECK_MSG(IsCellEditControlShown(), false, + wxT("Edit control not shown in wxSheet::HideCellEditControl")); - GetSheetRefData()->m_cellEditor.Show( false, GetAttr(GetEditControlCoords()) ); - m_gridWin->SetFocus(); - RefreshCell(GetEditControlCoords(), false); - return true; + GetSheetRefData()->m_cellEditor.Show(false, GetAttr(GetEditControlCoords())); + m_gridWin->SetFocus(); + RefreshCell(GetEditControlCoords(), false); + return true; } void wxSheet::SaveEditControlValue() { - wxCHECK_RET(IsCellEditControlCreated(), wxT("Edit control not shown in wxSheet::HideCellEditControl")); + wxCHECK_RET(IsCellEditControlCreated(), + wxT("Edit control not shown in wxSheet::HideCellEditControl")); - wxString oldval = GetCellValue(GetEditControlCoords()); + wxString oldval = GetCellValue(GetEditControlCoords()); - if (GetSheetRefData()->m_cellEditor.EndEdit(GetEditControlCoords(), this)) - { - // Event has been vetoed, set the data back. - if ( SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGED, GetEditControlCoords()) == EVT_VETOED ) - SetCellValue(GetEditControlCoords(), oldval); + if (GetSheetRefData()->m_cellEditor.EndEdit(GetEditControlCoords(), this)) { + // Event has been vetoed, set the data back. + if (SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGED, GetEditControlCoords()) == EVT_VETOED) { + SetCellValue(GetEditControlCoords(), oldval); } + } } // ---------------------------------------------------------------------------- @@ -3085,596 +3169,572 @@ void wxSheet::SaveEditControlValue() void wxSheet::EndBatch(bool refresh) { - if ( m_batchCount > 0 ) - { - m_batchCount--; - if ( !m_batchCount && refresh ) - { - m_batchCount++; // temp block refresh for window sizing - AdjustScrollbars(); - m_batchCount--; - Refresh(true); - } + if (m_batchCount > 0) { + m_batchCount--; + if (!m_batchCount && refresh) { + m_batchCount++; // temp block refresh for window sizing + AdjustScrollbars(); + m_batchCount--; + Refresh(true); } + } } -void wxSheet::Refresh(bool eraseb, const wxRect* rect_) +void wxSheet::Refresh(bool eraseb, const wxRect *rect_) { - // Don't do anything if between Begin/EndBatch... - // EndBatch() will do all this on the last nested one anyway. - if (GetBatchCount()) - return; + // Don't do anything if between Begin/EndBatch... + // EndBatch() will do all this on the last nested one anyway. + if (GetBatchCount()) { + return; + } - if (rect_) - { - const wxRect rect(*rect_); - const int rowLabelWidth = GetRowLabelWidth(); - const int colLabelHeight = GetColLabelHeight(); - const wxSize extentSize(GetGridExtent()); - - wxRect cornerRect(0, 0, rowLabelWidth, colLabelHeight); - cornerRect.Intersect(rect); - - wxRect rowLabelRect(0, colLabelHeight, rowLabelWidth, extentSize.y); - rowLabelRect.Intersect(rect); - rowLabelRect.y -= colLabelHeight; - - wxRect colLabelRect(rowLabelWidth, 0, extentSize.x, colLabelHeight); - colLabelRect.Intersect(rect); - colLabelRect.x -= rowLabelWidth; - - wxRect gridRect(rowLabelWidth, colLabelHeight, extentSize.x, extentSize.y); - gridRect.Intersect(rect); - gridRect.x -= rowLabelWidth; - gridRect.y -= colLabelHeight; - - if ( !wxRectIsEmpty(cornerRect) ) - RefreshCornerLabelWindow(eraseb, &cornerRect); - if ( !wxRectIsEmpty(rowLabelRect) ) - RefreshRowLabelWindow(eraseb, &rowLabelRect); - if ( !wxRectIsEmpty(colLabelRect) ) - RefreshColLabelWindow(eraseb, &colLabelRect); - if ( !wxRectIsEmpty(gridRect) ) - RefreshGridWindow(eraseb, &gridRect); - } - else - { - RefreshCornerLabelWindow(eraseb, NULL); - RefreshRowLabelWindow(eraseb, NULL); - RefreshColLabelWindow(eraseb, NULL); - RefreshGridWindow(eraseb, NULL); - } -} -void wxSheet::RefreshGridWindow(bool eraseb, const wxRect* rect) -{ - if (GetBatchCount()) - return; + if (rect_) { + const wxRect rect(*rect_); + const int rowLabelWidth = GetRowLabelWidth(); + const int colLabelHeight = GetColLabelHeight(); + const wxSize extentSize(GetGridExtent()); - size_t n, count = GetSheetRefData()->GetSheetCount(); - for (n=0; nGetSheet(n); - wxWindow *win = (wxWindow*)s->GetGridWindow(); - if (win && win->IsShown()) - { - if (rect) - { - wxRect scrolledRect(s->CalcScrolledRect(*rect)); - const wxRect refedRect(wxPoint(0,0), win->GetSize()); - scrolledRect.Intersect(refedRect); - if (!wxRectIsEmpty(scrolledRect)) - win->Refresh(eraseb, &scrolledRect); - } - else - win->Refresh(eraseb, NULL); - } - } -} -void wxSheet::RefreshRowLabelWindow(bool eraseb, const wxRect* rect) -{ - if (GetBatchCount()) - return; + wxRect cornerRect(0, 0, rowLabelWidth, colLabelHeight); + cornerRect.Intersect(rect); - size_t n, count = GetSheetRefData()->GetSheetCount(); - for (n=0; nGetSheet(n); - wxWindow *win = (wxWindow*)s->GetRowLabelWindow(); - if (win && win->IsShown()) - { - if (rect) - { - wxRect scrolledRect(*rect); - s->CalcScrolledPosition(0, scrolledRect.y, NULL, &scrolledRect.y); - const wxRect refedRect(wxPoint(0,0), win->GetSize()); - scrolledRect.Intersect(refedRect); - if (!wxRectIsEmpty(scrolledRect)) - win->Refresh(eraseb, &scrolledRect); - } - else - win->Refresh(eraseb, NULL); - } - } -} -void wxSheet::RefreshColLabelWindow(bool eraseb, const wxRect* rect) -{ - if (GetBatchCount()) - return; + wxRect rowLabelRect(0, colLabelHeight, rowLabelWidth, extentSize.y); + rowLabelRect.Intersect(rect); + rowLabelRect.y -= colLabelHeight; - size_t n, count = GetSheetRefData()->GetSheetCount(); - for (n=0; nGetSheet(n); - wxWindow *win = (wxWindow*)s->GetColLabelWindow(); - if (win && win->IsShown()) - { - if (rect) - { - wxRect scrolledRect(*rect); - s->CalcScrolledPosition(scrolledRect.x, 0, &scrolledRect.x, NULL); - const wxRect refedRect(wxPoint(0,0), win->GetSize()); - scrolledRect.Intersect(refedRect); - if (!wxRectIsEmpty(scrolledRect)) - win->Refresh(eraseb, &scrolledRect); - } - else - win->Refresh(eraseb, NULL); - } + wxRect colLabelRect(rowLabelWidth, 0, extentSize.x, colLabelHeight); + colLabelRect.Intersect(rect); + colLabelRect.x -= rowLabelWidth; + + wxRect gridRect(rowLabelWidth, colLabelHeight, extentSize.x, extentSize.y); + gridRect.Intersect(rect); + gridRect.x -= rowLabelWidth; + gridRect.y -= colLabelHeight; + + if (!wxRectIsEmpty(cornerRect)) { + RefreshCornerLabelWindow(eraseb, &cornerRect); + } + if (!wxRectIsEmpty(rowLabelRect)) { + RefreshRowLabelWindow(eraseb, &rowLabelRect); + } + if (!wxRectIsEmpty(colLabelRect)) { + RefreshColLabelWindow(eraseb, &colLabelRect); + } + if (!wxRectIsEmpty(gridRect)) { + RefreshGridWindow(eraseb, &gridRect); } + } + else { + RefreshCornerLabelWindow(eraseb, NULL); + RefreshRowLabelWindow(eraseb, NULL); + RefreshColLabelWindow(eraseb, NULL); + RefreshGridWindow(eraseb, NULL); + } } -void wxSheet::RefreshCornerLabelWindow(bool eraseb, const wxRect* rect) +void wxSheet::RefreshGridWindow(bool eraseb, const wxRect *rect) { - if (GetBatchCount()) - return; + if (GetBatchCount()) { + return; + } + + size_t n, count = GetSheetRefData()->GetSheetCount(); + for (n = 0; n < count; n++) { + wxSheet *s = GetSheetRefData()->GetSheet(n); + wxWindow *win = (wxWindow *)s->GetGridWindow(); + if (win && win->IsShown()) { + if (rect) { + wxRect scrolledRect(s->CalcScrolledRect(*rect)); + const wxRect refedRect(wxPoint(0, 0), win->GetSize()); + scrolledRect.Intersect(refedRect); + if (!wxRectIsEmpty(scrolledRect)) { + win->Refresh(eraseb, &scrolledRect); + } + } + else { + win->Refresh(eraseb, NULL); + } + } + } +} +void wxSheet::RefreshRowLabelWindow(bool eraseb, const wxRect *rect) +{ + if (GetBatchCount()) { + return; + } + + size_t n, count = GetSheetRefData()->GetSheetCount(); + for (n = 0; n < count; n++) { + wxSheet *s = GetSheetRefData()->GetSheet(n); + wxWindow *win = (wxWindow *)s->GetRowLabelWindow(); + if (win && win->IsShown()) { + if (rect) { + wxRect scrolledRect(*rect); + s->CalcScrolledPosition(0, scrolledRect.y, NULL, &scrolledRect.y); + const wxRect refedRect(wxPoint(0, 0), win->GetSize()); + scrolledRect.Intersect(refedRect); + if (!wxRectIsEmpty(scrolledRect)) { + win->Refresh(eraseb, &scrolledRect); + } + } + else { + win->Refresh(eraseb, NULL); + } + } + } +} +void wxSheet::RefreshColLabelWindow(bool eraseb, const wxRect *rect) +{ + if (GetBatchCount()) { + return; + } + + size_t n, count = GetSheetRefData()->GetSheetCount(); + for (n = 0; n < count; n++) { + wxSheet *s = GetSheetRefData()->GetSheet(n); + wxWindow *win = (wxWindow *)s->GetColLabelWindow(); + if (win && win->IsShown()) { + if (rect) { + wxRect scrolledRect(*rect); + s->CalcScrolledPosition(scrolledRect.x, 0, &scrolledRect.x, NULL); + const wxRect refedRect(wxPoint(0, 0), win->GetSize()); + scrolledRect.Intersect(refedRect); + if (!wxRectIsEmpty(scrolledRect)) { + win->Refresh(eraseb, &scrolledRect); + } + } + else { + win->Refresh(eraseb, NULL); + } + } + } +} +void wxSheet::RefreshCornerLabelWindow(bool eraseb, const wxRect *rect) +{ + if (GetBatchCount()) { + return; + } - size_t n, count = GetSheetRefData()->GetSheetCount(); - for (n=0; nGetSheet(n); - wxWindow *win = (wxWindow*)s->GetCornerLabelWindow(); - if (win && win->IsShown()) - win->Refresh(eraseb, rect); + size_t n, count = GetSheetRefData()->GetSheetCount(); + for (n = 0; n < count; n++) { + wxSheet *s = GetSheetRefData()->GetSheet(n); + wxWindow *win = (wxWindow *)s->GetCornerLabelWindow(); + if (win && win->IsShown()) { + win->Refresh(eraseb, rect); } + } } -void wxSheet::RefreshCell(const wxSheetCoords& coords, bool single_cell) +void wxSheet::RefreshCell(const wxSheetCoords &coords, bool single_cell) { - if ( GetBatchCount() ) - return; - - //wxPrintf(wxT("RefreshCell %d %d\n"), coords.m_row, coords.m_col); + if (GetBatchCount()) { + return; + } - if (IsCornerLabelCell(coords)) - { - RefreshCornerLabelWindow(true); - return; - } + // wxPrintf(wxT("RefreshCell %d %d\n"), coords.m_row, coords.m_col); - wxRect rect(CellToRect(coords, false)); + if (IsCornerLabelCell(coords)) { + RefreshCornerLabelWindow(true); + return; + } - if (ContainsRowLabelCell(coords)) - { - RefreshRowLabelWindow( true, &rect ); - return; - } - else if (ContainsColLabelCell(coords)) - { - RefreshColLabelWindow( true, &rect ); - return; - } - else if (ContainsGridCell(coords)) - { - if (!single_cell) - { - // hack to draw previous cell, if this cell turns empty and can be - // overflowed into we need to erase the previous cell's |> cutoff marker - if (coords.m_col > 0) - rect.x = GetColLeft(coords.m_col-1); - // we do have to draw the whole row right though - rect.width = GetVirtualSize().x - rect.x; - } + wxRect rect(CellToRect(coords, false)); - RefreshGridWindow( false, &rect ); - } - else - wxFAIL_MSG(wxT("Invalid coords in wxSheet::RefreshCell")); -} -void wxSheet::RefreshBlock(const wxSheetBlock& block) -{ - if ( GetBatchCount() || block.IsEmpty() ) - return; + if (ContainsRowLabelCell(coords)) { + RefreshRowLabelWindow(true, &rect); + return; + } + else if (ContainsColLabelCell(coords)) { + RefreshColLabelWindow(true, &rect); + return; + } + else if (ContainsGridCell(coords)) { + if (!single_cell) { + // hack to draw previous cell, if this cell turns empty and can be + // overflowed into we need to erase the previous cell's |> cutoff marker + if (coords.m_col > 0) { + rect.x = GetColLeft(coords.m_col - 1); + } + // we do have to draw the whole row right though + rect.width = GetVirtualSize().x - rect.x; + } + + RefreshGridWindow(false, &rect); + } + else { + wxFAIL_MSG(wxT("Invalid coords in wxSheet::RefreshCell")); + } +} +void wxSheet::RefreshBlock(const wxSheetBlock &block) +{ + if (GetBatchCount() || block.IsEmpty()) { + return; + } - //PRINT_BLOCK(wxT("RefreshBlock "), block) + // PRINT_BLOCK(wxT("RefreshBlock "), block) - // This function also refreshes beyond the labels and grid since if a - // cell is resized smaller that may have to be repainted + // This function also refreshes beyond the labels and grid since if a + // cell is resized smaller that may have to be repainted - wxSheetBlock b; - const wxSheetCoords coords(block.GetLeftTop()); - const wxSize winSize(GetGridExtent()); - const int numRows = GetNumberRows(); - const int numCols = GetNumberCols(); + wxSheetBlock b; + const wxSheetCoords coords(block.GetLeftTop()); + const wxSize winSize(GetGridExtent()); + const int numRows = GetNumberRows(); + const int numCols = GetNumberCols(); - // Corner Labels - if (IsCornerLabelCell(coords)) - { - RefreshCornerLabelWindow(true); - } - // Row Labels - b = block.Intersect(wxSheetBlock(0, -1, numRows, 1)); - if (!b.IsEmpty()) - { - wxRect rect(BlockToLogicalRect(b)); - if (b.GetBottom() == numRows - 1) - rect.height = winSize.y - rect.y; - RefreshRowLabelWindow( true, &rect ); - } - // Col Labels - b = block.Intersect(wxSheetBlock(-1, 0, 1, numCols)); - if (!b.IsEmpty()) - { - wxRect rect(BlockToLogicalRect(b)); - if (b.GetRight() == numCols - 1) - rect.width = winSize.x - rect.x; - RefreshColLabelWindow( true, &rect ); - } - // Grid cells - b = block.Intersect(wxSheetBlock(0, 0, numRows, numCols)); - if (!b.IsEmpty()) - { - wxRect rect(BlockToLogicalRect(b)); - if (b.GetBottom() == numRows - 1) - rect.height = winSize.y - rect.y; - if (b.GetRight() == numCols - 1) - rect.width = winSize.x - rect.x; - RefreshGridWindow( false, &rect ); + // Corner Labels + if (IsCornerLabelCell(coords)) { + RefreshCornerLabelWindow(true); + } + // Row Labels + b = block.Intersect(wxSheetBlock(0, -1, numRows, 1)); + if (!b.IsEmpty()) { + wxRect rect(BlockToLogicalRect(b)); + if (b.GetBottom() == numRows - 1) { + rect.height = winSize.y - rect.y; + } + RefreshRowLabelWindow(true, &rect); + } + // Col Labels + b = block.Intersect(wxSheetBlock(-1, 0, 1, numCols)); + if (!b.IsEmpty()) { + wxRect rect(BlockToLogicalRect(b)); + if (b.GetRight() == numCols - 1) { + rect.width = winSize.x - rect.x; + } + RefreshColLabelWindow(true, &rect); + } + // Grid cells + b = block.Intersect(wxSheetBlock(0, 0, numRows, numCols)); + if (!b.IsEmpty()) { + wxRect rect(BlockToLogicalRect(b)); + if (b.GetBottom() == numRows - 1) { + rect.height = winSize.y - rect.y; + } + if (b.GetRight() == numCols - 1) { + rect.width = winSize.x - rect.x; + } + RefreshGridWindow(false, &rect); + } +} +void wxSheet::RefreshRow(int row) { RefreshBlock(wxSheetBlock(row, 0, 1, GetNumberCols())); } +void wxSheet::RefreshCol(int col) { RefreshBlock(wxSheetBlock(0, col, GetNumberRows(), 1)); } +void wxSheet::RefreshGridCellBlock(const wxSheetBlock &block) { RefreshBlock(block); } + +void wxSheet::RefreshAttrChange(const wxSheetCoords &coords, wxSheetAttr_Type type) +{ + switch (GetCellCoordsType(coords)) { + case wxSHEET_CELL_GRID: { + switch (type) { + case wxSHEET_AttrDefault: { + m_gridWin->SetBackgroundColour(DoGetDefaultGridAttr().GetBackgroundColour()); + RefreshGridWindow(false); + break; + } + case wxSHEET_AttrCol: { + if (ContainsGridCol(coords.m_col)) { + RefreshCol(coords.m_col); + } + break; + } + case wxSHEET_AttrRow: { + if (ContainsGridRow(coords.m_row)) { + RefreshRow(coords.m_row); + } + break; + } + case wxSHEET_AttrCell: + default: { + if (ContainsGridCell(coords)) { + RefreshCell(coords, false); + } + break; } -} -void wxSheet::RefreshRow( int row ) -{ - RefreshBlock(wxSheetBlock(row, 0, 1, GetNumberCols())); -} -void wxSheet::RefreshCol( int col ) -{ - RefreshBlock(wxSheetBlock(0, col, GetNumberRows(), 1)); -} -void wxSheet::RefreshGridCellBlock( const wxSheetBlock& block ) -{ - RefreshBlock(block); -} - -void wxSheet::RefreshAttrChange(const wxSheetCoords& coords, wxSheetAttr_Type type) -{ - switch (GetCellCoordsType(coords)) - { - case wxSHEET_CELL_GRID : - { - switch (type) - { - case wxSHEET_AttrDefault : - { - m_gridWin->SetBackgroundColour(DoGetDefaultGridAttr().GetBackgroundColour()); - RefreshGridWindow(false); - break; - } - case wxSHEET_AttrCol : - { - if (ContainsGridCol(coords.m_col)) RefreshCol(coords.m_col); - break; - } - case wxSHEET_AttrRow : - { - if (ContainsGridRow(coords.m_row)) RefreshRow(coords.m_row); - break; - } - case wxSHEET_AttrCell : - default : - { - if (ContainsGridCell(coords)) RefreshCell(coords, false); - break; - } - } - break; - } - case wxSHEET_CELL_CORNERLABEL : - { - m_cornerLabelWin->SetBackgroundColour(DoGetDefaultCornerLabelAttr().GetBackgroundColour()); - RefreshCornerLabelWindow(true); - break; - } - case wxSHEET_CELL_ROWLABEL : - { - switch (type) - { - case wxSHEET_AttrDefault : - { - m_rowLabelWin->SetBackgroundColour(DoGetDefaultRowLabelAttr().GetBackgroundColour()); - RefreshRowLabelWindow(true); - break; - } - case wxSHEET_AttrCell : - default : - { - if (ContainsRowLabelCell(coords)) - RefreshCell(coords); - break; - } - } - break; - } - case wxSHEET_CELL_COLLABEL : - { - switch (type) - { - case wxSHEET_AttrDefault : - { - m_colLabelWin->SetBackgroundColour(DoGetDefaultColLabelAttr().GetBackgroundColour()); - RefreshColLabelWindow(true); - break; - } - case wxSHEET_AttrCell : - default : - { - if (ContainsColLabelCell(coords)) - RefreshCell(coords); - break; - } - } - break; - } - default : break; } -} - -void wxSheet::OnPaint( wxPaintEvent& event ) -{ - wxWindow *win = (wxWindow*)event.GetEventObject(); - wxPaintDC dc(win); - wxRegion reg(win->GetUpdateRegion()); - - if (!IsShown()) return; + break; + } + case wxSHEET_CELL_CORNERLABEL: { + m_cornerLabelWin->SetBackgroundColour(DoGetDefaultCornerLabelAttr().GetBackgroundColour()); + RefreshCornerLabelWindow(true); + break; + } + case wxSHEET_CELL_ROWLABEL: { + switch (type) { + case wxSHEET_AttrDefault: { + m_rowLabelWin->SetBackgroundColour(DoGetDefaultRowLabelAttr().GetBackgroundColour()); + RefreshRowLabelWindow(true); + break; + } + case wxSHEET_AttrCell: + default: { + if (ContainsRowLabelCell(coords)) { + RefreshCell(coords); + } + break; + } + } + break; + } + case wxSHEET_CELL_COLLABEL: { + switch (type) { + case wxSHEET_AttrDefault: { + m_colLabelWin->SetBackgroundColour(DoGetDefaultColLabelAttr().GetBackgroundColour()); + RefreshColLabelWindow(true); + break; + } + case wxSHEET_AttrCell: + default: { + if (ContainsColLabelCell(coords)) { + RefreshCell(coords); + } + break; + } + } + break; + } + default: + break; + } +} + +void wxSheet::OnPaint(wxPaintEvent &event) +{ + wxWindow *win = (wxWindow *)event.GetEventObject(); + wxPaintDC dc(win); + wxRegion reg(win->GetUpdateRegion()); + + if (!IsShown()) { + return; + } - if (win == this) - { - PaintSheetWindow( dc, reg ); - } - else if (win == m_cornerLabelWin) - { - if (m_cornerLabelWin->IsShown()) - { - PaintCornerLabelWindow( dc, reg ); - } + if (win == this) { + PaintSheetWindow(dc, reg); + } + else if (win == m_cornerLabelWin) { + if (m_cornerLabelWin->IsShown()) { + PaintCornerLabelWindow(dc, reg); } - else if (win == m_rowLabelWin) - { - if (m_rowLabelWin->IsShown()) - { - PrepareRowLabelDC( dc ); - PaintRowLabelWindow( dc, reg ); - } + } + else if (win == m_rowLabelWin) { + if (m_rowLabelWin->IsShown()) { + PrepareRowLabelDC(dc); + PaintRowLabelWindow(dc, reg); } - else if (win == m_colLabelWin) - { - if (m_colLabelWin->IsShown()) - { - PrepareColLabelDC( dc ); - PaintColLabelWindow( dc, reg ); - } + } + else if (win == m_colLabelWin) { + if (m_colLabelWin->IsShown()) { + PrepareColLabelDC(dc); + PaintColLabelWindow(dc, reg); } - else if (win == m_gridWin) - { - if (m_gridWin->IsShown()) - { - PrepareGridDC( dc ); - PaintGridWindow( dc, reg ); - } + } + else if (win == m_gridWin) { + if (m_gridWin->IsShown()) { + PrepareGridDC(dc); + PaintGridWindow(dc, reg); } + } } -void wxSheet::OnEraseBackground( wxEraseEvent& event ) +void wxSheet::OnEraseBackground(wxEraseEvent &event) { - wxWindow *win = (wxWindow*)event.GetEventObject(); + wxWindow *win = (wxWindow *)event.GetEventObject(); - if (win == this) - event.Skip(false); - else if ((win == m_cornerLabelWin) || (win == m_rowLabelWin) || (win == m_colLabelWin)) - event.Skip(false); - else if (win == m_gridWin) - event.Skip(false); + if (win == this) { + event.Skip(false); + } + else if ((win == m_cornerLabelWin) || (win == m_rowLabelWin) || (win == m_colLabelWin)) { + event.Skip(false); + } + else if (win == m_gridWin) { + event.Skip(false); + } } -void wxSheet::DrawSplitterButton(wxDC &dc, const wxRect& rect) +void wxSheet::DrawSplitterButton(wxDC &dc, const wxRect &rect) { - //dc.SetPen(*wxBLACK_PEN); - //dc.SetBrush(*wxBLACK_BRUSH); - //dc.DrawRectangle(rect); + // dc.SetPen(*wxBLACK_PEN); + // dc.SetBrush(*wxBLACK_BRUSH); + // dc.DrawRectangle(rect); - wxPen highlight(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT), - 1, wxPENSTYLE_SOLID); - wxPen shadow(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW), - 1, wxPENSTYLE_SOLID); - wxPen darkShadow(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW), - 1, wxPENSTYLE_SOLID); + wxPen highlight(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT), 1, wxPENSTYLE_SOLID); + wxPen shadow(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW), 1, wxPENSTYLE_SOLID); + wxPen darkShadow(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW), 1, wxPENSTYLE_SOLID); - dc.SetPen(shadow); - dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); - dc.DrawRectangle(rect); - dc.DrawLine(rect.GetRight()-1, rect.y+2, rect.GetRight()-1, rect.GetBottom()-1); - dc.DrawLine(rect.x+2, rect.GetBottom()-1, rect.GetRight(), rect.GetBottom()-1); + dc.SetPen(shadow); + dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); + dc.DrawRectangle(rect); + dc.DrawLine(rect.GetRight() - 1, rect.y + 2, rect.GetRight() - 1, rect.GetBottom() - 1); + dc.DrawLine(rect.x + 2, rect.GetBottom() - 1, rect.GetRight(), rect.GetBottom() - 1); - dc.SetPen(darkShadow); - dc.DrawLine(rect.GetRight(), rect.y+1, rect.GetRight(), rect.GetBottom()); - dc.DrawLine(rect.x+1, rect.GetBottom(), rect.GetRight(), rect.GetBottom()); + dc.SetPen(darkShadow); + dc.DrawLine(rect.GetRight(), rect.y + 1, rect.GetRight(), rect.GetBottom()); + dc.DrawLine(rect.x + 1, rect.GetBottom(), rect.GetRight(), rect.GetBottom()); - dc.SetPen(highlight); - dc.DrawLine(rect.x+1, rect.y+1, rect.GetRight()-1, rect.y+1); - dc.DrawLine(rect.x+1, rect.y+1, rect.x+1, rect.GetBottom()-1); + dc.SetPen(highlight); + dc.DrawLine(rect.x + 1, rect.y + 1, rect.GetRight() - 1, rect.y + 1); + dc.DrawLine(rect.x + 1, rect.y + 1, rect.x + 1, rect.GetBottom() - 1); } -void wxSheet::PaintSheetWindow( wxDC& dc, const wxRegion& WXUNUSED(reg) ) +void wxSheet::PaintSheetWindow(wxDC &dc, const wxRegion &WXUNUSED(reg)) { - // draw the bottom right square area between the scrollbars - // since we trap EVT_ERASE_BACKGROUND - if (m_vertScrollBar->IsShown() && m_horizScrollBar->IsShown()) - { - dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); - dc.SetPen(*wxTRANSPARENT_PEN); - wxSize clientSize = GetClientSize(); - int top = m_vertScrollBar->GetRect().GetBottom(); - int left = m_horizScrollBar->GetRect().GetRight() + m_horizSplitRect.GetWidth(); - dc.DrawRectangle(left, top, clientSize.x-left, clientSize.y-top); - } + // draw the bottom right square area between the scrollbars + // since we trap EVT_ERASE_BACKGROUND + if (m_vertScrollBar->IsShown() && m_horizScrollBar->IsShown()) { + dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); + dc.SetPen(*wxTRANSPARENT_PEN); + wxSize clientSize = GetClientSize(); + int top = m_vertScrollBar->GetRect().GetBottom(); + int left = m_horizScrollBar->GetRect().GetRight() + m_horizSplitRect.GetWidth(); + dc.DrawRectangle(left, top, clientSize.x - left, clientSize.y - top); + } - if (!wxRectIsEmpty(m_vertSplitRect)) - DrawSplitterButton(dc, m_vertSplitRect); - if (!wxRectIsEmpty(m_horizSplitRect)) - DrawSplitterButton(dc, m_horizSplitRect); + if (!wxRectIsEmpty(m_vertSplitRect)) { + DrawSplitterButton(dc, m_vertSplitRect); + } + if (!wxRectIsEmpty(m_horizSplitRect)) { + DrawSplitterButton(dc, m_horizSplitRect); + } } -void wxSheet::PaintGridWindow( wxDC& dc, const wxRegion& reg ) +void wxSheet::PaintGridWindow(wxDC &dc, const wxRegion ®) { - wxSheetSelection dirtyBlocks; - CalcCellsExposed( reg, dirtyBlocks ); + wxSheetSelection dirtyBlocks; + CalcCellsExposed(reg, dirtyBlocks); - DrawGridCells( dc, dirtyBlocks ); + DrawGridCells(dc, dirtyBlocks); #if WXSHEET_DRAW_LINES - DrawAllGridLines( dc, reg ); + DrawAllGridLines(dc, reg); #endif - DrawGridSpace( dc ); - DrawCursorHighlight( dc, dirtyBlocks ); + DrawGridSpace(dc); + DrawCursorHighlight(dc, dirtyBlocks); } -void wxSheet::PaintRowLabelWindow( wxDC& dc, const wxRegion& reg ) +void wxSheet::PaintRowLabelWindow(wxDC &dc, const wxRegion ®) { - const int numRows = GetNumberRows(); - if (0 && numRows) - { + const int numRows = GetNumberRows(); + if (0 && numRows) { - wxRect r(0, GetRowBottom(numRows-1), GetRowLabelWidth(), GetGridVirtualSize(true).y); - r = CalcScrolledRect(r); - r.Intersect(reg.GetBox()); - dc.DrawRectangle(r); - } - - wxArrayInt rows; - if (CalcRowLabelsExposed(reg, rows)) - DrawRowLabels( dc, rows ); + wxRect r(0, GetRowBottom(numRows - 1), GetRowLabelWidth(), GetGridVirtualSize(true).y); + r = CalcScrolledRect(r); + r.Intersect(reg.GetBox()); + dc.DrawRectangle(r); + } + wxArrayInt rows; + if (CalcRowLabelsExposed(reg, rows)) { + DrawRowLabels(dc, rows); + } } -void wxSheet::PaintColLabelWindow( wxDC& dc, const wxRegion& reg ) +void wxSheet::PaintColLabelWindow(wxDC &dc, const wxRegion ®) { - const int numCols = GetNumberCols(); - if (0 && numCols) - { - wxRect r(GetColRight(numCols-1), 0, GetGridVirtualSize(true).x, GetColLabelHeight()); - r = CalcScrolledRect(r); - r.Intersect(reg.GetBox()); - dc.DrawRectangle(r); - } + const int numCols = GetNumberCols(); + if (0 && numCols) { + wxRect r(GetColRight(numCols - 1), 0, GetGridVirtualSize(true).x, GetColLabelHeight()); + r = CalcScrolledRect(r); + r.Intersect(reg.GetBox()); + dc.DrawRectangle(r); + } - wxArrayInt cols; - if (CalcColLabelsExposed(reg, cols)) - DrawColLabels( dc, cols ); + wxArrayInt cols; + if (CalcColLabelsExposed(reg, cols)) { + DrawColLabels(dc, cols); + } } -void wxSheet::PaintCornerLabelWindow( wxDC& dc, const wxRegion& WXUNUSED(reg) ) +void wxSheet::PaintCornerLabelWindow(wxDC &dc, const wxRegion &WXUNUSED(reg)) { - DrawCornerLabel( dc ); + DrawCornerLabel(dc); } -int wxSheet::FindOverflowCell( const wxSheetCoords& coords, wxDC& dc ) +int wxSheet::FindOverflowCell(const wxSheetCoords &coords, wxDC &dc) { - wxSheetCoords c(coords); - while (c.m_col > 0) - { - c.m_col = GetTable()->GetFirstNonEmptyColToLeft(c); - if (c.m_col < 0) - return -1; - - // if !empty, stop, this is the only cell that could overflow - // Must check since default implementation of - // GetFirstNonEmptyColToLeft just returns the previous col - if (HasCellValue(c)) - { - wxSheetCellAttr attr(GetAttr(c)); - if (attr.GetOverflow()) - { - // check if this cell actually does overflow into coords - int width = attr.GetRenderer(this, c).GetBestSize(*this, attr, dc, c).GetWidth(); - if (GetColLeft(c.m_col)+width > GetColLeft(coords.m_col)) - return c.m_col; - } - break; + wxSheetCoords c(coords); + while (c.m_col > 0) { + c.m_col = GetTable()->GetFirstNonEmptyColToLeft(c); + if (c.m_col < 0) { + return -1; + } + + // if !empty, stop, this is the only cell that could overflow + // Must check since default implementation of + // GetFirstNonEmptyColToLeft just returns the previous col + if (HasCellValue(c)) { + wxSheetCellAttr attr(GetAttr(c)); + if (attr.GetOverflow()) { + // check if this cell actually does overflow into coords + int width = attr.GetRenderer(this, c).GetBestSize(*this, attr, dc, c).GetWidth(); + if (GetColLeft(c.m_col) + width > GetColLeft(coords.m_col)) { + return c.m_col; } + } + break; } - return -1; + } + return -1; } // Note - this function only draws cells that are in the list of // exposed cells (usually set from the update region by CalcExposedCells) -void wxSheet::DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel ) +void wxSheet::DrawGridCells(wxDC &dc, const wxSheetSelection &blockSel) { - if ( !GetNumberRows() || !GetNumberCols() || GetBatchCount() ) - return; - - //static long counter = 0; ++counter; // for testing only - - wxSheetSelection removedSel; // removed spanned - wxSheetCoords coords; - wxSheetCoords lastCoords(-1,-1); - wxSheetBlock cellBlock; - wxPairArrayIntInt leftCols; - - // paint cells in reverse order bottom to top, right to left for overflow - wxSheetSelectionIterator revIter(blockSel, wxSSI_REVERSE); - while (revIter.GetNext(coords) != wxSHEET_SELECTIONITER_GET_END) - { - // already painted this cell - if (removedSel.Contains(coords)) - { - lastCoords = coords; - continue; - } - - // trim out cells part of spanned cells, leaving only the owner cell - cellBlock = GetCellBlock(coords); - if (!cellBlock.IsOneCell()) - { - // forget part of spanned cell, we only care about owner cell - coords = cellBlock.GetLeftTop(); - // don't bother checking whole block again - removedSel.SelectBlock(cellBlock, false); - } - - // if empty find cell to left that might overflow into this one - // only need to check left side of each block, when row increments - if ((lastCoords.m_row > coords.m_row) && !HasCellValue(lastCoords)) - { - int overflow_col = FindOverflowCell(lastCoords, dc); - if ((overflow_col >= 0) && !blockSel.Contains(lastCoords.m_row, overflow_col)) - leftCols.SetValue(lastCoords.m_row, overflow_col); - } - - //wxPrintf(wxT("%ld Drawing Cell %d %d - has %d %d\n"), counter, coords.m_row, coords.m_col, HasCellValue(coords), HasCellValue(lastCoords)); fflush(stdout); - DrawCell( dc, coords ); - lastCoords = coords; - } - - // check the top left cell of the last block too - if (ContainsGridCell(lastCoords) && !HasCellValue(lastCoords)) - { - int overflow_col = FindOverflowCell(lastCoords, dc); - if ((overflow_col >= 0) && !blockSel.Contains(lastCoords.m_row, overflow_col)) - leftCols.SetValue(lastCoords.m_row, overflow_col); - } - - // now redraw the cells that could have overflowed into these - int n, count = leftCols.GetCount(); - for (n = 0; n < count; n++) - { - coords.Set(leftCols.GetItemKey(n), leftCols.GetItemValue(n)); - DrawCell( dc, coords ); - //wxPrintf(wxT("%ld Overflow Drawing Cell %d %d\n"), counter, coords.m_row, coords.m_col); fflush(stdout); - } + if (!GetNumberRows() || !GetNumberCols() || GetBatchCount()) { + return; + } + + // static long counter = 0; ++counter; // for testing only + + wxSheetSelection removedSel; // removed spanned + wxSheetCoords coords; + wxSheetCoords lastCoords(-1, -1); + wxSheetBlock cellBlock; + wxPairArrayIntInt leftCols; + + // paint cells in reverse order bottom to top, right to left for overflow + wxSheetSelectionIterator revIter(blockSel, wxSSI_REVERSE); + while (revIter.GetNext(coords) != wxSHEET_SELECTIONITER_GET_END) { + // already painted this cell + if (removedSel.Contains(coords)) { + lastCoords = coords; + continue; + } + + // trim out cells part of spanned cells, leaving only the owner cell + cellBlock = GetCellBlock(coords); + if (!cellBlock.IsOneCell()) { + // forget part of spanned cell, we only care about owner cell + coords = cellBlock.GetLeftTop(); + // don't bother checking whole block again + removedSel.SelectBlock(cellBlock, false); + } + + // if empty find cell to left that might overflow into this one + // only need to check left side of each block, when row increments + if ((lastCoords.m_row > coords.m_row) && !HasCellValue(lastCoords)) { + int overflow_col = FindOverflowCell(lastCoords, dc); + if ((overflow_col >= 0) && !blockSel.Contains(lastCoords.m_row, overflow_col)) { + leftCols.SetValue(lastCoords.m_row, overflow_col); + } + } + + // wxPrintf(wxT("%ld Drawing Cell %d %d - has %d %d\n"), counter, coords.m_row, coords.m_col, + // HasCellValue(coords), HasCellValue(lastCoords)); fflush(stdout); + DrawCell(dc, coords); + lastCoords = coords; + } + + // check the top left cell of the last block too + if (ContainsGridCell(lastCoords) && !HasCellValue(lastCoords)) { + int overflow_col = FindOverflowCell(lastCoords, dc); + if ((overflow_col >= 0) && !blockSel.Contains(lastCoords.m_row, overflow_col)) { + leftCols.SetValue(lastCoords.m_row, overflow_col); + } + } + + // now redraw the cells that could have overflowed into these + int n, count = leftCols.GetCount(); + for (n = 0; n < count; n++) { + coords.Set(leftCols.GetItemKey(n), leftCols.GetItemValue(n)); + DrawCell(dc, coords); + // wxPrintf(wxT("%ld Overflow Drawing Cell %d %d\n"), counter, coords.m_row, coords.m_col); + // fflush(stdout); + } } /* @@ -3716,7 +3776,8 @@ void wxSheet::DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel_ ) // if empty find cell to left that might overflow into this one // only need to check left side of each block, hence check_overflow_row - if ((bottom > check_overflow_row) && !HasValue()) //GetTable() && !GetTable()->HasValue(coords)) + if ((bottom > check_overflow_row) && !HasValue()) //GetTable() && +!GetTable()->HasValue(coords)) { check_overflow_row = bottom; @@ -3739,7 +3800,8 @@ void wxSheet::DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel_ ) if (attr.GetOverflow()) { // check if this cell actually does overflow into coords - int width = attr.GetRenderer(this, c).GetBestSize(*this, attr, dc, c).GetWidth(); + int width = attr.GetRenderer(this, c).GetBestSize(*this, attr, dc, +c).GetWidth(); if (GetColLeft(c.m_col)+width > GetColLeft(coords.m_col)) blockSel.SelectBlock(wxSheetBlock(c, 1, 1), false); @@ -3763,106 +3825,116 @@ void wxSheet::DrawGridCells( wxDC& dc, const wxSheetSelection& blockSel_ ) } */ -void wxSheet::DrawGridSpace( wxDC& dc ) +void wxSheet::DrawGridSpace(wxDC &dc) { - int cw, ch; - m_gridWin->GetClientSize( &cw, &ch ); + int cw, ch; + m_gridWin->GetClientSize(&cw, &ch); - int right, bottom; - CalcUnscrolledPosition( cw, ch, &right, &bottom ); + int right, bottom; + CalcUnscrolledPosition(cw, ch, &right, &bottom); - const int numRows = GetNumberRows(); - const int numCols = GetNumberCols(); - const int bottomRow = numRows > 0 ? GetRowBottom(numRows - 1) + 1: 0; - const int rightCol = numCols > 0 ? GetColRight(numCols - 1) + 1: 0; + const int numRows = GetNumberRows(); + const int numCols = GetNumberCols(); + const int bottomRow = numRows > 0 ? GetRowBottom(numRows - 1) + 1 : 0; + const int rightCol = numCols > 0 ? GetColRight(numCols - 1) + 1 : 0; - if ( (right > rightCol) || (bottom > bottomRow) ) - { - int left, top; - CalcUnscrolledPosition( 0, 0, &left, &top ); + if ((right > rightCol) || (bottom > bottomRow)) { + int left, top; + CalcUnscrolledPosition(0, 0, &left, &top); - dc.SetBrush( wxBrush(GetAttrBackgroundColour(wxSheetCoords(0,0), wxSHEET_AttrDefault), wxBRUSHSTYLE_SOLID) ); - dc.SetPen( *wxTRANSPARENT_PEN ); + dc.SetBrush(wxBrush(GetAttrBackgroundColour(wxSheetCoords(0, 0), wxSHEET_AttrDefault), + wxBRUSHSTYLE_SOLID)); + dc.SetPen(*wxTRANSPARENT_PEN); - if ( right > rightCol ) - dc.DrawRectangle( rightCol, top, right - rightCol, ch ); - if ( bottom > bottomRow ) - dc.DrawRectangle( left, bottomRow, cw, bottom - bottomRow ); + if (right > rightCol) { + dc.DrawRectangle(rightCol, top, right - rightCol, ch); + } + if (bottom > bottomRow) { + dc.DrawRectangle(left, bottomRow, cw, bottom - bottomRow); } + } } -void wxSheet::DrawCell( wxDC& dc, const wxSheetCoords& coords ) +void wxSheet::DrawCell(wxDC &dc, const wxSheetCoords &coords) { - wxRect rect(CellToRect(coords)); - if (wxRectIsEmpty(rect)) // !IsShown - return; + wxRect rect(CellToRect(coords)); + if (wxRectIsEmpty(rect)) { // !IsShown + return; + } - // we draw the cell border ourselves + // we draw the cell border ourselves #if !WXSHEET_DRAW_LINES - if ( GridLinesEnabled() != 0 ) - DrawCellBorder( dc, coords ); + if (GridLinesEnabled() != 0) { + DrawCellBorder(dc, coords); + } #endif - wxSheetCellAttr attr(GetAttr(coords)); + wxSheetCellAttr attr(GetAttr(coords)); - // if the editor is shown, we should use it and not the renderer - if ( (coords == GetEditControlCoords()) && IsCellEditControlShown() ) - GetSheetRefData()->m_cellEditor.PaintBackground(*this, attr, dc, rect, coords, IsCellSelected(coords)); - else - attr.GetRenderer(this, coords).Draw(*this, attr, dc, rect, coords, IsCellSelected(coords)); + // if the editor is shown, we should use it and not the renderer + if ((coords == GetEditControlCoords()) && IsCellEditControlShown()) { + GetSheetRefData()->m_cellEditor.PaintBackground(*this, attr, dc, rect, coords, + IsCellSelected(coords)); + } + else { + attr.GetRenderer(this, coords).Draw(*this, attr, dc, rect, coords, IsCellSelected(coords)); + } } -void wxSheet::DrawCursorHighlight(wxDC& dc, const wxSheetSelection& blockSel) +void wxSheet::DrawCursorHighlight(wxDC &dc, const wxSheetSelection &blockSel) { - // Make sure that the cursor is valid (just in case) - if ( !ContainsGridCell(GetGridCursorCell()) && GetNumberRows() && GetNumberCols() ) - GetSheetRefData()->m_cursorCoords.Set(0, 0); + // Make sure that the cursor is valid (just in case) + if (!ContainsGridCell(GetGridCursorCell()) && GetNumberRows() && GetNumberCols()) { + GetSheetRefData()->m_cursorCoords.Set(0, 0); + } - // don't show highlight when the edit control is shown - if (!blockSel.Contains(GetGridCursorCell()) || IsCellEditControlShown()) - return; + // don't show highlight when the edit control is shown + if (!blockSel.Contains(GetGridCursorCell()) || IsCellEditControlShown()) { + return; + } - DrawCursorCellHighlight(dc, GetAttr(GetGridCursorCell())); + DrawCursorCellHighlight(dc, GetAttr(GetGridCursorCell())); } -void wxSheet::DrawCursorCellHighlight( wxDC& dc, const wxSheetCellAttr& attr ) +void wxSheet::DrawCursorCellHighlight(wxDC &dc, const wxSheetCellAttr &attr) { - if (!ContainsGridCell(GetGridCursorCell())) - return; - - wxSheetCoords coords(GetCellOwner(GetGridCursorCell())); - wxRect rect( CellToRect(coords) ); - if (wxRectIsEmpty(rect)) // !IsCellShown - return; - - // hmmm... what could we do here to show that the cell is disabled? - // for now, I just draw a thinner border than for the other ones, but - // it doesn't look really good - - int penWidth = attr.GetReadOnly() ? GetCursorCellHighlightROPenWidth() : - GetCursorCellHighlightPenWidth(); + if (!ContainsGridCell(GetGridCursorCell())) { + return; + } - if (penWidth > 0) - { - // The center of the drawn line is where the position/width/height of - // the rectangle is actually at, (on wxMSW atr least,) so we will - // reduce the size of the rectangle to compensate for the thickness of - // the line. If this is too strange on non wxMSW platforms then - // please #ifdef this appropriately. - rect.x += penWidth/2; - rect.y += penWidth/2; - rect.width -= penWidth-1; - rect.height -= penWidth-1; - - // Now draw the rectangle - // use the cellHighlightColour if the cell is inside a selection, this - // will ensure the cell is always visible. - dc.SetPen(wxPen(IsCellSelected(coords) ? GetSelectionForeground() : - GetCursorCellHighlightColour(), - penWidth, wxPENSTYLE_SOLID)); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.DrawRectangle(rect); - } + wxSheetCoords coords(GetCellOwner(GetGridCursorCell())); + wxRect rect(CellToRect(coords)); + if (wxRectIsEmpty(rect)) { // !IsCellShown + return; + } + + // hmmm... what could we do here to show that the cell is disabled? + // for now, I just draw a thinner border than for the other ones, but + // it doesn't look really good + + int penWidth = + attr.GetReadOnly() ? GetCursorCellHighlightROPenWidth() : GetCursorCellHighlightPenWidth(); + + if (penWidth > 0) { + // The center of the drawn line is where the position/width/height of + // the rectangle is actually at, (on wxMSW atr least,) so we will + // reduce the size of the rectangle to compensate for the thickness of + // the line. If this is too strange on non wxMSW platforms then + // please #ifdef this appropriately. + rect.x += penWidth / 2; + rect.y += penWidth / 2; + rect.width -= penWidth - 1; + rect.height -= penWidth - 1; + + // Now draw the rectangle + // use the cellHighlightColour if the cell is inside a selection, this + // will ensure the cell is always visible. + dc.SetPen( + wxPen(IsCellSelected(coords) ? GetSelectionForeground() : GetCursorCellHighlightColour(), + penWidth, wxPENSTYLE_SOLID)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(rect); + } #if 0 // VZ: my experiments with 3d borders... @@ -3886,45 +3958,43 @@ void wxSheet::DrawCursorCellHighlight( wxDC& dc, const wxSheetCellAttr& attr ) #endif // 0 } -void wxSheet::DrawCellBorder( wxDC& dc, const wxSheetCoords& coords ) +void wxSheet::DrawCellBorder(wxDC &dc, const wxSheetCoords &coords) { - wxRect rect(CellToRect( coords )); - if ( wxRectIsEmpty(rect) ) // !IsCellShown - return; + wxRect rect(CellToRect(coords)); + if (wxRectIsEmpty(rect)) { // !IsCellShown + return; + } - dc.SetPen( wxPen(GetGridLineColour(), 1, wxPENSTYLE_SOLID) ); - if ((GridLinesEnabled() & wxVERTICAL) != 0) - { - // right hand border - dc.DrawLine( rect.x + rect.width, rect.y, - rect.x + rect.width, rect.y + rect.height + 1 ); - } - if ((GridLinesEnabled() & wxHORIZONTAL) != 0) - { - // bottom border - dc.DrawLine( rect.x, rect.y + rect.height, - rect.x + rect.width, rect.y + rect.height); - } + dc.SetPen(wxPen(GetGridLineColour(), 1, wxPENSTYLE_SOLID)); + if ((GridLinesEnabled() & wxVERTICAL) != 0) { + // right hand border + dc.DrawLine(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + rect.height + 1); + } + if ((GridLinesEnabled() & wxHORIZONTAL) != 0) { + // bottom border + dc.DrawLine(rect.x, rect.y + rect.height, rect.x + rect.width, rect.y + rect.height); + } } // TODO: remove this ??? // This is used to redraw all grid lines e.g. when the grid line colour // has been changed -void wxSheet::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) +void wxSheet::DrawAllGridLines(wxDC &dc, const wxRegion &WXUNUSED(reg)) { #if !WXSHEET_DRAW_LINES - return; + return; #endif - const int numRows = GetNumberRows(); - const int numCols = GetNumberCols(); + const int numRows = GetNumberRows(); + const int numCols = GetNumberCols(); - if ( GetBatchCount() || (GridLinesEnabled() == 0) || !numRows || !numCols ) - return; + if (GetBatchCount() || (GridLinesEnabled() == 0) || !numRows || !numCols) { + return; + } - int top, bottom, left, right; + int top, bottom, left, right; -#if 0 //#ifndef __WXGTK__ +#if 0 // #ifndef __WXGTK__ if (reg.IsEmpty()) { int cw, ch; @@ -3942,784 +4012,817 @@ void wxSheet::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) CalcUnscrolledPosition( x + w, y + h, &right, &bottom ); } #else - int cw, ch; - m_gridWin->GetClientSize(&cw, &ch); - CalcUnscrolledPosition( 0, 0, &left, &top ); - CalcUnscrolledPosition( cw, ch, &right, &bottom ); + int cw, ch; + m_gridWin->GetClientSize(&cw, &ch); + CalcUnscrolledPosition(0, 0, &left, &top); + CalcUnscrolledPosition(cw, ch, &right, &bottom); #endif - // avoid drawing grid lines past the last row and col - right = wxMin( right, GetColRight(numCols - 1) ); - bottom = wxMin( bottom, GetRowBottom(numRows - 1) ); + // avoid drawing grid lines past the last row and col + right = wxMin(right, GetColRight(numCols - 1)); + bottom = wxMin(bottom, GetRowBottom(numRows - 1)); - // no gridlines inside spanned cells, clip them out - int leftCol = XToGridCol(left, true); - int topRow = YToGridRow(top, true); - int rightCol = XToGridCol(right, true); - int bottomRow = YToGridRow(bottom, true); - int i; + // no gridlines inside spanned cells, clip them out + int leftCol = XToGridCol(left, true); + int topRow = YToGridRow(top, true); + int rightCol = XToGridCol(right, true); + int bottomRow = YToGridRow(bottom, true); + int i; - if (HasSpannedCells()) - { - const wxSheetBlock block(topRow, leftCol, bottomRow-topRow+1, rightCol-leftCol+1); - wxRegion clippedcells(0, 0, cw, ch); - bool done = false; + if (HasSpannedCells()) { + const wxSheetBlock block(topRow, leftCol, bottomRow - topRow + 1, rightCol - leftCol + 1); + wxRegion clippedcells(0, 0, cw, ch); + bool done = false; - if (GetSpannedBlocks()) - { - const wxSheetSelection* spannedBlocks = GetSpannedBlocks(); - const int count = spannedBlocks->GetCount(); + if (GetSpannedBlocks()) { + const wxSheetSelection *spannedBlocks = GetSpannedBlocks(); + const int count = spannedBlocks->GetCount(); - for (i=spannedBlocks->FindTopRow(topRow); iGetBlock(i); - if (block.Intersects(b)) - { - clippedcells.Subtract(BlockToRect(b, true)); - done = true; - } - else if (bottomRow < b.GetTop()) - break; - } + for (i = spannedBlocks->FindTopRow(topRow); i < count; i++) { + const wxSheetBlock &b = spannedBlocks->GetBlock(i); + if (block.Intersects(b)) { + clippedcells.Subtract(BlockToRect(b, true)); + done = true; } - else // grind through it - { - wxSheetCoords c; - for (c.m_row = topRow; c.m_row <= bottomRow; c.m_row++) - { - for (c.m_col = leftCol; c.m_col <= rightCol; c.m_col++) - { - const wxSheetBlock b(GetCellBlock(c)); - if (!b.IsOneCell()) - { - done = true; - clippedcells.Subtract(BlockToRect(b, true)); - } - } - } + else if (bottomRow < b.GetTop()) { + break; } - - if (done) - dc.SetDeviceClippingRegion( clippedcells ); + } } - - dc.SetPen( wxPen(GetGridLineColour(), 1, wxPENSTYLE_SOLID) ); - - if ((GridLinesEnabled() & wxHORIZONTAL) != 0) + else // grind through it { - for ( i = topRow; i < numRows; i++ ) - { - int rowBottom = GetRowBottom(i); - if ( rowBottom > bottom ) - break; - - if ( rowBottom >= top ) - dc.DrawLine( left, rowBottom, right, rowBottom ); + wxSheetCoords c; + for (c.m_row = topRow; c.m_row <= bottomRow; c.m_row++) { + for (c.m_col = leftCol; c.m_col <= rightCol; c.m_col++) { + const wxSheetBlock b(GetCellBlock(c)); + if (!b.IsOneCell()) { + done = true; + clippedcells.Subtract(BlockToRect(b, true)); + } } + } } - if ((GridLinesEnabled() & wxVERTICAL) != 0) - { - for ( i = leftCol; i < numCols; i++ ) - { - int colRight = GetColRight(i); - if ( colRight > right ) - break; - - if ( colRight >= left ) - dc.DrawLine( colRight, top, colRight, bottom ); - } + if (done) { + dc.SetDeviceClippingRegion(clippedcells); } + } - dc.DestroyClippingRegion(); -} - -void wxSheet::DrawRowLabels( wxDC& dc, const wxArrayInt& rows ) -{ - size_t i, numLabels = rows.GetCount(); - if ( !GetNumberRows() || !numLabels ) return; - - for ( i = 0; i < numLabels; i++ ) - DrawCell( dc, wxSheetCoords(rows[i], -1) ); + dc.SetPen(wxPen(GetGridLineColour(), 1, wxPENSTYLE_SOLID)); -/* // sample native rendernative code - FIXME - rect.SetX( 1 ); - rect.SetY( GetRowTop(row) + 1 ); - rect.SetWidth( m_rowLabelWidth - 2 ); - rect.SetHeight( GetRowHeight(row) - 2 ); - CalcScrolledPosition( 0, rect.y, NULL, &rect.y ); - wxWindowDC *win_dc = (wxWindowDC*) &dc; - wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); -*/ + if ((GridLinesEnabled() & wxHORIZONTAL) != 0) { + for (i = topRow; i < numRows; i++) { + int rowBottom = GetRowBottom(i); + if (rowBottom > bottom) { + break; + } - // Now draw the dividing lines - dc.SetPen( wxPen(GetLabelOutlineColour(), 1, wxPENSTYLE_SOLID) ); - int top; - CalcUnscrolledPosition(0, 0, NULL, &top); - //int top = GetRowTop(rows[0]); - int bottom = top + m_gridWin->GetSize().y; //GetRowBottom(rows[numLabels-1]); - int width = GetRowLabelWidth(); - // left of row labels - dc.DrawLine(0, top, 0, bottom); - // right of row labels - dc.DrawLine(width-1, top, width-1, bottom); - // draw bottoms - wxSheetCoords coords(0, -1); - for ( i = 0; i < numLabels; i++ ) - { - coords.m_row = rows[i]; - bottom = GetRowBottom(GetCellBlock(coords).GetBottom()); - dc.DrawLine(0, bottom, width-1, bottom); + if (rowBottom >= top) { + dc.DrawLine(left, rowBottom, right, rowBottom); + } } -} - -void wxSheet::DrawColLabels( wxDC& dc, const wxArrayInt& cols ) -{ - size_t i, numLabels = cols.GetCount(); - if ( !GetNumberCols() || !numLabels ) return; - - for ( i = 0; i < numLabels; i++ ) - DrawCell( dc, wxSheetCoords(-1, cols[i]) ); + } -/* // sample native rendernative code - FIXME - rect.SetX( colLeft + 1 ); - rect.SetY( 1 ); - rect.SetWidth( GetColWidth(col) - 2 ); - rect.SetHeight( m_colLabelHeight - 2 ); - wxWindowDC *win_dc = (wxWindowDC*) &dc; - wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); -*/ + if ((GridLinesEnabled() & wxVERTICAL) != 0) { + for (i = leftCol; i < numCols; i++) { + int colRight = GetColRight(i); + if (colRight > right) { + break; + } - // Now draw the dividing lines - dc.SetPen( wxPen(GetLabelOutlineColour(), 1, wxPENSTYLE_SOLID) ); - int left; - CalcUnscrolledPosition(0, 0, &left, NULL); - //int left = GetColLeft(cols[0]); - int right = left + m_gridWin->GetSize().x; //GetColRight(cols[numLabels-1]); - int height = GetColLabelHeight(); - // top of col labels - dc.DrawLine(left, 0, right, 0); - // bottom of col labels - dc.DrawLine(left, height-1, right, height-1); - // draw rights - wxSheetCoords coords(-1, 0); - for ( i = 0; i < numLabels; i++ ) - { - coords.m_col = cols[i]; - right = GetColRight(GetCellBlock(coords).GetRight()); - dc.DrawLine(right, 0, right, height-1); + if (colRight >= left) { + dc.DrawLine(colRight, top, colRight, bottom); + } } + } + + dc.DestroyClippingRegion(); } -void wxSheet::DrawCornerLabel( wxDC& dc ) +void wxSheet::DrawRowLabels(wxDC &dc, const wxArrayInt &rows) { - DrawCell( dc, wxSheetCoords(-1, -1) ); - wxSize size(m_cornerLabelWin->GetClientSize()); + size_t i, numLabels = rows.GetCount(); + if (!GetNumberRows() || !numLabels) { + return; + } + + for (i = 0; i < numLabels; i++) { + DrawCell(dc, wxSheetCoords(rows[i], -1)); + } + + /* // sample native rendernative code - FIXME + rect.SetX( 1 ); + rect.SetY( GetRowTop(row) + 1 ); + rect.SetWidth( m_rowLabelWidth - 2 ); + rect.SetHeight( GetRowHeight(row) - 2 ); + CalcScrolledPosition( 0, rect.y, NULL, &rect.y ); + wxWindowDC *win_dc = (wxWindowDC*) &dc; + wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); + */ + + // Now draw the dividing lines + dc.SetPen(wxPen(GetLabelOutlineColour(), 1, wxPENSTYLE_SOLID)); + int top; + CalcUnscrolledPosition(0, 0, NULL, &top); + // int top = GetRowTop(rows[0]); + int bottom = top + m_gridWin->GetSize().y; // GetRowBottom(rows[numLabels-1]); + int width = GetRowLabelWidth(); + // left of row labels + dc.DrawLine(0, top, 0, bottom); + // right of row labels + dc.DrawLine(width - 1, top, width - 1, bottom); + // draw bottoms + wxSheetCoords coords(0, -1); + for (i = 0; i < numLabels; i++) { + coords.m_row = rows[i]; + bottom = GetRowBottom(GetCellBlock(coords).GetBottom()); + dc.DrawLine(0, bottom, width - 1, bottom); + } +} + +void wxSheet::DrawColLabels(wxDC &dc, const wxArrayInt &cols) +{ + size_t i, numLabels = cols.GetCount(); + if (!GetNumberCols() || !numLabels) { + return; + } + + for (i = 0; i < numLabels; i++) { + DrawCell(dc, wxSheetCoords(-1, cols[i])); + } + + /* // sample native rendernative code - FIXME + rect.SetX( colLeft + 1 ); + rect.SetY( 1 ); + rect.SetWidth( GetColWidth(col) - 2 ); + rect.SetHeight( m_colLabelHeight - 2 ); + wxWindowDC *win_dc = (wxWindowDC*) &dc; + wxRendererNative::Get().DrawHeaderButton( win_dc->m_owner, dc, rect, 0 ); + */ + + // Now draw the dividing lines + dc.SetPen(wxPen(GetLabelOutlineColour(), 1, wxPENSTYLE_SOLID)); + int left; + CalcUnscrolledPosition(0, 0, &left, NULL); + // int left = GetColLeft(cols[0]); + int right = left + m_gridWin->GetSize().x; // GetColRight(cols[numLabels-1]); + int height = GetColLabelHeight(); + // top of col labels + dc.DrawLine(left, 0, right, 0); + // bottom of col labels + dc.DrawLine(left, height - 1, right, height - 1); + // draw rights + wxSheetCoords coords(-1, 0); + for (i = 0; i < numLabels; i++) { + coords.m_col = cols[i]; + right = GetColRight(GetCellBlock(coords).GetRight()); + dc.DrawLine(right, 0, right, height - 1); + } +} + +void wxSheet::DrawCornerLabel(wxDC &dc) +{ + DrawCell(dc, wxSheetCoords(-1, -1)); + wxSize size(m_cornerLabelWin->GetClientSize()); #ifdef USE_RENDERNATIVE - wxRect rect(1, 1, size.x-2, size.y-2); - //rect.SetX( 1 ); - //rect.SetY( 1 ); - //rect.SetWidth( client_width - 2 ); - //rect.SetHeight( client_height - 2 ); - wxRendererNative::Get().DrawHeaderButton( this, dc, rect, 0 ); + wxRect rect(1, 1, size.x - 2, size.y - 2); + // rect.SetX( 1 ); + // rect.SetY( 1 ); + // rect.SetWidth( client_width - 2 ); + // rect.SetHeight( client_height - 2 ); + wxRendererNative::Get().DrawHeaderButton(this, dc, rect, 0); #else - // Now draw the dividing lines - dc.SetPen( wxPen(GetLabelOutlineColour(), 1, wxPENSTYLE_SOLID) ); - dc.DrawLine(0, 0, size.x, 0); // top - dc.DrawLine(0, size.y-1, size.x, size.y-1); // bottom - dc.DrawLine(0, 0, 0, size.y-1); // left - dc.DrawLine(size.x-1, 0, size.x-1, size.y-1); // right + // Now draw the dividing lines + dc.SetPen(wxPen(GetLabelOutlineColour(), 1, wxPENSTYLE_SOLID)); + dc.DrawLine(0, 0, size.x, 0); // top + dc.DrawLine(0, size.y - 1, size.x, size.y - 1); // bottom + dc.DrawLine(0, 0, 0, size.y - 1); // left + dc.DrawLine(size.x - 1, 0, size.x - 1, size.y - 1); // right #endif } -void wxSheet::DrawRowColResizingMarker( int newDragPos ) +void wxSheet::DrawRowColResizingMarker(int newDragPos) { - if ( !HasMouseCursorMode(WXSHEET_CURSOR_RESIZING) || - ((m_dragLastPos == -1) && (newDragPos == -1)) ) - return; + if (!HasMouseCursorMode(WXSHEET_CURSOR_RESIZING) || + ((m_dragLastPos == -1) && (newDragPos == -1))) { + return; + } - wxClientDC dc( m_gridWin ); - PrepareGridDC( dc ); + wxClientDC dc(m_gridWin); + PrepareGridDC(dc); - int left = 0, top = 0; - CalcUnscrolledPosition( 0, 0, &left, &top ); + int left = 0, top = 0; + CalcUnscrolledPosition(0, 0, &left, &top); - int right = GetColRight(GetNumberCols()-1); - int bottom = GetRowBottom(GetNumberRows()-1); - int cw = 0, ch = 0; - m_gridWin->GetClientSize( &cw, &ch ); - right = wxMin(left+cw, right); - bottom = wxMin(top+ch, bottom); + int right = GetColRight(GetNumberCols() - 1); + int bottom = GetRowBottom(GetNumberRows() - 1); + int cw = 0, ch = 0; + m_gridWin->GetClientSize(&cw, &ch); + right = wxMin(left + cw, right); + bottom = wxMin(top + ch, bottom); - const bool resizingRow = HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW); + const bool resizingRow = HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW); - if (GridLinesEnabled()) - { - dc.SetPen(wxPen(GetGridLineColour(), 3, wxPENSTYLE_SOLID)); + if (GridLinesEnabled()) { + dc.SetPen(wxPen(GetGridLineColour(), 3, wxPENSTYLE_SOLID)); - // Draw the anchor marker so you know what row/col you're resizing - if (resizingRow) - { - int anchor = GetRowTop(m_dragRowOrCol); - dc.DrawLine( left, anchor, right, anchor ); - } - else // resizing col - { - int anchor = GetColLeft(m_dragRowOrCol); - dc.DrawLine( anchor, top, anchor, bottom ); - } + // Draw the anchor marker so you know what row/col you're resizing + if (resizingRow) { + int anchor = GetRowTop(m_dragRowOrCol); + dc.DrawLine(left, anchor, right, anchor); + } + else // resizing col + { + int anchor = GetColLeft(m_dragRowOrCol); + dc.DrawLine(anchor, top, anchor, bottom); } + } #if wxCHECK_VERSION(2, 9, 0) - wxRasterOperationMode log_fn = dc.GetLogicalFunction(); + wxRasterOperationMode log_fn = dc.GetLogicalFunction(); #else - int log_fn = dc.GetLogicalFunction(); -#endif /* wxCHECK_VERSION */ - dc.SetLogicalFunction(wxINVERT); + int log_fn = dc.GetLogicalFunction(); +#endif /* wxCHECK_VERSION */ + dc.SetLogicalFunction(wxINVERT); - if (m_dragLastPos >= 0) - { - if (resizingRow) - dc.DrawLine( left, m_dragLastPos, right, m_dragLastPos ); - else // resizing col - dc.DrawLine( m_dragLastPos, top, m_dragLastPos, bottom ); + if (m_dragLastPos >= 0) { + if (resizingRow) { + dc.DrawLine(left, m_dragLastPos, right, m_dragLastPos); } + else { // resizing col + dc.DrawLine(m_dragLastPos, top, m_dragLastPos, bottom); + } + } - if (newDragPos >= 0) - { - m_dragLastPos = newDragPos; + if (newDragPos >= 0) { + m_dragLastPos = newDragPos; - if (resizingRow) - dc.DrawLine( left, m_dragLastPos, right, m_dragLastPos ); - else // resizing col - dc.DrawLine( m_dragLastPos, top, m_dragLastPos, bottom ); + if (resizingRow) { + dc.DrawLine(left, m_dragLastPos, right, m_dragLastPos); } + else { // resizing col + dc.DrawLine(m_dragLastPos, top, m_dragLastPos, bottom); + } + } - dc.SetLogicalFunction(log_fn); // set it back since nobody else wants invert + dc.SetLogicalFunction(log_fn); // set it back since nobody else wants invert } -bool wxSheet::CalcRowLabelsExposed( const wxRegion& reg, wxArrayInt& rowLabels ) const +bool wxSheet::CalcRowLabelsExposed(const wxRegion ®, wxArrayInt &rowLabels) const { - const int numRows = GetNumberRows(); - if (!numRows) - return false; + const int numRows = GetNumberRows(); + if (!numRows) { + return false; + } - const bool spanned = HasSpannedCells(); - wxRegionIterator iter( reg ); + const bool spanned = HasSpannedCells(); + wxRegionIterator iter(reg); - while ( iter ) - { - wxRect r(iter.GetRect()); + while (iter) { + wxRect r(iter.GetRect()); - // TODO: remove this when we can... - // There is a bug in wxMotif that gives garbage update - // rectangles if you jump-scroll a long way by clicking the - // scrollbar with middle button. This is a work-around - // + // TODO: remove this when we can... + // There is a bug in wxMotif that gives garbage update + // rectangles if you jump-scroll a long way by clicking the + // scrollbar with middle button. This is a work-around + // #if defined(__WXMOTIF__) - int cw, ch; - m_gridWin->GetClientSize( &cw, &ch ); - if ( r.GetTop() > ch ) r.SetTop( 0 ); - r.SetBottom( wxMin( r.GetBottom(), ch ) ); + int cw, ch; + m_gridWin->GetClientSize(&cw, &ch); + if (r.GetTop() > ch) { + r.SetTop(0); + } + r.SetBottom(wxMin(r.GetBottom(), ch)); #endif - // logical bounds of update region - int top; - CalcUnscrolledPosition( 0, r.GetTop(), NULL, &top ); - int bottom = top + r.GetHeight(); - //CalcUnscrolledPosition( 0, r.GetBottom(), &dummy, &bottom ); + // logical bounds of update region + int top; + CalcUnscrolledPosition(0, r.GetTop(), NULL, &top); + int bottom = top + r.GetHeight(); + // CalcUnscrolledPosition( 0, r.GetBottom(), &dummy, &bottom ); - // find the row labels within these bounds - for ( int row = YToGridRow(top, true); row < numRows; row++ ) - { - if ( GetRowBottom(row) < top ) - continue; - if ( GetRowTop(row) > bottom ) - break; + // find the row labels within these bounds + for (int row = YToGridRow(top, true); row < numRows; row++) { + if (GetRowBottom(row) < top) { + continue; + } + if (GetRowTop(row) > bottom) { + break; + } - if (spanned) - { - const wxSheetBlock block(GetCellBlock(wxSheetCoords(row, -1))); + if (spanned) { + const wxSheetBlock block(GetCellBlock(wxSheetCoords(row, -1))); - if (block.GetHeight() >= 1) - { - rowLabels.Add( block.GetTop() ); - row = block.GetBottom(); - } - else if (block.GetHeight() < 1) - row = block.GetBottom(); - } - else - rowLabels.Add( row ); + if (block.GetHeight() >= 1) { + rowLabels.Add(block.GetTop()); + row = block.GetBottom(); } - - iter++ ; + else if (block.GetHeight() < 1) { + row = block.GetBottom(); + } + } + else { + rowLabels.Add(row); + } } - return rowLabels.GetCount() > 0u; + iter++; + } + + return rowLabels.GetCount() > 0u; } -bool wxSheet::CalcColLabelsExposed( const wxRegion& reg, wxArrayInt& colLabels ) const +bool wxSheet::CalcColLabelsExposed(const wxRegion ®, wxArrayInt &colLabels) const { - const int numCols = GetNumberCols(); - if (!numCols) - return false; + const int numCols = GetNumberCols(); + if (!numCols) { + return false; + } - const bool spanned = HasSpannedCells(); - wxRegionIterator iter( reg ); + const bool spanned = HasSpannedCells(); + wxRegionIterator iter(reg); - while ( iter ) - { - wxRect r(iter.GetRect()); + while (iter) { + wxRect r(iter.GetRect()); - // TODO: remove this when we can... - // There is a bug in wxMotif that gives garbage update - // rectangles if you jump-scroll a long way by clicking the - // scrollbar with middle button. This is a work-around - // + // TODO: remove this when we can... + // There is a bug in wxMotif that gives garbage update + // rectangles if you jump-scroll a long way by clicking the + // scrollbar with middle button. This is a work-around + // #if defined(__WXMOTIF__) - int cw, ch; - m_gridWin->GetClientSize( &cw, &ch ); - if ( r.GetLeft() > cw ) r.SetLeft( 0 ); - r.SetRight( wxMin( r.GetRight(), cw ) ); + int cw, ch; + m_gridWin->GetClientSize(&cw, &ch); + if (r.GetLeft() > cw) { + r.SetLeft(0); + } + r.SetRight(wxMin(r.GetRight(), cw)); #endif - // logical bounds of update region - int left; - CalcUnscrolledPosition( r.GetLeft(), 0, &left, NULL ); - int right = left + r.GetWidth(); - //CalcUnscrolledPosition( r.GetRight(), 0, &right, &dummy ); + // logical bounds of update region + int left; + CalcUnscrolledPosition(r.GetLeft(), 0, &left, NULL); + int right = left + r.GetWidth(); + // CalcUnscrolledPosition( r.GetRight(), 0, &right, &dummy ); - // find the cells within these bounds - for ( int col = XToGridCol(left, true); col < numCols; col++ ) - { - if ( GetColRight(col) < left ) - continue; - if ( GetColLeft(col) > right ) - break; + // find the cells within these bounds + for (int col = XToGridCol(left, true); col < numCols; col++) { + if (GetColRight(col) < left) { + continue; + } + if (GetColLeft(col) > right) { + break; + } - if (spanned) - { - const wxSheetBlock block(GetCellBlock(wxSheetCoords(-1, col))); + if (spanned) { + const wxSheetBlock block(GetCellBlock(wxSheetCoords(-1, col))); - if (block.GetWidth() >= 1) - { - colLabels.Add( block.GetLeft() ); - col = block.GetRight(); - } - else if (block.GetWidth() < 1) - col = block.GetRight(); - } - else - colLabels.Add( col ); + if (block.GetWidth() >= 1) { + colLabels.Add(block.GetLeft()); + col = block.GetRight(); } - - iter++ ; + else if (block.GetWidth() < 1) { + col = block.GetRight(); + } + } + else { + colLabels.Add(col); + } } - return colLabels.GetCount() > 0u; + + iter++; + } + return colLabels.GetCount() > 0u; } -bool wxSheet::CalcCellsExposed( const wxRegion& reg, wxSheetSelection& blockSel ) const +bool wxSheet::CalcCellsExposed(const wxRegion ®, wxSheetSelection &blockSel) const { - const int numRows = GetNumberRows(); - const int numCols = GetNumberCols(); - if (!numRows || !numCols) - return false; + const int numRows = GetNumberRows(); + const int numCols = GetNumberCols(); + if (!numRows || !numCols) { + return false; + } - wxRegionIterator iter( reg ); - while ( iter ) - { - wxRect r(iter.GetRect()); + wxRegionIterator iter(reg); + while (iter) { + wxRect r(iter.GetRect()); - // TODO: remove this when we can... - // There is a bug in wxMotif that gives garbage update - // rectangles if you jump-scroll a long way by clicking the - // scrollbar with middle button. This is a work-around - // + // TODO: remove this when we can... + // There is a bug in wxMotif that gives garbage update + // rectangles if you jump-scroll a long way by clicking the + // scrollbar with middle button. This is a work-around + // #if defined(__WXMOTIF__) - int cw, ch; - m_gridWin->GetClientSize( &cw, &ch ); - if ( r.GetTop() > ch ) r.SetTop( 0 ); - if ( r.GetLeft() > cw ) r.SetLeft( 0 ); - r.SetRight( wxMin( r.GetRight(), cw ) ); - r.SetBottom( wxMin( r.GetBottom(), ch ) ); + int cw, ch; + m_gridWin->GetClientSize(&cw, &ch); + if (r.GetTop() > ch) { + r.SetTop(0); + } + if (r.GetLeft() > cw) { + r.SetLeft(0); + } + r.SetRight(wxMin(r.GetRight(), cw)); + r.SetBottom(wxMin(r.GetBottom(), ch)); #endif - // logical bounds of update region - int left, top, right, bottom; - CalcUnscrolledPosition( r.GetLeft(), r.GetTop(), &left, &top ); - CalcUnscrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom ); + // logical bounds of update region + int left, top, right, bottom; + CalcUnscrolledPosition(r.GetLeft(), r.GetTop(), &left, &top); + CalcUnscrolledPosition(r.GetRight(), r.GetBottom(), &right, &bottom); - // find the cells within these bounds - wxSheetBlock block(YToGridRow(top, true), XToGridCol(left, true), 0, 0); - int row, col; - for ( row = block.GetTop(); row < numRows; row++ ) - { - if ( GetRowBottom(row) <= top ) - continue; - else if ( GetRowTop(row) > bottom ) - break; - } + // find the cells within these bounds + wxSheetBlock block(YToGridRow(top, true), XToGridCol(left, true), 0, 0); + int row, col; + for (row = block.GetTop(); row < numRows; row++) { + if (GetRowBottom(row) <= top) { + continue; + } + else if (GetRowTop(row) > bottom) { + break; + } + } - for ( col = block.GetLeft(); col < numCols; col++ ) - { - if ( GetColRight(col) <= left ) - continue; - else if ( GetColLeft(col) > right ) - break; - } + for (col = block.GetLeft(); col < numCols; col++) { + if (GetColRight(col) <= left) { + continue; + } + else if (GetColLeft(col) > right) { + break; + } + } - block.SetRight(col - 1); - block.SetBottom(row - 1); + block.SetRight(col - 1); + block.SetBottom(row - 1); - blockSel.SelectBlock(block, false); + blockSel.SelectBlock(block, false); - iter++; - } + iter++; + } - return blockSel.GetCount() > 0; + return blockSel.GetCount() > 0; } -void wxSheet::DrawTextRectangle( wxDC& dc, const wxString& value, - const wxRect& rect, int align, - int textOrientation ) +void wxSheet::DrawTextRectangle(wxDC &dc, const wxString &value, const wxRect &rect, int align, + int textOrientation) { - wxArrayString lines; - if (StringToLines( value, lines ) > 0) - DrawTextRectangle( dc, lines, rect, align, textOrientation ); + wxArrayString lines; + if (StringToLines(value, lines) > 0) { + DrawTextRectangle(dc, lines, rect, align, textOrientation); + } } -void wxSheet::DrawTextRectangle( wxDC& dc, const wxArrayString& lines, - const wxRect& rect, int align, - int textOrientation ) +void wxSheet::DrawTextRectangle(wxDC &dc, const wxArrayString &lines, const wxRect &rect, + int align, int textOrientation) { - int nLines = lines.GetCount(); - if ( (nLines == 0) || ((nLines == 1) && lines[0].IsEmpty()) ) - return; + int nLines = lines.GetCount(); + if ((nLines == 0) || ((nLines == 1) && lines[0].IsEmpty())) { + return; + } - dc.SetClippingRegion( rect ); + dc.SetClippingRegion(rect); - int l; - float x = 0.0, y = 0.0; - long textWidth=0, textHeight=0; - wxCoord lineWidth=0, lineHeight=0; - wxArrayInt lineWidths, lineHeights; + int l; + float x = 0.0, y = 0.0; + long textWidth = 0, textHeight = 0; + wxCoord lineWidth = 0, lineHeight = 0; + wxArrayInt lineWidths, lineHeights; - // Measure the text extent once, Gtk2 is slow (takes 2sec off 23sec run) - for ( l = 0; l < nLines; l++ ) - { - dc.GetTextExtent(lines[l], &lineWidth, &lineHeight); - lineWidths.Add(lineWidth); - lineHeights.Add(lineHeight); - textHeight += lineHeight; - if (lineWidth > textWidth) - textWidth = lineWidth; + // Measure the text extent once, Gtk2 is slow (takes 2sec off 23sec run) + for (l = 0; l < nLines; l++) { + dc.GetTextExtent(lines[l], &lineWidth, &lineHeight); + lineWidths.Add(lineWidth); + lineHeights.Add(lineHeight); + textHeight += lineHeight; + if (lineWidth > textWidth) { + textWidth = lineWidth; } + } - // swap width and height if vertically orientated - if ( textOrientation == wxVERTICAL ) - { - long tmp = textHeight; - textHeight = textWidth; - textWidth = tmp; + // swap width and height if vertically orientated + if (textOrientation == wxVERTICAL) { + long tmp = textHeight; + textHeight = textWidth; + textWidth = tmp; + } + + if ((align & wxALIGN_BOTTOM) != 0) { + if (textOrientation == wxHORIZONTAL) { + y = rect.y + (rect.height - textHeight - 1); + } + else { // wxVERTICAL + x = rect.x + rect.width - textWidth; + } + } + else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) { + if (textOrientation == wxHORIZONTAL) { + y = rect.y + (rect.height - textHeight) / 2; } + else { // wxVERTICAL + x = rect.x + (rect.width - textWidth) / 2; + } + } + else // wxALIGN_TOP + { + if (textOrientation == wxHORIZONTAL) { + y = rect.y + 1; + } + else { // wxVERTICAL + x = rect.x + 1; + } + } - if ((align & wxALIGN_BOTTOM) != 0) - { - if ( textOrientation == wxHORIZONTAL ) - y = rect.y + (rect.height - textHeight - 1); - else // wxVERTICAL - x = rect.x + rect.width - textWidth; + // Align each line of a multi-line label + for (l = 0; l < nLines; l++) { + lineWidth = lineWidths[l]; + lineHeight = lineHeights[l]; + + if ((align & wxALIGN_RIGHT) != 0) { + if (textOrientation == wxHORIZONTAL) { + x = rect.x + (rect.width - lineWidth - 1); + } + else { // wxVERTICAL + y = rect.y + lineWidth + 1; + } } - else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) - { - if ( textOrientation == wxHORIZONTAL ) - y = rect.y + (rect.height - textHeight)/2; - else // wxVERTICAL - x = rect.x + (rect.width - textWidth)/2; + else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) { + if (textOrientation == wxHORIZONTAL) { + x = rect.x + (rect.width - lineWidth) / 2; + } + else { // wxVERTICAL + y = rect.y + rect.height - (rect.height - lineWidth) / 2; + } } - else // wxALIGN_TOP + else // wxALIGN_LEFT { - if ( textOrientation == wxHORIZONTAL ) - y = rect.y + 1; - else // wxVERTICAL - x = rect.x + 1; + if (textOrientation == wxHORIZONTAL) { + x = rect.x + 1; + } + else { // wxVERTICAL + y = rect.y + rect.height - 1; + } } - // Align each line of a multi-line label - for ( l = 0; l < nLines; l++ ) + if (textOrientation == wxHORIZONTAL) { + dc.DrawText(lines[l], (int)x, (int)y); + y += lineHeight; + } + else // wxVERTICAL { - lineWidth = lineWidths[l]; - lineHeight = lineHeights[l]; - - if ((align & wxALIGN_RIGHT) != 0) - { - if ( textOrientation == wxHORIZONTAL ) - x = rect.x + (rect.width - lineWidth - 1); - else // wxVERTICAL - y = rect.y + lineWidth + 1; - } - else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) - { - if ( textOrientation == wxHORIZONTAL ) - x = rect.x + (rect.width - lineWidth)/2; - else // wxVERTICAL - y = rect.y + rect.height - (rect.height - lineWidth)/2; - } - else // wxALIGN_LEFT - { - if ( textOrientation == wxHORIZONTAL ) - x = rect.x + 1; - else // wxVERTICAL - y = rect.y + rect.height - 1; - } - - if ( textOrientation == wxHORIZONTAL ) - { - dc.DrawText( lines[l], (int)x, (int)y ); - y += lineHeight; - } - else // wxVERTICAL - { - dc.DrawRotatedText( lines[l], (int)x, (int)y, 90.0 ); - x += lineHeight; - } + dc.DrawRotatedText(lines[l], (int)x, (int)y, 90.0); + x += lineHeight; } + } - dc.DestroyClippingRegion(); + dc.DestroyClippingRegion(); } -int wxSheet::StringToLines( const wxString& value, wxArrayString& lines ) const +int wxSheet::StringToLines(const wxString &value, wxArrayString &lines) const { - size_t len = value.Length(); - if (!len) - return 0; + size_t len = value.Length(); + if (!len) { + return 0; + } - const wxChar *c = value.GetData(); - size_t pos, count = 0, start_pos = 0; + const wxChar *c = value.GetData(); + size_t pos, count = 0, start_pos = 0; - for (pos = 0; pos < len; pos++, c++) - { - if ((*c == wxT('\n') || (*c == wxT('\r')))) - { - if (pos == start_pos) - lines.Add(wxEmptyString); - else - lines.Add(value.Mid(start_pos, pos - start_pos)); + for (pos = 0; pos < len; pos++, c++) { + if ((*c == wxT('\n') || (*c == wxT('\r')))) { + if (pos == start_pos) { + lines.Add(wxEmptyString); + } + else { + lines.Add(value.Mid(start_pos, pos - start_pos)); + } - start_pos = pos + 1; - count++; + start_pos = pos + 1; + count++; - // Check for DOS line endings and skip them - if ((*c == wxT('\r')) && (pos + 1 < len) && (c[1] == wxT('\n'))) - { - c++; - pos++; - start_pos++; - } - } + // Check for DOS line endings and skip them + if ((*c == wxT('\r')) && (pos + 1 < len) && (c[1] == wxT('\n'))) { + c++; + pos++; + start_pos++; + } } + } - if ( start_pos < len ) - { - if (start_pos == 0) - lines.Add(value); - else - lines.Add(value.Mid(start_pos)); - - count++; + if (start_pos < len) { + if (start_pos == 0) { + lines.Add(value); + } + else { + lines.Add(value.Mid(start_pos)); } - return count; + count++; + } + + return count; } -bool wxSheet::GetTextBoxSize( wxDC& dc, const wxArrayString& lines, - long *width, long *height ) const +bool wxSheet::GetTextBoxSize(wxDC &dc, const wxArrayString &lines, long *width, long *height) const { - long w = 0, h = 0; - wxCoord lineW, lineH; - size_t i, count = lines.GetCount(); - for ( i = 0; i < count; i++ ) - { - dc.GetTextExtent( lines[i], &lineW, &lineH ); - if (w < lineW) w = lineW; - h += lineH; + long w = 0, h = 0; + wxCoord lineW, lineH; + size_t i, count = lines.GetCount(); + for (i = 0; i < count; i++) { + dc.GetTextExtent(lines[i], &lineW, &lineH); + if (w < lineW) { + w = lineW; } + h += lineH; + } - if (width) *width = w; - if (height) *height = h; + if (width) { + *width = w; + } + if (height) { + *height = h; + } - return (w > 0) && (h > 0); + return (w > 0) && (h > 0); } // ---------------------------------------------------------------------------- -wxSheetCoords wxSheet::XYToGridCell( int x, int y, bool clipToMinMax ) const +wxSheetCoords wxSheet::XYToGridCell(int x, int y, bool clipToMinMax) const { - return wxSheetCoords(YToGridRow(y, clipToMinMax), XToGridCol(x, clipToMinMax)); + return wxSheetCoords(YToGridRow(y, clipToMinMax), XToGridCol(x, clipToMinMax)); } -int wxSheet::YToGridRow( int y, bool clipToMinMax ) const +int wxSheet::YToGridRow(int y, bool clipToMinMax) const { - return GetSheetRefData()->m_rowEdges.FindIndex(y, clipToMinMax); + return GetSheetRefData()->m_rowEdges.FindIndex(y, clipToMinMax); } -int wxSheet::XToGridCol( int x, bool clipToMinMax ) const +int wxSheet::XToGridCol(int x, bool clipToMinMax) const { - return GetSheetRefData()->m_colEdges.FindIndex(x, clipToMinMax); + return GetSheetRefData()->m_colEdges.FindIndex(x, clipToMinMax); } -int wxSheet::YToEdgeOfGridRow( int y ) const +int wxSheet::YToEdgeOfGridRow(int y) const { - return GetSheetRefData()->m_rowEdges.FindMaxEdgeIndex(y); + return GetSheetRefData()->m_rowEdges.FindMaxEdgeIndex(y); } -int wxSheet::XToEdgeOfGridCol( int x ) const +int wxSheet::XToEdgeOfGridCol(int x) const { - return GetSheetRefData()->m_colEdges.FindMaxEdgeIndex(x); + return GetSheetRefData()->m_colEdges.FindMaxEdgeIndex(x); } -wxRect wxSheet::CellToRect( const wxSheetCoords& coords, bool getDeviceRect ) const +wxRect wxSheet::CellToRect(const wxSheetCoords &coords, bool getDeviceRect) const { - wxCHECK_MSG(ContainsCell(coords), wxRect(0,0,0,0), wxT("Invalid coords")); - return BlockToRect(GetCellBlock(coords), getDeviceRect); + wxCHECK_MSG(ContainsCell(coords), wxRect(0, 0, 0, 0), wxT("Invalid coords")); + return BlockToRect(GetCellBlock(coords), getDeviceRect); } -wxRect wxSheet::BlockToRect( const wxSheetBlock& block, bool getDeviceRect ) const +wxRect wxSheet::BlockToRect(const wxSheetBlock &block, bool getDeviceRect) const { - wxRect rect(BlockToLogicalRect(block, false)); + wxRect rect(BlockToLogicalRect(block, false)); - // if grid lines are enabled, then the area of the cell is a bit smaller - if ((GridLinesEnabled() & wxHORIZONTAL) != 0) - rect.height--; - if ((GridLinesEnabled() & wxVERTICAL) != 0) - rect.width--; + // if grid lines are enabled, then the area of the cell is a bit smaller + if ((GridLinesEnabled() & wxHORIZONTAL) != 0) { + rect.height--; + } + if ((GridLinesEnabled() & wxVERTICAL) != 0) { + rect.width--; + } - if (getDeviceRect) - { - switch (GetCellCoordsType(block.GetLeftTop())) - { - case wxSHEET_CELL_GRID : return CalcScrolledRect(rect); - case wxSHEET_CELL_ROWLABEL : CalcScrolledPosition(0, rect.y, NULL, &rect.y); break; - case wxSHEET_CELL_COLLABEL : CalcScrolledPosition(rect.x, 0, &rect.x, NULL); break; - default : break; - } + if (getDeviceRect) { + switch (GetCellCoordsType(block.GetLeftTop())) { + case wxSHEET_CELL_GRID: + return CalcScrolledRect(rect); + case wxSHEET_CELL_ROWLABEL: + CalcScrolledPosition(0, rect.y, NULL, &rect.y); + break; + case wxSHEET_CELL_COLLABEL: + CalcScrolledPosition(rect.x, 0, &rect.x, NULL); + break; + default: + break; } + } - return rect; + return rect; } -wxSheetBlock wxSheet::ExpandSpannedBlock(const wxSheetBlock& block_) const +wxSheetBlock wxSheet::ExpandSpannedBlock(const wxSheetBlock &block_) const { - if (!HasSpannedCells() || block_.IsEmpty()) - return block_; + if (!HasSpannedCells() || block_.IsEmpty()) { + return block_; + } - wxSheetBlock block(block_); + wxSheetBlock block(block_); - if (GetSpannedBlocks()) - { - const wxSheetSelection* spannedBlocks = GetSpannedBlocks(); - size_t n, count = spannedBlocks->GetCount(); - for (n=0; nGetBlock(n); - if (block_.Intersects(b)) // use original block so it doesn't keep growing - block = block.Union(b); - } + if (GetSpannedBlocks()) { + const wxSheetSelection *spannedBlocks = GetSpannedBlocks(); + size_t n, count = spannedBlocks->GetCount(); + for (n = 0; n < count; n++) { + const wxSheetBlock &b = spannedBlocks->GetBlock(n); + if (block_.Intersects(b)) { // use original block so it doesn't keep growing + block = block.Union(b); + } } - else // brute force expansion - { - wxSheetCoords c; - int row_bottom = block_.GetBottom(); - int col_right = block_.GetRight(); - for (c.m_row = block_.GetTop(); c.m_row <= row_bottom; c.m_row++) - { - for (c.m_col = block_.GetLeft(); c.m_col <= col_right; c.m_col++) - { - block = block.Union(GetCellBlock(c)); - } - } + } + else // brute force expansion + { + wxSheetCoords c; + int row_bottom = block_.GetBottom(); + int col_right = block_.GetRight(); + for (c.m_row = block_.GetTop(); c.m_row <= row_bottom; c.m_row++) { + for (c.m_col = block_.GetLeft(); c.m_col <= col_right; c.m_col++) { + block = block.Union(GetCellBlock(c)); + } } + } - return block; + return block; } -wxRect wxSheet::BlockToLogicalRect( const wxSheetBlock& block_, bool expand_spanned ) const +wxRect wxSheet::BlockToLogicalRect(const wxSheetBlock &block_, bool expand_spanned) const { - wxSheetBlock block(expand_spanned ? ExpandSpannedBlock(block_) : block_); + wxSheetBlock block(expand_spanned ? ExpandSpannedBlock(block_) : block_); - wxRect rect(GetColLeft(block.GetLeft()), GetRowTop(block.GetTop()), 0, 0); - rect.width = GetColRight(block.GetRight()) - rect.x + 1; - rect.height = GetRowBottom(block.GetBottom()) - rect.y + 1; - return rect; + wxRect rect(GetColLeft(block.GetLeft()), GetRowTop(block.GetTop()), 0, 0); + rect.width = GetColRight(block.GetRight()) - rect.x + 1; + rect.height = GetRowBottom(block.GetBottom()) - rect.y + 1; + return rect; } -wxRect wxSheet::BlockToDeviceRect( const wxSheetBlock &block_, bool expand_spanned) const +wxRect wxSheet::BlockToDeviceRect(const wxSheetBlock &block_, bool expand_spanned) const { - // merely convert to scrolled coords - return CalcScrolledRect(BlockToLogicalRect(block_, expand_spanned)); + // merely convert to scrolled coords + return CalcScrolledRect(BlockToLogicalRect(block_, expand_spanned)); } wxSheetBlock wxSheet::LogicalGridRectToBlock(const wxRect &rect, bool wholeCell) const { - const int numRows = GetNumberRows(); - const int numCols = GetNumberCols(); - if (!numRows || !numCols) return wxNullSheetBlock; + const int numRows = GetNumberRows(); + const int numCols = GetNumberCols(); + if (!numRows || !numCols) { + return wxNullSheetBlock; + } - int leftCol = XToGridCol(rect.GetLeft(), true); - int topRow = YToGridRow(rect.GetTop(), true); - int rightCol = XToGridCol(rect.GetRight(), true); - int bottomRow = YToGridRow(rect.GetBottom(), true); + int leftCol = XToGridCol(rect.GetLeft(), true); + int topRow = YToGridRow(rect.GetTop(), true); + int rightCol = XToGridCol(rect.GetRight(), true); + int bottomRow = YToGridRow(rect.GetBottom(), true); - if (wholeCell) - { - if (GetColLeft(leftCol) < rect.GetLeft()) - leftCol++; - if (GetColRight(rightCol) > rect.GetRight()) - rightCol--; - if (GetRowTop(topRow) < rect.GetTop()) - topRow++; - if (GetRowBottom(bottomRow) > rect.GetBottom()) - bottomRow--; + if (wholeCell) { + if (GetColLeft(leftCol) < rect.GetLeft()) { + leftCol++; + } + if (GetColRight(rightCol) > rect.GetRight()) { + rightCol--; + } + if (GetRowTop(topRow) < rect.GetTop()) { + topRow++; } + if (GetRowBottom(bottomRow) > rect.GetBottom()) { + bottomRow--; + } + } - wxSheetBlock block(topRow, leftCol, bottomRow-topRow+1, rightCol-leftCol+1); - return block.Intersect(wxSheetBlock(0, 0, numRows, numCols)); + wxSheetBlock block(topRow, leftCol, bottomRow - topRow + 1, rightCol - leftCol + 1); + return block.Intersect(wxSheetBlock(0, 0, numRows, numCols)); } wxSheetBlock wxSheet::GetVisibleGridCellsBlock(bool wholeCellVisible) const { - wxRect rect(CalcUnscrolledRect(wxRect(wxPoint(0,0), m_gridWin->GetClientSize()))); - return LogicalGridRectToBlock(rect, wholeCellVisible); + wxRect rect(CalcUnscrolledRect(wxRect(wxPoint(0, 0), m_gridWin->GetClientSize()))); + return LogicalGridRectToBlock(rect, wholeCellVisible); } -wxPoint wxSheet::AlignInRect( int align, const wxRect& rect, const wxSize& size, bool inside ) const +wxPoint wxSheet::AlignInRect(int align, const wxRect &rect, const wxSize &size, bool inside) const { - wxPoint origin(rect.x, rect.y); + wxPoint origin(rect.x, rect.y); - // if it won't fit horizontally, then it must be aligned left - if (inside && (size.x > rect.width)) - { - align &= ~wxALIGN_RIGHT; - align &= ~wxALIGN_CENTRE_HORIZONTAL; - } - // if it won't fit vertically, then it must be aligned to the top - if (inside && (size.y > rect.height)) - { - align &= ~wxALIGN_BOTTOM; - align &= ~wxALIGN_CENTRE_VERTICAL; - } + // if it won't fit horizontally, then it must be aligned left + if (inside && (size.x > rect.width)) { + align &= ~wxALIGN_RIGHT; + align &= ~wxALIGN_CENTRE_HORIZONTAL; + } + // if it won't fit vertically, then it must be aligned to the top + if (inside && (size.y > rect.height)) { + align &= ~wxALIGN_BOTTOM; + align &= ~wxALIGN_CENTRE_VERTICAL; + } - if ((align & wxALIGN_RIGHT) != 0) - origin.x += rect.width - size.x - 1; - else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) - origin.x += (rect.width - size.x)/2; - //else // wxALIGN_LEFT + if ((align & wxALIGN_RIGHT) != 0) { + origin.x += rect.width - size.x - 1; + } + else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) { + origin.x += (rect.width - size.x) / 2; + } + // else // wxALIGN_LEFT - if ((align & wxALIGN_BOTTOM) != 0) - origin.y += rect.height - size.y - 1; - else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) - origin.y += (rect.height - size.y)/2; - //else // wxALIGN_TOP + if ((align & wxALIGN_BOTTOM) != 0) { + origin.y += rect.height - size.y - 1; + } + else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) { + origin.y += (rect.height - size.y) / 2; + } + // else // wxALIGN_TOP - return origin; + return origin; } // ---------------------------------------------------------------------------- @@ -4727,1950 +4830,1897 @@ wxPoint wxSheet::AlignInRect( int align, const wxRect& rect, const wxSize& size, wxSize wxSheet::GetGridVirtualSize(bool add_margin) const { - wxSize size; - const int numRows = GetNumberRows(); - const int numCols = GetNumberCols(); - if ((numCols > 0) && (numRows > 0)) - { - size.x = GetColRight(numCols - 1); - size.y = GetRowBottom(numRows - 1); - } + wxSize size; + const int numRows = GetNumberRows(); + const int numCols = GetNumberCols(); + if ((numCols > 0) && (numRows > 0)) { + size.x = GetColRight(numCols - 1); + size.y = GetRowBottom(numRows - 1); + } - if (add_margin) - { - size.x += GetSheetRefData()->m_marginSize.x; - size.y += GetSheetRefData()->m_marginSize.y; - } + if (add_margin) { + size.x += GetSheetRefData()->m_marginSize.x; + size.y += GetSheetRefData()->m_marginSize.y; + } - return size; + return size; } wxSize wxSheet::GetGridExtent() const { - wxSize s(GetGridVirtualSize(true)); - if (GetGridWindow()) - { - wxSize winSize(GetGridWindow()->GetSize()); - if (winSize.x > s.x) s.x = winSize.x; - if (winSize.y > s.y) s.y = winSize.y; + wxSize s(GetGridVirtualSize(true)); + if (GetGridWindow()) { + wxSize winSize(GetGridWindow()->GetSize()); + if (winSize.x > s.x) { + s.x = winSize.x; } - return s; + if (winSize.y > s.y) { + s.y = winSize.y; + } + } + return s; } -void wxSheet::SetGridOrigin( int x, int y, bool adjustScrollBars, bool sendEvt ) +void wxSheet::SetGridOrigin(int x, int y, bool adjustScrollBars, bool sendEvt) { - if (!m_gridWin) - return; - - // normally -1 for don't change - if (x == -1) x = m_gridOrigin.x; - if (y == -1) y = m_gridOrigin.y; - - // during OnSize gridWin isn't resized yet - int cw, ch; - GetClientSize( &cw, &ch ); - cw -= GetRowLabelWidth(); - ch -= GetColLabelHeight(); - if ( m_vertScrollBar->IsShown() ) - cw -= m_vertScrollBar->GetSize().x; - if ( m_horizScrollBar->IsShown() ) - ch -= m_horizScrollBar->GetSize().y; - - // Force fitting, don't allow scrolling out of bounds - wxSize virtSize(GetGridVirtualSize()); - if ((x < 0) || (virtSize.x < cw)) - x = 0; - else if (x > virtSize.x-cw) - x = virtSize.x - cw; - if ((y < 0) || (virtSize.y < ch)) - y = 0; - else if (y > virtSize.y-ch) - y = virtSize.y - ch; - - int dx = m_gridOrigin.x - x; - int dy = m_gridOrigin.y - y; - - if ((dx == 0) && (dy == 0)) - return; + if (!m_gridWin) { + return; + } + + // normally -1 for don't change + if (x == -1) { + x = m_gridOrigin.x; + } + if (y == -1) { + y = m_gridOrigin.y; + } + + // during OnSize gridWin isn't resized yet + int cw, ch; + GetClientSize(&cw, &ch); + cw -= GetRowLabelWidth(); + ch -= GetColLabelHeight(); + if (m_vertScrollBar->IsShown()) { + cw -= m_vertScrollBar->GetSize().x; + } + if (m_horizScrollBar->IsShown()) { + ch -= m_horizScrollBar->GetSize().y; + } + + // Force fitting, don't allow scrolling out of bounds + wxSize virtSize(GetGridVirtualSize()); + if ((x < 0) || (virtSize.x < cw)) { + x = 0; + } + else if (x > virtSize.x - cw) { + x = virtSize.x - cw; + } + if ((y < 0) || (virtSize.y < ch)) { + y = 0; + } + else if (y > virtSize.y - ch) { + y = virtSize.y - ch; + } + + int dx = m_gridOrigin.x - x; + int dy = m_gridOrigin.y - y; + + if ((dx == 0) && (dy == 0)) { + return; + } - m_gridOrigin.x = x; - m_gridOrigin.y = y; + m_gridOrigin.x = x; + m_gridOrigin.y = y; -/* - wxRect rect( (dx >= 0) ? 0 : cw+dx, - (dy >= 0) ? 0 : ch+dy, - dy != 0 ? cw : abs(dx), - dx != 0 ? ch : abs(dy) ); -*/ + /* + wxRect rect( (dx >= 0) ? 0 : cw+dx, + (dy >= 0) ? 0 : ch+dy, + dy != 0 ? cw : abs(dx), + dx != 0 ? ch : abs(dy) ); + */ - if (adjustScrollBars) - AdjustScrollbars(); + if (adjustScrollBars) { + AdjustScrollbars(); + } - // FIXME - or at least check, GTK calcs rect for you, does MSW? - m_gridWin->ScrollWindow( dx, dy ); //, &rect ); - if (dx != 0) - m_colLabelWin->ScrollWindow( dx, 0 ); //, &rect ); - if (dy != 0) - m_rowLabelWin->ScrollWindow( 0, dy ); //, &rect ); + // FIXME - or at least check, GTK calcs rect for you, does MSW? + m_gridWin->ScrollWindow(dx, dy); //, &rect ); + if (dx != 0) { + m_colLabelWin->ScrollWindow(dx, 0); //, &rect ); + } + if (dy != 0) { + m_rowLabelWin->ScrollWindow(0, dy); //, &rect ); + } - // Let the windows refresh before next scroll event, otherwise windows - // don't line up - //wxYieldIfNeeded(); + // Let the windows refresh before next scroll event, otherwise windows + // don't line up + // wxYieldIfNeeded(); - if (sendEvt) - SendEvent(wxEVT_SHEET_VIEW_CHANGED, GetGridCursorCell()); + if (sendEvt) { + SendEvent(wxEVT_SHEET_VIEW_CHANGED, GetGridCursorCell()); + } } -void wxSheet::OnScroll( wxScrollEvent &event ) +void wxSheet::OnScroll(wxScrollEvent &event) { - if (!m_gridWin) - return; + if (!m_gridWin) { + return; + } - event.Skip(); + event.Skip(); - int pos = event.GetPosition(); - //wxPrintf(wxT("Pos %d %d Length %d Left %d Right %d\n"), pos, m_horizScrollBar->GetThumbPosition(), m_horizScrollBar->GetThumbSize(), pos*m_horizScrollBar->GetThumbSize(), pos*m_horizScrollBar->GetThumbSize()+GetGridWindow()->GetClientSize().x); + int pos = event.GetPosition(); + // wxPrintf(wxT("Pos %d %d Length %d Left %d Right %d\n"), pos, + // m_horizScrollBar->GetThumbPosition(), m_horizScrollBar->GetThumbSize(), + // pos*m_horizScrollBar->GetThumbSize(), + // pos*m_horizScrollBar->GetThumbSize()+GetGridWindow()->GetClientSize().x); - if (event.GetId() == ID_HORIZ_SCROLLBAR) - SetGridOrigin( pos*15, -1, false, true ); - //SetGridOrigin( pos*m_horizScrollBar->GetThumbSize(), -1, false, true ); - else if (event.GetId() == ID_VERT_SCROLLBAR) - SetGridOrigin( -1, pos*15, false, true ); - //SetGridOrigin( -1, pos*m_vertScrollBar->GetThumbSize(), false, true ); + if (event.GetId() == ID_HORIZ_SCROLLBAR) { + SetGridOrigin(pos * 15, -1, false, true); + } + // SetGridOrigin( pos*m_horizScrollBar->GetThumbSize(), -1, false, true ); + else if (event.GetId() == ID_VERT_SCROLLBAR) { + SetGridOrigin(-1, pos * 15, false, true); + } + // SetGridOrigin( -1, pos*m_vertScrollBar->GetThumbSize(), false, true ); } void wxSheet::AdjustScrollbars(bool calc_win_sizes) { - if (!m_gridWin || m_resizing) - return; + if (!m_gridWin || m_resizing) { + return; + } + + m_resizing = true; + + bool horizSbShown = m_horizScrollBar->IsShown(); + bool vertSbShown = m_vertScrollBar->IsShown(); + int sb_width = m_vertScrollBar->GetSize().x; + int sb_height = m_horizScrollBar->GetSize().y; + + int cw, ch; + GetClientSize(&cw, &ch); + + // Grid window width and height, may be in OnSize so not sized yet + int gw = cw - GetRowLabelWidth(); + int gh = ch - GetColLabelHeight(); + + // grid total size + wxSize virtSize(GetGridVirtualSize()); + /* + // take into account editor if shown // FIXME what is this? + if ( 0 && IsCellEditControlShown() ) + { + int w2, h2; + int r = GetGridCursorRow(); + int c = GetGridCursorCol(); + int x = GetColLeft(c); + int y = GetRowTop(r); + + // how big is the editor + GetEditControl().GetControl()->GetSize(&w2, &h2); + w2 += x; + h2 += y; + if( w2 > virtSize.x ) virtSize.x = w2; + if( h2 > virtSize.y ) virtSize.y = h2; + } + */ + // Figure out if we need the scrollbars at all + bool need_Xscroll = (m_scrollBarMode & SB_HORIZ_NEVER) != 0 + ? false + : (((m_scrollBarMode & SB_HORIZ_ALWAYS) != 0) ? true : virtSize.x > gw); + bool need_Yscroll = (m_scrollBarMode & SB_VERT_NEVER) != 0 + ? false + : (((m_scrollBarMode & SB_VERT_ALWAYS) != 0) ? true : virtSize.y > gh); + + // Now cut down size due to the scrollbars if shown + if (need_Xscroll) { + gh -= sb_height; + } + if (need_Yscroll) { + gw -= sb_width; + } + + // Maybe now that it's smaller we need the other scrollbar + need_Xscroll = (m_scrollBarMode & SB_HORIZ_NEVER) != 0 + ? false + : (((m_scrollBarMode & SB_HORIZ_ALWAYS) != 0) ? true : virtSize.x > gw); + need_Yscroll = (m_scrollBarMode & SB_VERT_NEVER) != 0 + ? false + : (((m_scrollBarMode & SB_VERT_ALWAYS) != 0) ? true : virtSize.y > gh); + + // if (need_Xscroll) ch -= sb_height; + // if (need_Yscroll) cw -= sb_width; + // bool horiz_splitter = need_Xscroll && m_enable_split_horiz; + // bool vert_splitter = need_Yscroll && m_enable_split_vert; + + // width and height of the horiz and vert scrollbars + // int sw = cw - (vert_splitter ? SPLIT_BUTTON_WIDTH : 0); + // int sh = ch - (horiz_splitter ? SPLIT_BUTTON_WIDTH : 0); + + // set scrollbar parameters + int thumbX = SHEET_SCROLL_LINE_X; + int thumbY = SHEET_SCROLL_LINE_Y; + + // virtSize.x += sw - gw; + // virtSize.y += sh - gh; + + // FIXME this is wrong for GTK and MSW, but why? + int rangeX = !need_Xscroll ? 0 : 1 + (virtSize.x - gw + thumbX - 1) / thumbX; + int rangeY = !need_Yscroll ? 0 : 1 + (virtSize.y - gh + thumbY - 1) / thumbY; + + int pageX = int((gw * 0.9) / thumbX); + int pageY = int((gh * 0.9) / thumbY); + + int posX = m_gridOrigin.x / thumbX; + int posY = m_gridOrigin.y / thumbY; + + thumbX = 1; + thumbY = 1; + + // wxPrintf(wxT("Pos %d %d, virtSize %d %d, range %d %d, thumb %d %d page %d %d, win %d %d \n"), + // posX, posY, virtSize.x, virtSize.y, rangeX, rangeY, thumbX, thumbY, pageX, pageY, gw, gh); + + if (need_Xscroll) { + m_horizScrollBar->SetScrollbar(posX, thumbX, rangeX, pageX); + } + if (need_Yscroll) { + m_vertScrollBar->SetScrollbar(posY, thumbY, rangeY, pageY); + } + + // wxPrintf(wxT("Set pos %d range %d, thumb %d, page %d\n"), + // m_horizScrollBar->GetThumbPosition(), m_horizScrollBar->GetRange(), + // m_horizScrollBar->GetThumbSize(), m_horizScrollBar->GetPageSize()); + + // recalculate the windows sizes and positions if we added/removed scrollbar + bool calcSizes = false; + + if (need_Xscroll != horizSbShown) { + calcSizes = true; + m_horizScrollBar->Show(need_Xscroll); + } + if (need_Yscroll != vertSbShown) { + calcSizes = true; + m_vertScrollBar->Show(need_Yscroll); + } + + m_resizing = false; + + if (calcSizes && calc_win_sizes) { + CalcWindowSizes(false); + } +} + +void wxSheet::PrepareGridDC(wxDC &dc) { dc.SetDeviceOrigin(-m_gridOrigin.x, -m_gridOrigin.y); } + +void wxSheet::PrepareRowLabelDC(wxDC &dc) { dc.SetDeviceOrigin(0, -m_gridOrigin.y); } + +void wxSheet::PrepareColLabelDC(wxDC &dc) { dc.SetDeviceOrigin(-m_gridOrigin.x, 0); } - m_resizing = true; +// ---------------------------------------------------------------------------- - bool horizSbShown = m_horizScrollBar->IsShown(); - bool vertSbShown = m_vertScrollBar->IsShown(); - int sb_width = m_vertScrollBar->GetSize().x; - int sb_height = m_horizScrollBar->GetSize().y; - - int cw, ch; - GetClientSize( &cw, &ch ); - - // Grid window width and height, may be in OnSize so not sized yet - int gw = cw - GetRowLabelWidth(); - int gh = ch - GetColLabelHeight(); - - // grid total size - wxSize virtSize(GetGridVirtualSize()); -/* - // take into account editor if shown // FIXME what is this? - if ( 0 && IsCellEditControlShown() ) - { - int w2, h2; - int r = GetGridCursorRow(); - int c = GetGridCursorCol(); - int x = GetColLeft(c); - int y = GetRowTop(r); - - // how big is the editor - GetEditControl().GetControl()->GetSize(&w2, &h2); - w2 += x; - h2 += y; - if( w2 > virtSize.x ) virtSize.x = w2; - if( h2 > virtSize.y ) virtSize.y = h2; - } -*/ - // Figure out if we need the scrollbars at all - bool need_Xscroll = (m_scrollBarMode & SB_HORIZ_NEVER) != 0 ? false : - (((m_scrollBarMode & SB_HORIZ_ALWAYS) != 0) ? true : virtSize.x > gw); - bool need_Yscroll = (m_scrollBarMode & SB_VERT_NEVER ) != 0 ? false : - (((m_scrollBarMode & SB_VERT_ALWAYS ) != 0) ? true : virtSize.y > gh); - - // Now cut down size due to the scrollbars if shown - if (need_Xscroll) gh -= sb_height; - if (need_Yscroll) gw -= sb_width; - - // Maybe now that it's smaller we need the other scrollbar - need_Xscroll = (m_scrollBarMode & SB_HORIZ_NEVER) != 0 ? false : - (((m_scrollBarMode & SB_HORIZ_ALWAYS) != 0) ? true : virtSize.x > gw); - need_Yscroll = (m_scrollBarMode & SB_VERT_NEVER ) != 0 ? false : - (((m_scrollBarMode & SB_VERT_ALWAYS ) != 0) ? true : virtSize.y > gh); - - //if (need_Xscroll) ch -= sb_height; - //if (need_Yscroll) cw -= sb_width; - //bool horiz_splitter = need_Xscroll && m_enable_split_horiz; - //bool vert_splitter = need_Yscroll && m_enable_split_vert; - - // width and height of the horiz and vert scrollbars - //int sw = cw - (vert_splitter ? SPLIT_BUTTON_WIDTH : 0); - //int sh = ch - (horiz_splitter ? SPLIT_BUTTON_WIDTH : 0); - - // set scrollbar parameters - int thumbX = SHEET_SCROLL_LINE_X; - int thumbY = SHEET_SCROLL_LINE_Y; - - //virtSize.x += sw - gw; - //virtSize.y += sh - gh; - - // FIXME this is wrong for GTK and MSW, but why? - int rangeX = !need_Xscroll ? 0 : 1 + (virtSize.x - gw + thumbX - 1)/thumbX; - int rangeY = !need_Yscroll ? 0 : 1 + (virtSize.y - gh + thumbY - 1)/thumbY; - - int pageX = int((gw * 0.9) / thumbX); - int pageY = int((gh * 0.9) / thumbY); - - int posX = m_gridOrigin.x/thumbX; - int posY = m_gridOrigin.y/thumbY; - - thumbX = 1; - thumbY = 1; - - //wxPrintf(wxT("Pos %d %d, virtSize %d %d, range %d %d, thumb %d %d page %d %d, win %d %d \n"), - // posX, posY, virtSize.x, virtSize.y, rangeX, rangeY, thumbX, thumbY, pageX, pageY, gw, gh); - - if (need_Xscroll) - m_horizScrollBar->SetScrollbar(posX, thumbX, rangeX, pageX); - if (need_Yscroll) - m_vertScrollBar->SetScrollbar(posY, thumbY, rangeY, pageY); - - //wxPrintf(wxT("Set pos %d range %d, thumb %d, page %d\n"), - // m_horizScrollBar->GetThumbPosition(), m_horizScrollBar->GetRange(), m_horizScrollBar->GetThumbSize(), m_horizScrollBar->GetPageSize()); - - // recalculate the windows sizes and positions if we added/removed scrollbar - bool calcSizes = false; - - if (need_Xscroll != horizSbShown) - { - calcSizes = true; - m_horizScrollBar->Show(need_Xscroll); - } - if (need_Yscroll != vertSbShown) - { - calcSizes = true; - m_vertScrollBar->Show(need_Yscroll); - } - - m_resizing = false; - - if (calcSizes && calc_win_sizes) - CalcWindowSizes(false); -} - -void wxSheet::PrepareGridDC( wxDC& dc ) -{ - dc.SetDeviceOrigin( -m_gridOrigin.x, -m_gridOrigin.y ); -} - -void wxSheet::PrepareRowLabelDC( wxDC& dc ) -{ - dc.SetDeviceOrigin( 0, -m_gridOrigin.y ); -} - -void wxSheet::PrepareColLabelDC( wxDC& dc ) -{ - dc.SetDeviceOrigin( -m_gridOrigin.x, 0 ); -} - -// ---------------------------------------------------------------------------- - -// Checks and returns a suitable horiz or vert alignment, if invalid replaces -// with wxSheetCellAttr::NoHorizAlign/NoVertAlign -static int CheckAlignment(int align) -{ - // note: it's a shame that wxALIGN_LEFT = wxALIGN_TOP = 0 - - int count = 0; - if ((align & wxSHEET_AttrAlignRight) != 0) count++; - if ((align & wxSHEET_AttrAlignCenterHoriz) != 0) count++; - if ((align & wxSHEET_AttrAlignHorizUnset) != 0) count++; - if (count > 1) - { - align &= ~wxSHEET_AttrAlignHoriz_Mask; // clear whatever is there - align |= wxSHEET_AttrAlignHorizUnset; // set to no alignment - } - - count = 0; - if ((align & wxSHEET_AttrAlignBottom) != 0) count++; - if ((align & wxSHEET_AttrAlignCenterVert) != 0) count++; - if ((align & wxSHEET_AttrAlignVertUnset) != 0) count++; - if (count > 1) - { - align &= ~wxSHEET_AttrAlignVert_Mask; // clear whatever is there - align |= wxSHEET_AttrAlignVertUnset; // set to no alignment - } - - return align; -} +// Checks and returns a suitable horiz or vert alignment, if invalid replaces +// with wxSheetCellAttr::NoHorizAlign/NoVertAlign +static int CheckAlignment(int align) +{ + // note: it's a shame that wxALIGN_LEFT = wxALIGN_TOP = 0 + + int count = 0; + if ((align & wxSHEET_AttrAlignRight) != 0) { + count++; + } + if ((align & wxSHEET_AttrAlignCenterHoriz) != 0) { + count++; + } + if ((align & wxSHEET_AttrAlignHorizUnset) != 0) { + count++; + } + if (count > 1) { + align &= ~wxSHEET_AttrAlignHoriz_Mask; // clear whatever is there + align |= wxSHEET_AttrAlignHorizUnset; // set to no alignment + } + + count = 0; + if ((align & wxSHEET_AttrAlignBottom) != 0) { + count++; + } + if ((align & wxSHEET_AttrAlignCenterVert) != 0) { + count++; + } + if ((align & wxSHEET_AttrAlignVertUnset) != 0) { + count++; + } + if (count > 1) { + align &= ~wxSHEET_AttrAlignVert_Mask; // clear whatever is there + align |= wxSHEET_AttrAlignVertUnset; // set to no alignment + } + + return align; +} int wxSheet::SetAlignment(int orig_align, int hAlign, int vAlign) { - if (hAlign != -1) - { - orig_align &= ~wxSHEET_AttrAlignHoriz_Mask; // clear old - orig_align |= (hAlign & wxSHEET_AttrAlignHoriz_Mask); // set new - } - if (vAlign != -1) - { - orig_align &= ~wxSHEET_AttrAlignVert_Mask; - orig_align |= (vAlign & wxSHEET_AttrAlignVert_Mask); - } + if (hAlign != -1) { + orig_align &= ~wxSHEET_AttrAlignHoriz_Mask; // clear old + orig_align |= (hAlign & wxSHEET_AttrAlignHoriz_Mask); // set new + } + if (vAlign != -1) { + orig_align &= ~wxSHEET_AttrAlignVert_Mask; + orig_align |= (vAlign & wxSHEET_AttrAlignVert_Mask); + } - return CheckAlignment(orig_align); + return CheckAlignment(orig_align); } // ---------------------------------------------------------------------------- bool wxSheet::HasFocus() const { - wxWindow *win = FindFocus(); - return win && ((win==(wxSheet*)this) || (win==m_gridWin) || (win==m_rowLabelWin) || - (win == m_colLabelWin) || (win == m_cornerLabelWin)); + wxWindow *win = FindFocus(); + return win && ((win == (wxSheet *)this) || (win == m_gridWin) || (win == m_rowLabelWin) || + (win == m_colLabelWin) || (win == m_cornerLabelWin)); } // ---------------------------------------------------------------------------- // Event handlers -void wxSheet::OnMouse( wxMouseEvent& event ) -{ - wxWindow *win = (wxWindow*)event.GetEventObject(); - - if (win == this) - ProcessSheetMouseEvent(event); - else if (win == m_rowLabelWin) - ProcessRowLabelMouseEvent(event); - else if (win == m_colLabelWin) - ProcessColLabelMouseEvent(event); - else if (win == m_cornerLabelWin) - ProcessCornerLabelMouseEvent(event); - else if (win == m_gridWin) - ProcessGridCellMouseEvent(event); - else - event.Skip(); +void wxSheet::OnMouse(wxMouseEvent &event) +{ + wxWindow *win = (wxWindow *)event.GetEventObject(); + + if (win == this) { + ProcessSheetMouseEvent(event); + } + else if (win == m_rowLabelWin) { + ProcessRowLabelMouseEvent(event); + } + else if (win == m_colLabelWin) { + ProcessColLabelMouseEvent(event); + } + else if (win == m_cornerLabelWin) { + ProcessCornerLabelMouseEvent(event); + } + else if (win == m_gridWin) { + ProcessGridCellMouseEvent(event); + } + else { + event.Skip(); + } } -void wxSheet::OnMouseWheel( wxMouseEvent& event ) +void wxSheet::OnMouseWheel(wxMouseEvent &event) { - wxWindow *win = (wxWindow*)event.GetEventObject(); + wxWindow *win = (wxWindow *)event.GetEventObject(); - // Scroll up and down by a 1/3 of the height of the window - if ((win == m_rowLabelWin) || (win == m_gridWin)) - { - // GTK doesn't have good wheel events - if (GetNumberRows() > 0) - { - wxPoint origin(GetGridOrigin()); - wxSize size(GetGridWindow()->GetClientSize()); - int dy = event.GetWheelRotation() < 0 ? 1 : -1; - SetGridOrigin( origin.x, origin.y + dy * size.y/3, true, true ); - } + // Scroll up and down by a 1/3 of the height of the window + if ((win == m_rowLabelWin) || (win == m_gridWin)) { + // GTK doesn't have good wheel events + if (GetNumberRows() > 0) { + wxPoint origin(GetGridOrigin()); + wxSize size(GetGridWindow()->GetClientSize()); + int dy = event.GetWheelRotation() < 0 ? 1 : -1; + SetGridOrigin(origin.x, origin.y + dy * size.y / 3, true, true); } - // Scroll sideways by a 1/3 of the width of the window - else if (win == m_colLabelWin) - { - if (GetNumberCols() > 0) - { - wxPoint origin(GetGridOrigin()); - wxSize size(GetGridWindow()->GetClientSize()); - int dx = event.GetWheelRotation() < 0 ? 1 : -1; - SetGridOrigin( origin.x + dx * size.x/3, origin.y, true, true ); - } + } + // Scroll sideways by a 1/3 of the width of the window + else if (win == m_colLabelWin) { + if (GetNumberCols() > 0) { + wxPoint origin(GetGridOrigin()); + wxSize size(GetGridWindow()->GetClientSize()); + int dx = event.GetWheelRotation() < 0 ? 1 : -1; + SetGridOrigin(origin.x + dx * size.x / 3, origin.y, true, true); } + } - event.Skip(); + event.Skip(); } -void wxSheet::ProcessSheetMouseEvent( wxMouseEvent& event ) +void wxSheet::ProcessSheetMouseEvent(wxMouseEvent &event) { - if (!m_enable_split_vert && !m_enable_split_horiz) - return; + if (!m_enable_split_vert && !m_enable_split_horiz) { + return; + } - wxPoint mousePos = event.GetPosition(); + wxPoint mousePos = event.GetPosition(); - if (event.LeftDown()) - { -#if wxCHECK_VERSION(2,7,0) - if (m_vertSplitRect.Contains(mousePos) || m_horizSplitRect.Contains(mousePos)) + if (event.LeftDown()) { +#if wxCHECK_VERSION(2, 7, 0) + if (m_vertSplitRect.Contains(mousePos) || m_horizSplitRect.Contains(mousePos)) #else - if (m_vertSplitRect.Inside(mousePos) || m_horizSplitRect.Inside(mousePos)) + if (m_vertSplitRect.Inside(mousePos) || m_horizSplitRect.Inside(mousePos)) #endif - SetCaptureWindow(this); + SetCaptureWindow(this); + } + else if (event.LeftUp()) { + SetCaptureWindow(NULL); + } + else if (event.Dragging() && HasCapture() && HasMouseCursorMode(WXSHEET_CURSOR_SPLITTING)) { + wxSheetSplitterEvent splitEvent(GetId(), wxEVT_SHEET_SPLIT_BEGIN); + splitEvent.SetEventObject(this); + splitEvent.m_vert_split = HasMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL); + + SetCaptureWindow(NULL); + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); + GetEventHandler()->ProcessEvent(splitEvent); + } + else if ((event.Leaving() || event.Entering()) && !HasCapture()) { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); + } + else if (event.Moving() && !HasCapture()) { +#if wxCHECK_VERSION(2, 7, 0) + if (m_vertSplitRect.Contains(mousePos)) { + SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL, this); + } + else if (m_horizSplitRect.Contains(mousePos)) { + SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_HORIZONTAL, this); + } + else { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); } - else if (event.LeftUp()) - { - SetCaptureWindow(NULL); +#else + if (m_vertSplitRect.Inside(mousePos)) { + SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL, this); } - else if (event.Dragging() && HasCapture() && HasMouseCursorMode(WXSHEET_CURSOR_SPLITTING)) - { - wxSheetSplitterEvent splitEvent(GetId(), wxEVT_SHEET_SPLIT_BEGIN); - splitEvent.SetEventObject(this); - splitEvent.m_vert_split = HasMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL); - - SetCaptureWindow(NULL); - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); - GetEventHandler()->ProcessEvent(splitEvent); + else if (m_horizSplitRect.Inside(mousePos)) { + SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_HORIZONTAL, this); } - else if ((event.Leaving() || event.Entering()) && !HasCapture()) - { - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); + else { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); } - else if (event.Moving() && !HasCapture()) - { -#if wxCHECK_VERSION(2,7,0) - if (m_vertSplitRect.Contains(mousePos)) - SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL, this); - else if (m_horizSplitRect.Contains(mousePos)) - SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_HORIZONTAL, this); - else - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); -#else - if (m_vertSplitRect.Inside(mousePos)) - SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_VERTICAL, this); - else if (m_horizSplitRect.Inside(mousePos)) - SetMouseCursorMode(WXSHEET_CURSOR_SPLIT_HORIZONTAL, this); - else - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, this); #endif - } + } } -void wxSheet::ProcessRowLabelMouseEvent( wxMouseEvent& event ) +void wxSheet::ProcessRowLabelMouseEvent(wxMouseEvent &event) { - int x, y; - m_mousePos = event.GetPosition(); - CalcUnscrolledPosition( m_mousePos.x, m_mousePos.y, &x, &y ); - wxSheetCoords coords(YToGridRow(y), -1); - - if ( event.Entering() || event.Leaving() ) - { - if (!event.Dragging() && !m_isDragging) - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); + int x, y; + m_mousePos = event.GetPosition(); + CalcUnscrolledPosition(m_mousePos.x, m_mousePos.y, &x, &y); + wxSheetCoords coords(YToGridRow(y), -1); - return; + if (event.Entering() || event.Leaving()) { + if (!event.Dragging() && !m_isDragging) { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); } - if ( event.Dragging() && event.LeftIsDown() ) - { - if (!m_isDragging) - { - m_isDragging = true; - SetCaptureWindow(m_rowLabelWin); - } + return; + } - if ( event.LeftIsDown() ) - { - bool can_scroll = true; + if (event.Dragging() && event.LeftIsDown()) { + if (!m_isDragging) { + m_isDragging = true; + SetCaptureWindow(m_rowLabelWin); + } - switch ( GetMouseCursorMode() ) - { - case WXSHEET_CURSOR_RESIZE_ROW: - { - y = wxMax( y, GetRowTop(m_dragRowOrCol) + - GetMinimalRowHeight(m_dragRowOrCol)); - can_scroll = false; // y != m_dragLastPos; - DrawRowColResizingMarker( y ); - break; - } - case WXSHEET_CURSOR_SELECT_ROW: - { - if (HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectCols)) - break; + if (event.LeftIsDown()) { + bool can_scroll = true; - // check for clearing here since we didn't if editing allowed - bool add = event.ShiftDown() || event.ControlDown(); - if (HasSelection(false) && !add) - ClearSelection(true); + switch (GetMouseCursorMode()) { + case WXSHEET_CURSOR_RESIZE_ROW: { + y = wxMax(y, GetRowTop(m_dragRowOrCol) + GetMinimalRowHeight(m_dragRowOrCol)); + can_scroll = false; // y != m_dragLastPos; + DrawRowColResizingMarker(y); + break; + } + case WXSHEET_CURSOR_SELECT_ROW: { + if (HasSelectionMode(wxSHEET_SelectNone | wxSHEET_SelectCols)) { + break; + } - if (ContainsGridCell(GetSelectingAnchor()) && ContainsRowLabelCell(coords)) - { - HighlightSelectingBlock(GetSelectingAnchor(), - wxSheetCoords(coords.m_row, GetNumberCols()+1)); - } - break; - } - default: - break; - } + // check for clearing here since we didn't if editing allowed + bool add = event.ShiftDown() || event.ControlDown(); + if (HasSelection(false) && !add) { + ClearSelection(true); + } - if (can_scroll && - ((m_mousePos.y < 0) || (m_mousePos.y > m_rowLabelWin->GetClientSize().GetHeight()))) - { - if (!m_mouseTimer) - StartMouseTimer(); - } - else - StopMouseTimer(); + if (ContainsGridCell(GetSelectingAnchor()) && ContainsRowLabelCell(coords)) { + HighlightSelectingBlock(GetSelectingAnchor(), + wxSheetCoords(coords.m_row, GetNumberCols() + 1)); } - return; - } + break; + } + default: + break; + } + if (can_scroll && + ((m_mousePos.y < 0) || (m_mousePos.y > m_rowLabelWin->GetClientSize().GetHeight()))) { + if (!m_mouseTimer) { + StartMouseTimer(); + } + } + else { + StopMouseTimer(); + } + } + return; + } + + StopMouseTimer(); + SetCaptureWindow(NULL); + m_isDragging = false; + + if (event.LeftDown()) { + if (IsCellEditControlShown()) { + DisableCellEditControl(true); + } + + // don't send a label click event for a hit on the edge of the row label + // this is probably the user wanting to resize the row + if (YToEdgeOfGridRow(y) < 0) { + if (ContainsRowLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) && + !HasSelectionMode(wxSHEET_SelectNone | wxSHEET_SelectCols)) { + bool add = event.ShiftDown() || event.ControlDown(); + wxSheetBlock block; + + if (event.ShiftDown()) { + SetSelectingAnchor(wxSheetCoords(GetGridCursorRow(), 0)); + block = + wxSheetBlock(GetSelectingAnchor(), wxSheetCoords(coords.m_row, GetNumberCols() + 1)); + } + else { + SetSelectingAnchor(wxSheetCoords(coords.m_row, 0)); + block = wxSheetBlock(GetSelectingAnchor(), 1, GetNumberCols() + 1); + } + + // if you can edit the row label then don't select row until drag + bool can_edit = CanEnableCellControl(coords); + if (!add && HasSelection() && + (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, false, false, &event) != + EVT_VETOED)) { + ClearSelection(true); + } + + if (!can_edit) { + HighlightSelectingBlock(block); + } + + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_ROW, m_rowLabelWin); + } + } + else { + // starting to drag-resize a row + if (CanDragRowSize()) { + SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_rowLabelWin); + SetCaptureWindow(m_rowLabelWin); + } + } + } + else if (event.LeftDClick()) { + int row = YToEdgeOfGridRow(y); + if (row < 0) { + if (ContainsRowLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) { + if (CanEnableCellControl(coords)) { + m_waitForSlowClick = false; + ClearSelection(true); + EnableCellEditControl(coords); + if (IsCellEditControlCreated()) { + GetSheetRefData()->m_cellEditor.StartingClick(); + } + } + } + } + else { + // adjust row height depending on label text + if (CanDragRowSize()) { + AutoSizeRowLabelHeight(row); + } + + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); + m_dragLastPos = -1; + } + } + else if (event.LeftUp()) { StopMouseTimer(); SetCaptureWindow(NULL); - m_isDragging = false; - - if ( event.LeftDown() ) - { - if (IsCellEditControlShown()) - DisableCellEditControl(true); - - // don't send a label click event for a hit on the edge of the row label - // this is probably the user wanting to resize the row - if ( YToEdgeOfGridRow(y) < 0 ) - { - if ( ContainsRowLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) && - !HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectCols) ) - { - bool add = event.ShiftDown() || event.ControlDown(); - wxSheetBlock block; - - if ( event.ShiftDown() ) - { - SetSelectingAnchor(wxSheetCoords(GetGridCursorRow(), 0)); - block = wxSheetBlock(GetSelectingAnchor(), - wxSheetCoords(coords.m_row, GetNumberCols()+1)); - } - else - { - SetSelectingAnchor(wxSheetCoords(coords.m_row, 0)); - block = wxSheetBlock(GetSelectingAnchor(), 1, GetNumberCols()+1); - } - // if you can edit the row label then don't select row until drag - bool can_edit = CanEnableCellControl(coords); - if (!add && HasSelection() && - (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, false, false, &event) != EVT_VETOED)) - { - ClearSelection(true); - } - - if (!can_edit) - HighlightSelectingBlock(block); - - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_ROW, m_rowLabelWin); - } - } - else - { - // starting to drag-resize a row - if ( CanDragRowSize() ) - { - SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_rowLabelWin); - SetCaptureWindow(m_rowLabelWin); - } - } + if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW)) { + // Note: send event *after* doing default processing in this case + if (DoEndDragResizeRowCol()) { + SendEvent(wxEVT_SHEET_ROW_SIZE, wxSheetCoords(m_dragRowOrCol, -1), &event); + } } - else if ( event.LeftDClick() ) - { - int row = YToEdgeOfGridRow(y); - if ( row < 0 ) - { - if ( ContainsRowLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) - { - if (CanEnableCellControl(coords)) - { - m_waitForSlowClick = false; - ClearSelection(true); - EnableCellEditControl(coords); - if ( IsCellEditControlCreated() ) - GetSheetRefData()->m_cellEditor.StartingClick(); - } - } - } - else - { - // adjust row height depending on label text - if (CanDragRowSize()) - AutoSizeRowLabelHeight( row ); + else if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_ROW)) { + if (!GetSelectingBlock().IsEmpty()) { + bool add = event.ShiftDown() || event.ControlDown(); - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); - m_dragLastPos = -1; + if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, add, &event) != + EVT_VETOED) { + SelectRows(GetSelectingBlock().GetTop(), GetSelectingBlock().GetBottom(), add, true); + SetSelectingBlock(wxNullSheetBlock); } + } } - else if ( event.LeftUp() ) - { - StopMouseTimer(); - SetCaptureWindow(NULL); - - if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW) ) - { - // Note: send event *after* doing default processing in this case - if (DoEndDragResizeRowCol()) - SendEvent( wxEVT_SHEET_ROW_SIZE, wxSheetCoords(m_dragRowOrCol, -1), &event ); - } - else if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_ROW) ) - { - if (!GetSelectingBlock().IsEmpty()) - { - bool add = event.ShiftDown() || event.ControlDown(); - - if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - GetSelectingBlock(), true, add, &event) != EVT_VETOED) - { - SelectRows(GetSelectingBlock().GetTop(), GetSelectingBlock().GetBottom(), add, true); - SetSelectingBlock(wxNullSheetBlock); - } - } - } - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); - m_dragLastPos = -1; - if (!m_keySelecting) - SetSelectingAnchor(wxNullSheetCoords); + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); + m_dragLastPos = -1; + if (!m_keySelecting) { + SetSelectingAnchor(wxNullSheetCoords); + } - // send after default processing, they can use own evt handler - SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); + // send after default processing, they can use own evt handler + SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); + } + else if (event.RightDown()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightDown() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if ( ContainsRowLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED)) - { - // no default action at the moment - } + if (ContainsRowLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED)) { + // no default action at the moment + } + } + else if (event.RightDClick()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightDClick() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if ( ContainsRowLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED)) - { - // no default action at the moment - } + if (ContainsRowLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED)) { + // no default action at the moment + } + } + else if (event.RightUp()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightUp() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if ( ContainsRowLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED)) - { - // no default action at the moment - } + if (ContainsRowLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED)) { + // no default action at the moment } - else if ( event.Moving() ) - { - m_dragRowOrCol = YToEdgeOfGridRow( y ); - if ( m_dragRowOrCol >= 0 ) - { - if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - { - // don't capture the mouse yet - if ( CanDragRowSize() ) - { - SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_rowLabelWin); - } - } - } - else if ( !HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - { - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); + } + else if (event.Moving()) { + m_dragRowOrCol = YToEdgeOfGridRow(y); + if (m_dragRowOrCol >= 0) { + if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + // don't capture the mouse yet + if (CanDragRowSize()) { + SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_rowLabelWin); } + } + } + else if (!HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_rowLabelWin); } + } } -void wxSheet::ProcessColLabelMouseEvent( wxMouseEvent& event ) +void wxSheet::ProcessColLabelMouseEvent(wxMouseEvent &event) { - int x, y; - m_mousePos = event.GetPosition(); - CalcUnscrolledPosition( m_mousePos.x, m_mousePos.y, &x, &y ); - wxSheetCoords coords(-1, XToGridCol(x)); + int x, y; + m_mousePos = event.GetPosition(); + CalcUnscrolledPosition(m_mousePos.x, m_mousePos.y, &x, &y); + wxSheetCoords coords(-1, XToGridCol(x)); - if ( event.Entering() || event.Leaving() ) - { - if (!event.Dragging() && !m_isDragging) - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); - - return; + if (event.Entering() || event.Leaving()) { + if (!event.Dragging() && !m_isDragging) { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); } - if ( event.Dragging() && event.LeftIsDown() ) - { - if (!m_isDragging) - { - m_isDragging = true; - SetCaptureWindow(m_colLabelWin); - } - - if ( event.LeftIsDown() ) - { - bool can_scroll = true; - - switch( GetMouseCursorMode() ) - { - case WXSHEET_CURSOR_RESIZE_COL : - { - x = wxMax( x, GetColLeft(m_dragRowOrCol) + - GetMinimalColWidth(m_dragRowOrCol)); - can_scroll = false; // x != m_dragLastPos; - DrawRowColResizingMarker( x ); - break; - } - case WXSHEET_CURSOR_SELECT_COL : - { - if (HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectRows)) - break; - - // check for clearing here since we didn't if editing allowed - bool add = event.ShiftDown() || event.ControlDown(); - if (HasSelection(false) && !add) - ClearSelection(true); - - if (ContainsGridCell(GetSelectingAnchor()) && ContainsColLabelCell(coords)) - { - HighlightSelectingBlock(GetSelectingAnchor(), - wxSheetCoords(GetNumberRows()+1, coords.m_col)); - } - break; - } - default: - break; - } + return; + } - if (can_scroll && - ((m_mousePos.x < 0) || (m_mousePos.x > m_colLabelWin->GetClientSize().GetWidth()))) - { - if (!m_mouseTimer) - StartMouseTimer(); - } - else - StopMouseTimer(); - } - return; + if (event.Dragging() && event.LeftIsDown()) { + if (!m_isDragging) { + m_isDragging = true; + SetCaptureWindow(m_colLabelWin); } - StopMouseTimer(); - SetCaptureWindow(NULL); - m_isDragging = false; - - if ( event.LeftDown() ) - { - if (IsCellEditControlShown()) - DisableCellEditControl(true); - - // don't send a label click event for a hit on the edge of the col label - // this is probably the user wanting to resize the col - if ( XToEdgeOfGridCol(x) < 0 ) - { - if ( ContainsColLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) && - !HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectRows) ) - { - bool add = event.ShiftDown() || event.ControlDown(); - wxSheetBlock block; - - if ( event.ShiftDown() ) - { - SetSelectingAnchor(wxSheetCoords(0, GetGridCursorCol())); - block = wxSheetBlock(GetSelectingAnchor(), - wxSheetCoords(GetNumberRows()+1, coords.m_col)); - } - else - { - SetSelectingAnchor(wxSheetCoords(0, coords.m_col)); - block = wxSheetBlock(GetSelectingAnchor(), GetNumberRows()+1, 1); - } + if (event.LeftIsDown()) { + bool can_scroll = true; - // if you can edit the row label then don't select row - bool can_edit = CanEnableCellControl(coords); - if (!add && HasSelection() && - (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, false, false, &event) != EVT_VETOED)) - { - ClearSelection(true); - } - - if (!can_edit) - HighlightSelectingBlock(block); - - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_COL, m_colLabelWin); - } + switch (GetMouseCursorMode()) { + case WXSHEET_CURSOR_RESIZE_COL: { + x = wxMax(x, GetColLeft(m_dragRowOrCol) + GetMinimalColWidth(m_dragRowOrCol)); + can_scroll = false; // x != m_dragLastPos; + DrawRowColResizingMarker(x); + break; + } + case WXSHEET_CURSOR_SELECT_COL: { + if (HasSelectionMode(wxSHEET_SelectNone | wxSHEET_SelectRows)) { + break; } - else - { - // starting to drag-resize a col - if ( CanDragColSize() ) - { - SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_colLabelWin); - SetCaptureWindow(m_colLabelWin); - } + + // check for clearing here since we didn't if editing allowed + bool add = event.ShiftDown() || event.ControlDown(); + if (HasSelection(false) && !add) { + ClearSelection(true); } - } - if ( event.LeftDClick() ) - { - int col = XToEdgeOfGridCol(x); - if ( col < 0 ) - { - if ( ContainsColLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) - { - if (CanEnableCellControl(coords)) - { - m_waitForSlowClick = false; - ClearSelection(true); - EnableCellEditControl(coords); - if ( IsCellEditControlCreated() ) - GetSheetRefData()->m_cellEditor.StartingClick(); - } - } + if (ContainsGridCell(GetSelectingAnchor()) && ContainsColLabelCell(coords)) { + HighlightSelectingBlock(GetSelectingAnchor(), + wxSheetCoords(GetNumberRows() + 1, coords.m_col)); } - else - { - // adjust column width depending on label text - if (CanDragColSize()) - AutoSizeColLabelWidth( col ); + break; + } + default: + break; + } - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); - m_dragLastPos = -1; + if (can_scroll && + ((m_mousePos.x < 0) || (m_mousePos.x > m_colLabelWin->GetClientSize().GetWidth()))) { + if (!m_mouseTimer) { + StartMouseTimer(); } - } - else if ( event.LeftUp() ) - { + } + else { StopMouseTimer(); - SetCaptureWindow(NULL); + } + } + return; + } + + StopMouseTimer(); + SetCaptureWindow(NULL); + m_isDragging = false; + + if (event.LeftDown()) { + if (IsCellEditControlShown()) { + DisableCellEditControl(true); + } + + // don't send a label click event for a hit on the edge of the col label + // this is probably the user wanting to resize the col + if (XToEdgeOfGridCol(x) < 0) { + if (ContainsColLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) && + !HasSelectionMode(wxSHEET_SelectNone | wxSHEET_SelectRows)) { + bool add = event.ShiftDown() || event.ControlDown(); + wxSheetBlock block; + + if (event.ShiftDown()) { + SetSelectingAnchor(wxSheetCoords(0, GetGridCursorCol())); + block = + wxSheetBlock(GetSelectingAnchor(), wxSheetCoords(GetNumberRows() + 1, coords.m_col)); + } + else { + SetSelectingAnchor(wxSheetCoords(0, coords.m_col)); + block = wxSheetBlock(GetSelectingAnchor(), GetNumberRows() + 1, 1); + } + + // if you can edit the row label then don't select row + bool can_edit = CanEnableCellControl(coords); + if (!add && HasSelection() && + (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, false, false, &event) != + EVT_VETOED)) { + ClearSelection(true); + } + + if (!can_edit) { + HighlightSelectingBlock(block); + } + + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_COL, m_colLabelWin); + } + } + else { + // starting to drag-resize a col + if (CanDragColSize()) { + SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_colLabelWin); + SetCaptureWindow(m_colLabelWin); + } + } + } + + if (event.LeftDClick()) { + int col = XToEdgeOfGridCol(x); + if (col < 0) { + if (ContainsColLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) { + if (CanEnableCellControl(coords)) { + m_waitForSlowClick = false; + ClearSelection(true); + EnableCellEditControl(coords); + if (IsCellEditControlCreated()) { + GetSheetRefData()->m_cellEditor.StartingClick(); + } + } + } + } + else { + // adjust column width depending on label text + if (CanDragColSize()) { + AutoSizeColLabelWidth(col); + } + + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); + m_dragLastPos = -1; + } + } + else if (event.LeftUp()) { + StopMouseTimer(); + SetCaptureWindow(NULL); - if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL) ) - { - // Note: send event *after* doing default processing in this case - if (DoEndDragResizeRowCol()) - SendEvent( wxEVT_SHEET_COL_SIZE, wxSheetCoords(-1, m_dragRowOrCol), &event ); - } - else if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_COL) ) - { - if (!GetSelectingBlock().IsEmpty()) - { - bool add = event.ShiftDown() || event.ControlDown(); + if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL)) { + // Note: send event *after* doing default processing in this case + if (DoEndDragResizeRowCol()) { + SendEvent(wxEVT_SHEET_COL_SIZE, wxSheetCoords(-1, m_dragRowOrCol), &event); + } + } + else if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_COL)) { + if (!GetSelectingBlock().IsEmpty()) { + bool add = event.ShiftDown() || event.ControlDown(); - if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - GetSelectingBlock(), true, add, &event) != EVT_VETOED) - { - SelectCols(GetSelectingBlock().GetLeft(), GetSelectingBlock().GetRight(), add, true); - SetSelectingBlock(wxNullSheetBlock); - } - } + if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, add, &event) != + EVT_VETOED) { + SelectCols(GetSelectingBlock().GetLeft(), GetSelectingBlock().GetRight(), add, true); + SetSelectingBlock(wxNullSheetBlock); } + } + } - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); - m_dragLastPos = -1; - if (!m_keySelecting) - SetSelectingAnchor(wxNullSheetCoords); + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); + m_dragLastPos = -1; + if (!m_keySelecting) { + SetSelectingAnchor(wxNullSheetCoords); + } - // send after default processing, they can use own evt handler - SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); + // send after default processing, they can use own evt handler + SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); + } + else if (event.RightDown()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightDown() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if (ContainsColLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED)) - { - // no default action at the moment - } + if (ContainsColLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED)) { + // no default action at the moment + } + } + else if (event.RightDClick()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightDClick() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if (ContainsColLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED)) - { - // no default action at the moment - } + if (ContainsColLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED)) { + // no default action at the moment + } + } + else if (event.RightUp()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightUp() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if (ContainsColLabelCell(coords) && - (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED)) - { - // no default action at the moment - } + if (ContainsColLabelCell(coords) && + (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED)) { + // no default action at the moment } - else if ( event.Moving() ) - { - m_dragRowOrCol = XToEdgeOfGridCol( x ); - if ( m_dragRowOrCol >= 0 ) - { - if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - { - // don't capture the cursor yet - if ( CanDragColSize() ) - SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_colLabelWin); - } + } + else if (event.Moving()) { + m_dragRowOrCol = XToEdgeOfGridCol(x); + if (m_dragRowOrCol >= 0) { + if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + // don't capture the cursor yet + if (CanDragColSize()) { + SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_colLabelWin); } - else if ( !HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); + } + } + else if (!HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_colLabelWin); } + } } -void wxSheet::ProcessCornerLabelMouseEvent( wxMouseEvent& event ) +void wxSheet::ProcessCornerLabelMouseEvent(wxMouseEvent &event) { - wxSheetCoords coords(-1,-1); + wxSheetCoords coords(-1, -1); - if ( event.Dragging() ) - { - if ( event.LeftIsDown() ) - { - if ((GetNumberRows() > 0) && (GetNumberCols() > 0) && !HasSelectionMode(wxSHEET_SelectNone)) - { - SetSelectingAnchor(wxSheetCoords(0, 0)); - HighlightSelectingBlock(GetSelectingAnchor(), - wxSheetCoords(GetNumberRows()+1, GetNumberCols()+1)); - } - } - return; + if (event.Dragging()) { + if (event.LeftIsDown()) { + if ((GetNumberRows() > 0) && (GetNumberCols() > 0) && + !HasSelectionMode(wxSHEET_SelectNone)) { + SetSelectingAnchor(wxSheetCoords(0, 0)); + HighlightSelectingBlock(GetSelectingAnchor(), + wxSheetCoords(GetNumberRows() + 1, GetNumberCols() + 1)); + } } + return; + } - if ( event.LeftDown() ) - { - SetSelectingBlock(wxNullSheetBlock); - - if ( SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) - { - wxSheetBlock block(0, 0, GetNumberRows()+1, GetNumberCols()+1); + if (event.LeftDown()) { + SetSelectingBlock(wxNullSheetBlock); - // if you can edit the corner label then don't select everything - bool can_edit = CanEnableCellControl(coords); - if (!can_edit && !HasSelectionMode(wxSHEET_SelectNone) && - (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, true, false, &event) != EVT_VETOED)) - { - SelectAll(true); - } + if (SendEvent(wxEVT_SHEET_LABEL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) { + wxSheetBlock block(0, 0, GetNumberRows() + 1, GetNumberCols() + 1); + + // if you can edit the corner label then don't select everything + bool can_edit = CanEnableCellControl(coords); + if (!can_edit && !HasSelectionMode(wxSHEET_SelectNone) && + (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, false, &event) != + EVT_VETOED)) { + SelectAll(true); + } + } + } + else if (event.LeftDClick()) { + if (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED) { + if (CanEnableCellControl(coords)) { + ClearSelection(true); + EnableCellEditControl(coords); + if (IsCellEditControlCreated()) { + GetSheetRefData()->m_cellEditor.StartingClick(); } - } - else if ( event.LeftDClick() ) - { - if (SendEvent(wxEVT_SHEET_LABEL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED) - { - if (CanEnableCellControl(coords)) - { - ClearSelection(true); - EnableCellEditControl(coords); - if ( IsCellEditControlCreated() ) - GetSheetRefData()->m_cellEditor.StartingClick(); - m_waitForSlowClick = false; - } - } + m_waitForSlowClick = false; + } + } + } + else if (event.LeftUp()) { + if (!GetSelectingBlock().IsEmpty()) { + if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, false, &event) != + EVT_VETOED) { + SelectAll(true); + SetSelectingBlock(wxNullSheetBlock); + } } - else if ( event.LeftUp() ) - { - if (!GetSelectingBlock().IsEmpty()) - { - if (SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - GetSelectingBlock(), true, false, &event) != EVT_VETOED) - { - SelectAll(true); - SetSelectingBlock(wxNullSheetBlock); - } - } - // send after default processing, they can use own evt handler - SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); + // send after default processing, they can use own evt handler + SendEvent(wxEVT_SHEET_LABEL_LEFT_UP, coords, &event); + } + else if (event.RightDown()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightDown() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED) - { - // no default action at the moment - } + if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED) { + // no default action at the moment + } + } + else if (event.RightDClick()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightDClick() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED) - { - // no default action at the moment - } + if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED) { + // no default action at the moment + } + } + else if (event.RightUp()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - else if ( event.RightUp() ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED) - { - // no default action at the moment - } + if (SendEvent(wxEVT_SHEET_LABEL_RIGHT_UP, coords, &event) == EVT_SKIPPED) { + // no default action at the moment } + } } -void wxSheet::ProcessGridCellMouseEvent( wxMouseEvent& event ) +void wxSheet::ProcessGridCellMouseEvent(wxMouseEvent &event) { - int x, y; - m_mousePos = event.GetPosition(); - CalcUnscrolledPosition( m_mousePos.x, m_mousePos.y, &x, &y ); - wxSheetCoords coords(XYToGridCell( x, y )); + int x, y; + m_mousePos = event.GetPosition(); + CalcUnscrolledPosition(m_mousePos.x, m_mousePos.y, &x, &y); + wxSheetCoords coords(XYToGridCell(x, y)); - //wxPrintf("Mouse %d %d, %d %d\n", x, y, m_mousePos.x, m_mousePos.y); + // wxPrintf("Mouse %d %d, %d %d\n", x, y, m_mousePos.x, m_mousePos.y); - // VZ: if we do this, the mode is reset to WXSHEET_CURSOR_SELECT_CELL - // immediately after it becomes WXSHEET_CURSOR_RESIZE_ROW/COL under wxGTK - if ( event.Entering() || event.Leaving() ) - { - //SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); - //m_gridWin->SetCursor( *wxSTANDARD_CURSOR ); - return; - } + // VZ: if we do this, the mode is reset to WXSHEET_CURSOR_SELECT_CELL + // immediately after it becomes WXSHEET_CURSOR_RESIZE_ROW/COL under wxGTK + if (event.Entering() || event.Leaving()) { + // SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + // m_gridWin->SetCursor( *wxSTANDARD_CURSOR ); + return; + } - if ( event.Dragging() && event.LeftIsDown() ) - { - //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); + if (event.Dragging() && event.LeftIsDown()) { + // wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); - // Don't start doing anything until the mouse has been dragged at - // least 3 pixels in any direction... - if (!m_isDragging) - { - SetCaptureWindow(m_gridWin); + // Don't start doing anything until the mouse has been dragged at + // least 3 pixels in any direction... + if (!m_isDragging) { + SetCaptureWindow(m_gridWin); - if (m_startDragPos == wxDefaultPosition) - { - m_startDragPos = m_mousePos; - return; - } - if ((abs(m_startDragPos.x - m_mousePos.x) < 4) && - (abs(m_startDragPos.y - m_mousePos.y) < 4)) - return; - } + if (m_startDragPos == wxDefaultPosition) { + m_startDragPos = m_mousePos; + return; + } + if ((abs(m_startDragPos.x - m_mousePos.x) < 4) && + (abs(m_startDragPos.y - m_mousePos.y) < 4)) { + return; + } + } - bool can_scroll = true; - m_isDragging = true; - if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - { - // Hide the edit control, so it won't interfer with drag-shrinking. - if ( IsCellEditControlShown() ) - DisableCellEditControl(true); + bool can_scroll = true; + m_isDragging = true; + if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + // Hide the edit control, so it won't interfer with drag-shrinking. + if (IsCellEditControlShown()) { + DisableCellEditControl(true); + } - if ( ContainsGridCell(coords) && !HasSelectionMode(wxSHEET_SelectNone) ) - { - HighlightSelectingBlock( GetSelectingAnchor(), coords ); - } - } - else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW) ) - { - y = wxMax( y, GetRowTop(m_dragRowOrCol) + - GetMinimalRowHeight(m_dragRowOrCol) ); - can_scroll = false; // y != m_dragLastPos; - DrawRowColResizingMarker( y ); - } - else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL) ) - { - x = wxMax( x, GetColLeft(m_dragRowOrCol) + - GetMinimalColWidth(m_dragRowOrCol)); - can_scroll = false; // x != m_dragLastPos; - DrawRowColResizingMarker( x ); - } + if (ContainsGridCell(coords) && !HasSelectionMode(wxSHEET_SelectNone)) { + HighlightSelectingBlock(GetSelectingAnchor(), coords); + } + } + else if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW)) { + y = wxMax(y, GetRowTop(m_dragRowOrCol) + GetMinimalRowHeight(m_dragRowOrCol)); + can_scroll = false; // y != m_dragLastPos; + DrawRowColResizingMarker(y); + } + else if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL)) { + x = wxMax(x, GetColLeft(m_dragRowOrCol) + GetMinimalColWidth(m_dragRowOrCol)); + can_scroll = false; // x != m_dragLastPos; + DrawRowColResizingMarker(x); + } - if (can_scroll && -#if wxCHECK_VERSION(2,7,0) - !wxRect(wxPoint(0,0), m_gridWin->GetClientSize()).Contains(m_mousePos)) + if (can_scroll && +#if wxCHECK_VERSION(2, 7, 0) + !wxRect(wxPoint(0, 0), m_gridWin->GetClientSize()).Contains(m_mousePos)) #else - !wxRect(wxPoint(0,0), m_gridWin->GetClientSize()).Inside(m_mousePos)) + !wxRect(wxPoint(0, 0), m_gridWin->GetClientSize()).Inside(m_mousePos)) #endif - { - if (!m_mouseTimer) - StartMouseTimer(); - } - else - StopMouseTimer(); - - return; - } - - StopMouseTimer(); - SetCaptureWindow(NULL); - m_isDragging = false; - m_startDragPos = wxDefaultPosition; - - if ( event.LeftDown() && ContainsGridCell(coords) ) { - if ( SendEvent(wxEVT_SHEET_CELL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) - { - if ( !event.ControlDown() && HasSelection() ) - { - wxSheetBlock block(0, 0, GetNumberRows()-1, GetNumberCols()-1); - - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, false, false, &event) != EVT_VETOED) - { - ClearSelection(true); - } - } + if (!m_mouseTimer) { + StartMouseTimer(); + } + } + else { + StopMouseTimer(); + } - if ( event.ShiftDown() ) - { - wxSheetBlock block(GetGridCursorCell(), coords); + return; + } - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, true, true, &event) != EVT_VETOED) - { - SelectBlock(block, event.ControlDown(), true); - } - } - else if ( (XToEdgeOfGridCol(x) < 0) && (YToEdgeOfGridRow(y) < 0) ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); + StopMouseTimer(); + SetCaptureWindow(NULL); + m_isDragging = false; + m_startDragPos = wxDefaultPosition; - MakeCellVisible( coords ); + if (event.LeftDown() && ContainsGridCell(coords)) { + if (SendEvent(wxEVT_SHEET_CELL_LEFT_DOWN, coords, &event) == EVT_SKIPPED) { + if (!event.ControlDown() && HasSelection()) { + wxSheetBlock block(0, 0, GetNumberRows() - 1, GetNumberCols() - 1); - if ( !ContainsGridCell(GetSelectingAnchor()) ) - SetSelectingAnchor(coords); + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, false, false, &event) != + EVT_VETOED) { + ClearSelection(true); + } + } - if ( event.ControlDown() ) - { - // toggle cell selection - int sel = IsCellSelected(coords); - wxSheetBlock block(coords, 1, 1); - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, !sel, !sel, &event) != EVT_VETOED) - { - ToggleCellSelection(coords, !sel, true); - SetSelectingBlock(wxNullSheetBlock); - } - } - else - { - if (GetGridCursorCell() == coords) - m_waitForSlowClick = true; + if (event.ShiftDown()) { + wxSheetBlock block(GetGridCursorCell(), coords); - SetGridCursorCell( coords ); - // FIXME weird? Highlight a whole row/col when not in select cells? - if ( !HasSelectionMode(wxSHEET_SelectNone|wxSHEET_SelectCells) ) - HighlightSelectingBlock( coords, coords ); - } - } + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, true, &event) != EVT_VETOED) { + SelectBlock(block, event.ControlDown(), true); } - } - else if ( event.LeftDClick() && ContainsGridCell(coords) ) - { - if ((XToEdgeOfGridCol(x) < 0) && (YToEdgeOfGridRow(y) < 0) && - (SendEvent(wxEVT_SHEET_CELL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) - { - if ((coords == GetGridCursorCell()) && CanEnableCellControl(GetGridCursorCell())) - { - ClearSelection(true); - EnableCellEditControl(GetGridCursorCell()); - if ( IsCellEditControlCreated() ) - GetSheetRefData()->m_cellEditor.StartingClick(); - - m_waitForSlowClick = false; - } + } + else if ((XToEdgeOfGridCol(x) < 0) && (YToEdgeOfGridRow(y) < 0)) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } - } - else if ( event.LeftUp() ) - { - StopMouseTimer(); - SetCaptureWindow(NULL); - if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - { - if ((coords == GetGridCursorCell()) && m_waitForSlowClick && - CanEnableCellControl(GetGridCursorCell())) - { - ClearSelection(true); - EnableCellEditControl(GetGridCursorCell()); - if ( IsCellEditControlCreated() ) - GetSheetRefData()->m_cellEditor.StartingClick(); + MakeCellVisible(coords); - m_waitForSlowClick = false; - } - else if ( !GetSelectingBlock().IsEmpty() ) - { - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - GetSelectingBlock(), true, true, &event) != EVT_VETOED) - { - SelectBlock(GetSelectingBlock(), true, true); - SetSelectingBlock(wxNullSheetBlock); - } - } + if (!ContainsGridCell(GetSelectingAnchor())) { + SetSelectingAnchor(coords); } - else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW) ) - { - // Note: send event *after* doing default processing in this case - if (DoEndDragResizeRowCol()) - SendEvent( wxEVT_SHEET_ROW_SIZE, wxSheetCoords(m_dragRowOrCol, -1), &event ); - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + if (event.ControlDown()) { + // toggle cell selection + int sel = IsCellSelected(coords); + wxSheetBlock block(coords, 1, 1); + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, !sel, !sel, &event) != + EVT_VETOED) { + ToggleCellSelection(coords, !sel, true); + SetSelectingBlock(wxNullSheetBlock); + } } - else if ( HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL) ) - { - // Note: send event *after* doing default processing in this case - if (DoEndDragResizeRowCol()) - SendEvent( wxEVT_SHEET_COL_SIZE, wxSheetCoords(-1, m_dragRowOrCol), &event ); + else { + if (GetGridCursorCell() == coords) { + m_waitForSlowClick = true; + } - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + SetGridCursorCell(coords); + // FIXME weird? Highlight a whole row/col when not in select cells? + if (!HasSelectionMode(wxSHEET_SelectNone | wxSHEET_SelectCells)) { + HighlightSelectingBlock(coords, coords); + } } - - // Show edit control, if it has been hidden for drag-shrinking. - if (IsCellEditControlCreated() && !IsCellEditControlShown()) - ShowCellEditControl(); - - if (!m_keySelecting) - SetSelectingAnchor(wxNullSheetCoords); - - m_dragLastPos = -1; - - // send after default processing, they can use own evt handler - SendEvent(wxEVT_SHEET_CELL_LEFT_UP, coords, &event); + } } - else if ( event.RightDown() && ContainsGridCell(coords) ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - - if (SendEvent(wxEVT_SHEET_CELL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED) - { - // no default action at the moment + } + else if (event.LeftDClick() && ContainsGridCell(coords)) { + if ((XToEdgeOfGridCol(x) < 0) && (YToEdgeOfGridRow(y) < 0) && + (SendEvent(wxEVT_SHEET_CELL_LEFT_DCLICK, coords, &event) == EVT_SKIPPED)) { + if ((coords == GetGridCursorCell()) && CanEnableCellControl(GetGridCursorCell())) { + ClearSelection(true); + EnableCellEditControl(GetGridCursorCell()); + if (IsCellEditControlCreated()) { + GetSheetRefData()->m_cellEditor.StartingClick(); } + + m_waitForSlowClick = false; + } } - else if ( event.RightDClick() && ContainsGridCell(coords) ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); + } + else if (event.LeftUp()) { + StopMouseTimer(); + SetCaptureWindow(NULL); - if (SendEvent(wxEVT_SHEET_CELL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED) - { - // no default action at the moment + if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + if ((coords == GetGridCursorCell()) && m_waitForSlowClick && + CanEnableCellControl(GetGridCursorCell())) { + ClearSelection(true); + EnableCellEditControl(GetGridCursorCell()); + if (IsCellEditControlCreated()) { + GetSheetRefData()->m_cellEditor.StartingClick(); } - } - else if ( event.RightUp() && ContainsGridCell(coords) ) - { - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - if (SendEvent(wxEVT_SHEET_CELL_RIGHT_UP, coords, &event) == EVT_SKIPPED) - { - // no default action at the moment + m_waitForSlowClick = false; + } + else if (!GetSelectingBlock().IsEmpty()) { + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, true, &event) != + EVT_VETOED) { + SelectBlock(GetSelectingBlock(), true, true); + SetSelectingBlock(wxNullSheetBlock); } + } } - else if ( event.Moving() && !event.IsButton() ) - { - if ( (coords.GetRow() < 0) || (coords.GetCol() < 0) ) - { - // out of grid cell area - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); - return; - } + else if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW)) { + // Note: send event *after* doing default processing in this case + if (DoEndDragResizeRowCol()) { + SendEvent(wxEVT_SHEET_ROW_SIZE, wxSheetCoords(m_dragRowOrCol, -1), &event); + } - int dragRow = YToEdgeOfGridRow( y ); - int dragCol = XToEdgeOfGridCol( x ); + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + } + else if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL)) { + // Note: send event *after* doing default processing in this case + if (DoEndDragResizeRowCol()) { + SendEvent(wxEVT_SHEET_COL_SIZE, wxSheetCoords(-1, m_dragRowOrCol), &event); + } - // check if this is inside a spanned cell, if so don't drag - if ( (dragRow >= 0) || (dragCol >= 0) ) - { - const wxSheetBlock cellBlock(GetCellBlock(coords)); - if (!cellBlock.IsOneCell() && - ((dragRow != cellBlock.GetBottom()) || (dragCol != cellBlock.GetRight()))) - dragRow = dragCol = -1; - } + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + } - // Dragging on the corner of a cell to resize in both - // directions is not implemented yet... - if ( (dragRow >= 0) && (dragCol >= 0) ) - { - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); - } - else if ( dragRow >= 0 ) - { - m_dragRowOrCol = dragRow; + // Show edit control, if it has been hidden for drag-shrinking. + if (IsCellEditControlCreated() && !IsCellEditControlShown()) { + ShowCellEditControl(); + } - if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - { - if ( CanDragRowSize() && CanDragGridSize() ) - { - SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_gridWin); - SetCaptureWindow(m_gridWin); - } - } + if (!m_keySelecting) { + SetSelectingAnchor(wxNullSheetCoords); + } - if ( dragCol >= 0 ) - m_dragRowOrCol = dragCol; - } - else if ( dragCol >= 0 ) - { - m_dragRowOrCol = dragCol; + m_dragLastPos = -1; - if ( HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - { - if ( CanDragColSize() && CanDragGridSize() ) - { - SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_gridWin); - SetCaptureWindow(m_gridWin); - } - } - } - // Neither on a row or col edge - else if ( !HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL) ) - SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + // send after default processing, they can use own evt handler + SendEvent(wxEVT_SHEET_CELL_LEFT_UP, coords, &event); + } + else if (event.RightDown() && ContainsGridCell(coords)) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); } -} -void wxSheet::OnKeyDown( wxKeyEvent& event ) -{ - //wxCHECK_RET(!m_inOnKeyDown, wxT("wxSheet::OnKeyDown called while already active")); - // yield called from SetGridOrigin causes this in MSW + if (SendEvent(wxEVT_SHEET_CELL_RIGHT_DOWN, coords, &event) == EVT_SKIPPED) { + // no default action at the moment + } + } + else if (event.RightDClick() && ContainsGridCell(coords)) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); + } - if (m_inOnKeyDown) - return; + if (SendEvent(wxEVT_SHEET_CELL_RIGHT_DCLICK, coords, &event) == EVT_SKIPPED) { + // no default action at the moment + } + } + else if (event.RightUp() && ContainsGridCell(coords)) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); + } - m_inOnKeyDown = true; + if (SendEvent(wxEVT_SHEET_CELL_RIGHT_UP, coords, &event) == EVT_SKIPPED) { + // no default action at the moment + } + } + else if (event.Moving() && !event.IsButton()) { + if ((coords.GetRow() < 0) || (coords.GetCol() < 0)) { + // out of grid cell area + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + return; + } - // FIXME - is this really a good idea? probably not, should make own "key" event - // propagate the event up and see if it gets processed - //wxWindow *parent = GetParent(); - //wxKeyEvent keyEvt( event ); - //keyEvt.SetEventObject( parent ); - //!parent->GetEventHandler()->ProcessEvent(keyEvt) && + int dragRow = YToEdgeOfGridRow(y); + int dragCol = XToEdgeOfGridCol(x); - if ( GetNumberRows() && GetNumberCols() ) - { - // try local handlers - switch ( event.GetKeyCode() ) - { - case WXK_RETURN: - case WXK_NUMPAD_ENTER: - { - if ( event.ControlDown() ) - event.Skip(); // to let the edit control have the return - else - { - if ( IsCellEditControlCreated() ) - DisableCellEditControl(true); - if ( GetGridCursorRow() < GetNumberRows()-1 ) - MoveCursorDown( event.ShiftDown() ); - } - break; - } - case WXK_ESCAPE: - { - ClearSelection(); - break; - } - case WXK_TAB: - { - if (event.ShiftDown()) - { - if ( IsCellEditControlCreated() ) - DisableCellEditControl(true); - if ( GetGridCursorCol() > 0 ) - MoveCursorLeft( false ); - } - else - { - if ( IsCellEditControlCreated() ) - DisableCellEditControl(true); - if ( GetGridCursorCol() < GetNumberCols()-1 ) - MoveCursorRight( false ); - } - break; - } - case WXK_SPACE: - { - if ( event.ShiftDown() && ContainsGridCell(GetGridCursorCell()) ) - { - wxSheetBlock block(GetGridCursorRow(), 0, 1, GetNumberCols()+1); + // check if this is inside a spanned cell, if so don't drag + if ((dragRow >= 0) || (dragCol >= 0)) { + const wxSheetBlock cellBlock(GetCellBlock(coords)); + if (!cellBlock.IsOneCell() && + ((dragRow != cellBlock.GetBottom()) || (dragCol != cellBlock.GetRight()))) { + dragRow = dragCol = -1; + } + } - if (!GetSelectingBlock().IsEmpty() && - GetSelectingBlock().Contains(GetGridCursorCell())) - { - block.SetTop(GetSelectingBlock().GetTop()); - block.SetBottom(GetSelectingBlock().GetBottom()); - } + // Dragging on the corner of a cell to resize in both + // directions is not implemented yet... + if ((dragRow >= 0) && (dragCol >= 0)) { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + } + else if (dragRow >= 0) { + m_dragRowOrCol = dragRow; - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, true, false, &event) != EVT_VETOED) - { - SelectRows(block.GetTop(), block.GetBottom(), false, true); - } + if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + if (CanDragRowSize() && CanDragGridSize()) { + SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW, m_gridWin); + SetCaptureWindow(m_gridWin); + } + } - break; - } - if ( event.ControlDown() && ContainsGridCell(GetGridCursorCell()) ) - { - wxSheetBlock block(0, GetGridCursorCol(), GetNumberRows()+1, 1); + if (dragCol >= 0) { + m_dragRowOrCol = dragCol; + } + } + else if (dragCol >= 0) { + m_dragRowOrCol = dragCol; - if (!GetSelectingBlock().IsEmpty() && - GetSelectingBlock().Contains(GetGridCursorCell())) - { - block.SetLeft(GetSelectingBlock().GetLeft()); - block.SetRight(GetSelectingBlock().GetRight()); - } + if (HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + if (CanDragColSize() && CanDragGridSize()) { + SetMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL, m_gridWin); + SetCaptureWindow(m_gridWin); + } + } + } + // Neither on a row or col edge + else if (!HasMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL)) { + SetMouseCursorMode(WXSHEET_CURSOR_SELECT_CELL, m_gridWin); + } + } +} - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, true, false, &event) != EVT_VETOED) - { - SelectCols(block.GetLeft(), block.GetRight(), false, true); - } +void wxSheet::OnKeyDown(wxKeyEvent &event) +{ + // wxCHECK_RET(!m_inOnKeyDown, wxT("wxSheet::OnKeyDown called while already active")); + // yield called from SetGridOrigin causes this in MSW - break; - } - if ( event.AltDown() && ContainsGridCell(GetGridCursorCell()) ) - { - // Toggle cell selection FIXME not sure how useful this is - bool sel = IsCellSelected(GetGridCursorCell()); - wxSheetBlock block(GetGridCursorCell(), 1, 1); - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - block, !sel, !sel, &event) != EVT_VETOED) - { - ToggleCellSelection(GetGridCursorCell(), !sel, true); - } + if (m_inOnKeyDown) { + return; + } - break; - } - if ( !IsEditable() ) - { - MoveCursorRight( false ); - break; - } - // Otherwise fall through to default - } - default: - { - // is it possible to edit the current cell at all? - if ( !IsCellEditControlCreated() && CanEnableCellControl(GetGridCursorCell()) ) - { - // yes, now check whether the cells editor accepts the key - wxSheetCellEditor editor(GetAttr(GetGridCursorCell()).GetEditor(this, GetGridCursorCell())); + m_inOnKeyDown = true; - // is special and will always start editing, for - // other keys - ask the editor itself - if ( ((event.GetKeyCode() == WXK_F2) && !event.HasModifiers()) - || editor.IsAcceptedKey(event) ) - { - // ensure cell is visble - MakeCellVisible(GetGridCursorCell()); - EnableCellEditControl(GetGridCursorCell()); - - // a problem can arise if the cell is not completely - // visible (even after calling MakeCellVisible the - // control is not created and calling StartingKey will - // crash the app - if ( IsCellEditControlCreated() ) - GetSheetRefData()->m_cellEditor.StartingKey(event); - } - else - event.Skip(); - } - else - { - // let others process char events with modifiers or all - // char events for readonly cells - event.Skip(); - } - break; - } - } + // FIXME - is this really a good idea? probably not, should make own "key" event + // propagate the event up and see if it gets processed + // wxWindow *parent = GetParent(); + // wxKeyEvent keyEvt( event ); + // keyEvt.SetEventObject( parent ); + //! parent->GetEventHandler()->ProcessEvent(keyEvt) && + + if (GetNumberRows() && GetNumberCols()) { + // try local handlers + switch (event.GetKeyCode()) { + case WXK_RETURN: + case WXK_NUMPAD_ENTER: { + if (event.ControlDown()) { + event.Skip(); // to let the edit control have the return + } + else { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); + } + if (GetGridCursorRow() < GetNumberRows() - 1) { + MoveCursorDown(event.ShiftDown()); + } + } + break; + } + case WXK_ESCAPE: { + ClearSelection(); + break; + } + case WXK_TAB: { + if (event.ShiftDown()) { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); + } + if (GetGridCursorCol() > 0) { + MoveCursorLeft(false); + } + } + else { + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); + } + if (GetGridCursorCol() < GetNumberCols() - 1) { + MoveCursorRight(false); + } + } + break; + } + case WXK_SPACE: { + if (event.ShiftDown() && ContainsGridCell(GetGridCursorCell())) { + wxSheetBlock block(GetGridCursorRow(), 0, 1, GetNumberCols() + 1); + + if (!GetSelectingBlock().IsEmpty() && GetSelectingBlock().Contains(GetGridCursorCell())) { + block.SetTop(GetSelectingBlock().GetTop()); + block.SetBottom(GetSelectingBlock().GetBottom()); + } + + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, false, &event) != + EVT_VETOED) { + SelectRows(block.GetTop(), block.GetBottom(), false, true); + } + + break; + } + if (event.ControlDown() && ContainsGridCell(GetGridCursorCell())) { + wxSheetBlock block(0, GetGridCursorCol(), GetNumberRows() + 1, 1); + + if (!GetSelectingBlock().IsEmpty() && GetSelectingBlock().Contains(GetGridCursorCell())) { + block.SetLeft(GetSelectingBlock().GetLeft()); + block.SetRight(GetSelectingBlock().GetRight()); + } + + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, true, false, &event) != + EVT_VETOED) { + SelectCols(block.GetLeft(), block.GetRight(), false, true); + } + + break; + } + if (event.AltDown() && ContainsGridCell(GetGridCursorCell())) { + // Toggle cell selection FIXME not sure how useful this is + bool sel = IsCellSelected(GetGridCursorCell()); + wxSheetBlock block(GetGridCursorCell(), 1, 1); + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, block, !sel, !sel, &event) != EVT_VETOED) { + ToggleCellSelection(GetGridCursorCell(), !sel, true); + } + + break; + } + if (!IsEditable()) { + MoveCursorRight(false); + break; + } + // Otherwise fall through to default + } + default: { + // is it possible to edit the current cell at all? + if (!IsCellEditControlCreated() && CanEnableCellControl(GetGridCursorCell())) { + // yes, now check whether the cells editor accepts the key + wxSheetCellEditor editor( + GetAttr(GetGridCursorCell()).GetEditor(this, GetGridCursorCell())); + + // is special and will always start editing, for + // other keys - ask the editor itself + if (((event.GetKeyCode() == WXK_F2) && !event.HasModifiers()) || + editor.IsAcceptedKey(event)) { + // ensure cell is visble + MakeCellVisible(GetGridCursorCell()); + EnableCellEditControl(GetGridCursorCell()); + + // a problem can arise if the cell is not completely + // visible (even after calling MakeCellVisible the + // control is not created and calling StartingKey will + // crash the app + if (IsCellEditControlCreated()) { + GetSheetRefData()->m_cellEditor.StartingKey(event); + } + } + else { + event.Skip(); + } + } + else { + // let others process char events with modifiers or all + // char events for readonly cells + event.Skip(); + } + break; } + } + } - m_inOnKeyDown = false; + m_inOnKeyDown = false; } -void wxSheet::OnKeyUp( wxKeyEvent& event ) +void wxSheet::OnKeyUp(wxKeyEvent &event) { - if ( m_keySelecting && (event.GetKeyCode() == WXK_SHIFT) ) - { - if ( !GetSelectingBlock().IsEmpty() ) - { - if (!HasSelectionMode(wxSHEET_SelectNone) && - SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, - GetSelectingBlock(), true, true, &event) != EVT_VETOED) - { - SelectBlock(GetSelectingBlock(), true, true); - SetSelectingBlock(wxNullSheetBlock); - } - - SetSelectingAnchor(wxNullSheetCoords); - } + if (m_keySelecting && (event.GetKeyCode() == WXK_SHIFT)) { + if (!GetSelectingBlock().IsEmpty()) { + if (!HasSelectionMode(wxSHEET_SelectNone) && + SendRangeEvent(wxEVT_SHEET_RANGE_SELECTING, GetSelectingBlock(), true, true, &event) != + EVT_VETOED) { + SelectBlock(GetSelectingBlock(), true, true); + SetSelectingBlock(wxNullSheetBlock); + } - m_keySelecting = false; + SetSelectingAnchor(wxNullSheetCoords); } - event.Skip(); + m_keySelecting = false; + } + + event.Skip(); } -void wxSheet::OnChar( wxKeyEvent& event ) +void wxSheet::OnChar(wxKeyEvent &event) { - //wxCHECK_RET(!m_inOnKeyDown, wxT("wxSheet::OnKeyDown called while already active")); - // yield called from SetGridOrigin causes this in MSW - if (m_inOnKeyDown) - return; + // wxCHECK_RET(!m_inOnKeyDown, wxT("wxSheet::OnKeyDown called while already active")); + // yield called from SetGridOrigin causes this in MSW + if (m_inOnKeyDown) { + return; + } - if ( !GetNumberRows() || !GetNumberCols() ) - { - event.Skip(); - return; + if (!GetNumberRows() || !GetNumberCols()) { + event.Skip(); + return; + } + + m_inOnKeyDown = true; + int keyMods = GetKeyModifiers(&event); + + // try local handlers + switch (event.GetKeyCode()) { + case WXK_UP: { + if (!ContainsGridCell(GetGridCursorCell())) { + break; + } + if (event.ControlDown()) { + MoveCursorUpBlock(event.ShiftDown()); + } + else if (keyMods == ALT_DOWN) { + SetRowHeight(GetGridCursorRow(), GetRowHeight(GetGridCursorRow()) - 5); + } + else { + MoveCursorUp(event.ShiftDown()); } - m_inOnKeyDown = true; - int keyMods = GetKeyModifiers(&event); + break; + } + case WXK_DOWN: { + if (!ContainsGridCell(GetGridCursorCell())) { + break; + } + if (event.ControlDown()) { + MoveCursorDownBlock(event.ShiftDown()); + } + else if (keyMods == ALT_DOWN) { + SetRowHeight(GetGridCursorRow(), GetRowHeight(GetGridCursorRow()) + 5); + } + else { + MoveCursorDown(event.ShiftDown()); + } - // try local handlers - switch ( event.GetKeyCode() ) - { - case WXK_UP: - { - if (!ContainsGridCell(GetGridCursorCell())) break; - if ( event.ControlDown() ) - MoveCursorUpBlock( event.ShiftDown() ); - else if ( keyMods == ALT_DOWN ) - SetRowHeight(GetGridCursorRow(), GetRowHeight(GetGridCursorRow())-5); - else - MoveCursorUp( event.ShiftDown() ); - - break; - } - case WXK_DOWN: - { - if (!ContainsGridCell(GetGridCursorCell())) break; - if ( event.ControlDown() ) - MoveCursorDownBlock( event.ShiftDown() ); - else if ( keyMods == ALT_DOWN ) - SetRowHeight(GetGridCursorRow(), GetRowHeight(GetGridCursorRow())+5); - else - MoveCursorDown( event.ShiftDown() ); - - break; - } - case WXK_LEFT: - { - if (!ContainsGridCell(GetGridCursorCell())) break; - if ( event.ControlDown() ) - MoveCursorLeftBlock( event.ShiftDown() ); - else if ( keyMods == ALT_DOWN ) - SetColWidth(GetGridCursorCol(), GetColWidth(GetGridCursorCol())-5); - else - MoveCursorLeft( event.ShiftDown() ); - - break; - } - case WXK_RIGHT: - { - if (!ContainsGridCell(GetGridCursorCell())) break; - if ( event.ControlDown() ) - MoveCursorRightBlock( event.ShiftDown() ); - else if ( keyMods == ALT_DOWN ) - SetColWidth(GetGridCursorCol(), GetColWidth(GetGridCursorCol())+5); - else - MoveCursorRight( event.ShiftDown() ); - - break; - } - case WXK_PAGEUP: - { - MoveCursorUpPage( event.ShiftDown() ); - break; - } - case WXK_PAGEDOWN: - { - MoveCursorDownPage( event.ShiftDown() ); - break; - } - case WXK_HOME : - { - if ( event.ControlDown() ) - { - wxSheetCoords coords( 0, 0 ); - if ( ContainsGridCell(coords) ) - { - wxSheetCoords lastCoords(GetGridCursorCell()); - MakeCellVisible( coords ); - SetGridCursorCell( coords ); - if ( event.ShiftDown() && ContainsGridCell(lastCoords) ) - { - m_keySelecting = true; - if ( !ContainsGridCell(GetSelectingAnchor()) ) - SetSelectingAnchor(lastCoords); + break; + } + case WXK_LEFT: { + if (!ContainsGridCell(GetGridCursorCell())) { + break; + } + if (event.ControlDown()) { + MoveCursorLeftBlock(event.ShiftDown()); + } + else if (keyMods == ALT_DOWN) { + SetColWidth(GetGridCursorCol(), GetColWidth(GetGridCursorCol()) - 5); + } + else { + MoveCursorLeft(event.ShiftDown()); + } - HighlightSelectingBlock(GetSelectingAnchor(), GetGridCursorCell()); - } - } - } - else - event.Skip(); + break; + } + case WXK_RIGHT: { + if (!ContainsGridCell(GetGridCursorCell())) { + break; + } + if (event.ControlDown()) { + MoveCursorRightBlock(event.ShiftDown()); + } + else if (keyMods == ALT_DOWN) { + SetColWidth(GetGridCursorCol(), GetColWidth(GetGridCursorCol()) + 5); + } + else { + MoveCursorRight(event.ShiftDown()); + } - break; + break; + } + case WXK_PAGEUP: { + MoveCursorUpPage(event.ShiftDown()); + break; + } + case WXK_PAGEDOWN: { + MoveCursorDownPage(event.ShiftDown()); + break; + } + case WXK_HOME: { + if (event.ControlDown()) { + wxSheetCoords coords(0, 0); + if (ContainsGridCell(coords)) { + wxSheetCoords lastCoords(GetGridCursorCell()); + MakeCellVisible(coords); + SetGridCursorCell(coords); + if (event.ShiftDown() && ContainsGridCell(lastCoords)) { + m_keySelecting = true; + if (!ContainsGridCell(GetSelectingAnchor())) { + SetSelectingAnchor(lastCoords); + } + + HighlightSelectingBlock(GetSelectingAnchor(), GetGridCursorCell()); } - case WXK_END: - { - if ( event.ControlDown() ) - { - wxSheetCoords coords(GetNumberRows()-1, GetNumberCols()-1); - if ( ContainsGridCell(coords) ) - { - wxSheetCoords lastCoords(GetGridCursorCell()); - MakeCellVisible( coords ); - SetGridCursorCell( coords ); - if ( event.ShiftDown() && ContainsGridCell(lastCoords) ) - { - m_keySelecting = true; - if ( !ContainsGridCell(GetSelectingAnchor()) ) - SetSelectingAnchor(lastCoords); + } + } + else { + event.Skip(); + } - HighlightSelectingBlock(GetSelectingAnchor(), GetGridCursorCell()); - } - } - } - else - event.Skip(); + break; + } + case WXK_END: { + if (event.ControlDown()) { + wxSheetCoords coords(GetNumberRows() - 1, GetNumberCols() - 1); + if (ContainsGridCell(coords)) { + wxSheetCoords lastCoords(GetGridCursorCell()); + MakeCellVisible(coords); + SetGridCursorCell(coords); + if (event.ShiftDown() && ContainsGridCell(lastCoords)) { + m_keySelecting = true; + if (!ContainsGridCell(GetSelectingAnchor())) { + SetSelectingAnchor(lastCoords); + } - break; + HighlightSelectingBlock(GetSelectingAnchor(), GetGridCursorCell()); } - default : - event.Skip(); + } } + else { + event.Skip(); + } + + break; + } + default: + event.Skip(); + } - m_inOnKeyDown = false; + m_inOnKeyDown = false; } void wxSheet::StopMouseTimer() { - if (m_mouseTimer) - { - if (m_mouseTimer->IsRunning()) - m_mouseTimer->Stop(); - - delete m_mouseTimer; - m_mouseTimer = NULL; + if (m_mouseTimer) { + if (m_mouseTimer->IsRunning()) { + m_mouseTimer->Stop(); } + + delete m_mouseTimer; + m_mouseTimer = NULL; + } } void wxSheet::StartMouseTimer() { - if (!m_mouseTimer) - m_mouseTimer = new wxTimer(this, ID_MOUSE_DRAG_TIMER); + if (!m_mouseTimer) { + m_mouseTimer = new wxTimer(this, ID_MOUSE_DRAG_TIMER); + } - if (!m_mouseTimer->IsRunning()) - m_mouseTimer->Start(100, true); // one shot + if (!m_mouseTimer->IsRunning()) { + m_mouseTimer->Start(100, true); // one shot + } } -void wxSheet::OnMouseTimer( wxTimerEvent &WXUNUSED(event) ) +void wxSheet::OnMouseTimer(wxTimerEvent &WXUNUSED(event)) { - // the window must be captured and thus m_mousePos is for that window - wxWindow *win = GetCaptureWindow(); + // the window must be captured and thus m_mousePos is for that window + wxWindow *win = GetCaptureWindow(); - if (!win || (GetNumberCols() < 1) || (GetNumberRows() < 1)) - { - StopMouseTimer(); - return; - } + if (!win || (GetNumberCols() < 1) || (GetNumberRows() < 1)) { + StopMouseTimer(); + return; + } - wxSize clientSize(win->GetClientSize()); - int dx = (m_mousePos.x < 0) ? -1 : ((m_mousePos.x > clientSize.x) ? 1 : 0); - int dy = (m_mousePos.y < 0) ? -1 : ((m_mousePos.y > clientSize.y) ? 1 : 0); + wxSize clientSize(win->GetClientSize()); + int dx = (m_mousePos.x < 0) ? -1 : ((m_mousePos.x > clientSize.x) ? 1 : 0); + int dy = (m_mousePos.y < 0) ? -1 : ((m_mousePos.y > clientSize.y) ? 1 : 0); - if (win == m_rowLabelWin) - dx = 0; - else if (win == m_colLabelWin) - dy = 0; + if (win == m_rowLabelWin) { + dx = 0; + } + else if (win == m_colLabelWin) { + dy = 0; + } - if ((dx == 0) && (dy == 0)) // mouse is back in the window - { - StopMouseTimer(); - return; - } + if ((dx == 0) && (dy == 0)) // mouse is back in the window + { + StopMouseTimer(); + return; + } - /*wxSize cSize = */ m_gridWin->GetClientSize(); - SetGridOrigin( m_gridOrigin.x + dx*SHEET_SCROLL_LINE_X, - m_gridOrigin.y + dy*SHEET_SCROLL_LINE_Y, true, true ); + /*wxSize cSize = */ m_gridWin->GetClientSize(); + SetGridOrigin(m_gridOrigin.x + dx * SHEET_SCROLL_LINE_X, + m_gridOrigin.y + dy * SHEET_SCROLL_LINE_Y, true, true); - // send fake mouse event to process, assume left down and we're dragging - wxMouseEvent mEvt(wxEVT_MOTION); - mEvt.SetEventObject(win); - mEvt.m_leftDown = true; - mEvt.m_x = m_mousePos.x; - mEvt.m_y = m_mousePos.y; + // send fake mouse event to process, assume left down and we're dragging + wxMouseEvent mEvt(wxEVT_MOTION); + mEvt.SetEventObject(win); + mEvt.m_leftDown = true; + mEvt.m_x = m_mousePos.x; + mEvt.m_y = m_mousePos.y; - win->GetEventHandler()->ProcessEvent(mEvt); - StartMouseTimer(); + win->GetEventHandler()->ProcessEvent(mEvt); + StartMouseTimer(); } bool wxSheet::DoEndDragResizeRowCol() { - if ( m_dragLastPos < 0 ) - return false; + if (m_dragLastPos < 0) { + return false; + } - if (IsCellEditControlCreated()) - DisableCellEditControl(true); + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); + } - // erase the last line and resize the row/col - DrawRowColResizingMarker(); + // erase the last line and resize the row/col + DrawRowColResizingMarker(); - if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW)) - { - int height = m_dragLastPos - GetRowTop(m_dragRowOrCol); - const int minHeight = GetMinimalRowHeight(m_dragRowOrCol); - if (minHeight > height) height = minHeight; - if (height != GetRowHeight(m_dragRowOrCol)) - { - SetRowHeight( m_dragRowOrCol, height ); - return true; - } + if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_ROW)) { + int height = m_dragLastPos - GetRowTop(m_dragRowOrCol); + const int minHeight = GetMinimalRowHeight(m_dragRowOrCol); + if (minHeight > height) { + height = minHeight; } - else if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL)) - { - int width = m_dragLastPos - GetColLeft(m_dragRowOrCol); - const int minWidth = GetMinimalColWidth(m_dragRowOrCol); - if (minWidth > width) width = minWidth; - if (width != GetColWidth(m_dragRowOrCol)) - { - SetColWidth( m_dragRowOrCol, width ); - return true; - } + if (height != GetRowHeight(m_dragRowOrCol)) { + SetRowHeight(m_dragRowOrCol, height); + return true; + } + } + else if (HasMouseCursorMode(WXSHEET_CURSOR_RESIZE_COL)) { + int width = m_dragLastPos - GetColLeft(m_dragRowOrCol); + const int minWidth = GetMinimalColWidth(m_dragRowOrCol); + if (minWidth > width) { + width = minWidth; } + if (width != GetColWidth(m_dragRowOrCol)) { + SetColWidth(m_dragRowOrCol, width); + return true; + } + } - return false; + return false; } void wxSheet::SetMouseCursorMode(MouseCursorMode mode, wxWindow *win) { - wxCHECK_RET(win, wxT("Invalid window")); + wxCHECK_RET(win, wxT("Invalid window")); - m_mouseCursorMode = mode; - - if (win == m_gridWin) - { - if (m_gridWin->m_mouseCursor == mode) - return; + m_mouseCursorMode = mode; - m_gridWin->m_mouseCursor = mode; + if (win == m_gridWin) { + if (m_gridWin->m_mouseCursor == mode) { + return; } - else if (win == m_cornerLabelWin) - { - if (m_cornerLabelWin->m_mouseCursor == mode) - return; - m_cornerLabelWin->m_mouseCursor = mode; + m_gridWin->m_mouseCursor = mode; + } + else if (win == m_cornerLabelWin) { + if (m_cornerLabelWin->m_mouseCursor == mode) { + return; } - else if (win == m_rowLabelWin) - { - if (m_rowLabelWin->m_mouseCursor == mode) - return; - m_rowLabelWin->m_mouseCursor = mode; + m_cornerLabelWin->m_mouseCursor = mode; + } + else if (win == m_rowLabelWin) { + if (m_rowLabelWin->m_mouseCursor == mode) { + return; } - else if (win == m_colLabelWin) - { - if (m_colLabelWin->m_mouseCursor == mode) - return; - m_colLabelWin->m_mouseCursor = mode; + m_rowLabelWin->m_mouseCursor = mode; + } + else if (win == m_colLabelWin) { + if (m_colLabelWin->m_mouseCursor == mode) { + return; } - else if (win == this) - { - if (m_mouseCursor == mode) - return; - m_mouseCursor = mode; + m_colLabelWin->m_mouseCursor = mode; + } + else if (win == this) { + if (m_mouseCursor == mode) { + return; } - switch ( mode ) - { - case WXSHEET_CURSOR_RESIZE_ROW : - case WXSHEET_CURSOR_SPLIT_VERTICAL : - { - win->SetCursor( GetSheetRefData()->m_rowResizeCursor ); - break; - } - case WXSHEET_CURSOR_RESIZE_COL : - case WXSHEET_CURSOR_SPLIT_HORIZONTAL : - { - win->SetCursor( GetSheetRefData()->m_colResizeCursor ); - break; - } - default: - win->SetCursor( *wxSTANDARD_CURSOR ); - } + m_mouseCursor = mode; + } + + switch (mode) { + case WXSHEET_CURSOR_RESIZE_ROW: + case WXSHEET_CURSOR_SPLIT_VERTICAL: { + win->SetCursor(GetSheetRefData()->m_rowResizeCursor); + break; + } + case WXSHEET_CURSOR_RESIZE_COL: + case WXSHEET_CURSOR_SPLIT_HORIZONTAL: { + win->SetCursor(GetSheetRefData()->m_colResizeCursor); + break; + } + default: + win->SetCursor(*wxSTANDARD_CURSOR); + } } void wxSheet::SetCaptureWindow(wxWindow *win) { - if (m_winCapture && (m_winCapture != win) && m_winCapture->HasCapture()) - m_winCapture->ReleaseMouse(); + if (m_winCapture && (m_winCapture != win) && m_winCapture->HasCapture()) { + m_winCapture->ReleaseMouse(); + } - m_winCapture = win; + m_winCapture = win; - if (m_winCapture && (!m_winCapture->HasCapture())) - m_winCapture->CaptureMouse(); + if (m_winCapture && (!m_winCapture->HasCapture())) { + m_winCapture->CaptureMouse(); + } } -wxWindow* wxSheet::GetWindowForCoords( const wxSheetCoords& coords ) const +wxWindow *wxSheet::GetWindowForCoords(const wxSheetCoords &coords) const { - if (IsGridCell(coords)) - return m_gridWin; - if (IsRowLabelCell(coords)) - return m_rowLabelWin; - if (IsColLabelCell(coords)) - return m_colLabelWin; - if (IsCornerLabelCell(coords)) - return m_cornerLabelWin; + if (IsGridCell(coords)) { + return m_gridWin; + } + if (IsRowLabelCell(coords)) { + return m_rowLabelWin; + } + if (IsColLabelCell(coords)) { + return m_colLabelWin; + } + if (IsCornerLabelCell(coords)) { + return m_cornerLabelWin; + } - wxFAIL_MSG(wxString::Format(wxT("Unable to get window for coords (%d,%d)"), coords.m_row, coords.m_col)); - return NULL; + wxFAIL_MSG(wxString::Format(wxT("Unable to get window for coords (%d,%d)"), coords.m_row, + coords.m_col)); + return NULL; } // ----- event handlers // Generate a grid event based on a mouse/key event and // return the result of ProcessEvent() -int wxSheet::SendEvent( const wxEventType type, const wxSheetCoords& coords, - wxEvent *mouseOrKeyEvt ) +int wxSheet::SendEvent(const wxEventType type, const wxSheetCoords &coords, wxEvent *mouseOrKeyEvt) { - //wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvt, wxMouseEvent); - //wxPoint pos = mouseEvt ? mouseEvt->GetPosition() : wxPoint(-1, -1); - //pos += wxPoint(GetRowLabelWidth(), GetColLabelHeight()); + // wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvt, wxMouseEvent); + // wxPoint pos = mouseEvt ? mouseEvt->GetPosition() : wxPoint(-1, -1); + // pos += wxPoint(GetRowLabelWidth(), GetColLabelHeight()); - wxSheetEvent sheetEvt(GetId(), type, this, coords, wxPoint(-1,-1), IsSelecting()); - sheetEvt.SetKeysDownMousePos(mouseOrKeyEvt); - return DoSendEvent(&sheetEvt); + wxSheetEvent sheetEvt(GetId(), type, this, coords, wxPoint(-1, -1), IsSelecting()); + sheetEvt.SetKeysDownMousePos(mouseOrKeyEvt); + return DoSendEvent(&sheetEvt); } -int wxSheet::SendRangeEvent( const wxEventType type, const wxSheetBlock& block, - bool selecting, bool add, wxEvent *mouseOrKeyEvt ) +int wxSheet::SendRangeEvent(const wxEventType type, const wxSheetBlock &block, bool selecting, + bool add, wxEvent *mouseOrKeyEvt) { - if ( type == wxEVT_SHEET_RANGE_SELECTED ) - { - wxSheetRangeSelectEvent sheetEvt(GetId(), type, this, block, selecting, add ); + if (type == wxEVT_SHEET_RANGE_SELECTED) { + wxSheetRangeSelectEvent sheetEvt(GetId(), type, this, block, selecting, add); - sheetEvt.SetKeysDownMousePos(mouseOrKeyEvt); - sheetEvt.m_coords = GetGridCursorCell(); - return DoSendEvent(&sheetEvt); - } + sheetEvt.SetKeysDownMousePos(mouseOrKeyEvt); + sheetEvt.m_coords = GetGridCursorCell(); + return DoSendEvent(&sheetEvt); + } - return 0; + return 0; } int wxSheet::DoSendEvent(wxSheetEvent *event) { - wxCHECK_MSG(event, 0, wxT("invalid event in wxSheet::DoSendEvent")); - bool claimed = GetEventHandler()->ProcessEvent(*event); - bool vetoed = !event->IsAllowed(); + wxCHECK_MSG(event, 0, wxT("invalid event in wxSheet::DoSendEvent")); + bool claimed = GetEventHandler()->ProcessEvent(*event); + bool vetoed = !event->IsAllowed(); - // A Veto'd event may not be claimed, test this first - if (vetoed) return EVT_VETOED; - return claimed ? EVT_CLAIMED : EVT_SKIPPED; + // A Veto'd event may not be claimed, test this first + if (vetoed) { + return EVT_VETOED; + } + return claimed ? EVT_CLAIMED : EVT_SKIPPED; } -void wxSheet::HighlightSelectingBlock( const wxSheetBlock &block_ ) +void wxSheet::HighlightSelectingBlock(const wxSheetBlock &block_) { - wxSheetBlock block(block_.GetAligned()); + wxSheetBlock block(block_.GetAligned()); - if (block == GetSelectingBlock()) - return; + if (block == GetSelectingBlock()) { + return; + } - if ( GetSelection() && !block.IsEmpty() ) - { - // make sure block that's selected goes full width/height - if ( HasSelectionMode(wxSHEET_SelectRows) ) - { - block.SetLeft(0); - block.SetWidth(GetNumberCols() - 1); - } - else if ( HasSelectionMode(wxSHEET_SelectCols) ) - { - block.SetTop(0); - block.SetHeight(GetNumberRows() - 1); - } + if (GetSelection() && !block.IsEmpty()) { + // make sure block that's selected goes full width/height + if (HasSelectionMode(wxSHEET_SelectRows)) { + block.SetLeft(0); + block.SetWidth(GetNumberCols() - 1); + } + else if (HasSelectionMode(wxSHEET_SelectCols)) { + block.SetTop(0); + block.SetHeight(GetNumberRows() - 1); } + } - wxSheetBlock oldSelBlock(GetSelectingBlock()); - SetSelectingBlock(block.IsEmpty() ? wxNullSheetBlock : block); + wxSheetBlock oldSelBlock(GetSelectingBlock()); + SetSelectingBlock(block.IsEmpty() ? wxNullSheetBlock : block); - // First the case that we selected a completely new area - if ( oldSelBlock.IsEmpty() ) - { - RefreshGridCellBlock(block); - } - // New selection is empty, erase old one - else if ( block.IsEmpty() ) - { - RefreshGridCellBlock(oldSelBlock); - } - // two selections don't intersect at all, not expected, but ok I guess - else if ( !block.Intersects(oldSelBlock) ) - { - RefreshGridCellBlock(block.Union(oldSelBlock)); - } - // Now handle changing an existing selection area. - else if ( oldSelBlock != block ) - { - // FIXME - this is not great - wxSheetBlock changed[8]; - wxSheetBlock bounds; + // First the case that we selected a completely new area + if (oldSelBlock.IsEmpty()) { + RefreshGridCellBlock(block); + } + // New selection is empty, erase old one + else if (block.IsEmpty()) { + RefreshGridCellBlock(oldSelBlock); + } + // two selections don't intersect at all, not expected, but ok I guess + else if (!block.Intersects(oldSelBlock)) { + RefreshGridCellBlock(block.Union(oldSelBlock)); + } + // Now handle changing an existing selection area. + else if (oldSelBlock != block) { + // FIXME - this is not great + wxSheetBlock changed[8]; + wxSheetBlock bounds; - oldSelBlock.Delete(block, changed[0], changed[1], changed[2], changed[3]); - block.Delete(oldSelBlock, changed[4], changed[5], changed[6], changed[7]); + oldSelBlock.Delete(block, changed[0], changed[1], changed[2], changed[3]); + block.Delete(oldSelBlock, changed[4], changed[5], changed[6], changed[7]); - { - for (int n=0; n<8; n++) - bounds = bounds.ExpandUnion(changed[n]); + { + for (int n = 0; n < 8; n++) { + bounds = bounds.ExpandUnion(changed[n]); + } - RefreshGridCellBlock(bounds); - } + RefreshGridCellBlock(bounds); } + } } // ------ functions to get/send data (see also public functions) bool wxSheet::GetModelValues() { - // Hide the editor, so it won't hide a changed value. - if (IsCellEditControlShown()) - HideCellEditControl(); + // Hide the editor, so it won't hide a changed value. + if (IsCellEditControlShown()) { + HideCellEditControl(); + } - if ( GetTable() ) - { - RefreshGridWindow(); // all we need to do is repaint the grid - return true; - } + if (GetTable()) { + RefreshGridWindow(); // all we need to do is repaint the grid + return true; + } - return false; + return false; } bool wxSheet::SetModelValues() { - // Disable the editor, so it won't hide a changed value. - // FIXME: Do we also want to save the current value of the editor first? yes? - if (IsCellEditControlCreated()) - DisableCellEditControl(true); - - if ( GetTable() ) - { - wxSheetCoords coords; - int numRows = GetNumberRows(); - int numCols = GetNumberCols(); - for ( coords.m_row = 0; coords.m_row < numRows; coords.m_row++ ) - { - for ( coords.m_col = 0; coords.m_col < numCols; coords.m_col++ ) - GetTable()->SetValue( coords, GetCellValue(coords) ); - } + // Disable the editor, so it won't hide a changed value. + // FIXME: Do we also want to save the current value of the editor first? yes? + if (IsCellEditControlCreated()) { + DisableCellEditControl(true); + } - return true; + if (GetTable()) { + wxSheetCoords coords; + int numRows = GetNumberRows(); + int numCols = GetNumberCols(); + for (coords.m_row = 0; coords.m_row < numRows; coords.m_row++) { + for (coords.m_col = 0; coords.m_col < numCols; coords.m_col++) { + GetTable()->SetValue(coords, GetCellValue(coords)); + } } - return false; + return true; + } + + return false; } // ---------------------------------------------------------------------------- @@ -6678,44 +6728,41 @@ bool wxSheet::SetModelValues() void wxSheet::ClearAttrCache() { - if ( m_cacheAttrType != -1 ) - { - m_cacheAttr.Destroy(); - m_cacheAttrCoords = wxNullSheetCoords; - m_cacheAttrType = -1; - } + if (m_cacheAttrType != -1) { + m_cacheAttr.Destroy(); + m_cacheAttrCoords = wxNullSheetCoords; + m_cacheAttrType = -1; + } } -void wxSheet::CacheAttr(const wxSheetCoords& coords, const wxSheetCellAttr &attr, - wxSheetAttr_Type type ) const +void wxSheet::CacheAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr, + wxSheetAttr_Type type) const { - if ( attr.Ok() ) - { - wxSheet *self = (wxSheet *)this; // const_cast - self->m_cacheAttr = attr; - self->m_cacheAttrCoords = coords; - self->m_cacheAttrType = type; - } + if (attr.Ok()) { + wxSheet *self = (wxSheet *)this; // const_cast + self->m_cacheAttr = attr; + self->m_cacheAttrCoords = coords; + self->m_cacheAttrType = type; + } } -bool wxSheet::LookupAttr(const wxSheetCoords& coords, wxSheetAttr_Type type, - wxSheetCellAttr &attr ) const +bool wxSheet::LookupAttr(const wxSheetCoords &coords, wxSheetAttr_Type type, + wxSheetCellAttr &attr) const { - if ( (type == m_cacheAttrType) && (coords == m_cacheAttrCoords) ) - { - attr = m_cacheAttr; + if ((type == m_cacheAttrType) && (coords == m_cacheAttrCoords)) { + attr = m_cacheAttr; #ifdef DEBUG_ATTR_CACHE - gs_nAttrCacheHits++; + gs_nAttrCacheHits++; #endif - return true; - } + return true; + } #ifdef DEBUG_ATTR_CACHE - gs_nAttrCacheMisses++; + gs_nAttrCacheMisses++; #endif - return false; + return false; } // ---------------------------------------------------------------------------- @@ -6723,161 +6770,175 @@ bool wxSheet::LookupAttr(const wxSheetCoords& coords, wxSheetAttr_Type type, void wxSheet::CalcWindowSizes(bool adjustScrollBars) { - if (!m_gridWin || m_resizing) - return; - - if (adjustScrollBars) - AdjustScrollbars(false); - - m_resizing = true; - - int cw, ch; - GetClientSize( &cw, &ch ); - wxRect rect; - - const int rowLabelWidth = GetRowLabelWidth(); - const int colLabelHeight = GetColLabelHeight(); - int sb_width = m_vertScrollBar->GetSize().x; - int sb_height = m_horizScrollBar->GetSize().y; - bool horiz_sb = m_horizScrollBar->IsShown(); - bool vert_sb = m_vertScrollBar->IsShown(); - if (horiz_sb) ch -= sb_width; - if (vert_sb ) cw -= sb_width; - - bool horiz_splitter = horiz_sb && m_enable_split_horiz; - bool vert_splitter = vert_sb && m_enable_split_vert; - - if ( horiz_sb ) - { - rect = wxRect(0, ch, cw, sb_height); - if (horiz_splitter) - { - rect.width -= SPLIT_BUTTON_WIDTH; - m_horizSplitRect = wxRect(rect.GetRight(), rect.GetTop(), SPLIT_BUTTON_WIDTH, rect.GetHeight()); - } - else - m_horizSplitRect = wxRect(0,0,0,0); - - if (rect != m_horizScrollBar->GetRect()) - m_horizScrollBar->SetSize( rect ); - } - if ( vert_sb ) - { - rect = wxRect(cw, 0, sb_width, ch); - if (vert_splitter) - { - rect.height -= SPLIT_BUTTON_WIDTH; - m_vertSplitRect = wxRect(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), SPLIT_BUTTON_WIDTH); - rect.y += SPLIT_BUTTON_WIDTH; - } - else - m_vertSplitRect = wxRect(0,0,0,0); - - if (rect != m_vertScrollBar->GetRect()) - m_vertScrollBar->SetSize( rect ); - } - if ( m_cornerLabelWin->IsShown() ) - { - rect = wxRect(0, 0, rowLabelWidth, colLabelHeight); - if (rect != m_cornerLabelWin->GetRect()) - m_cornerLabelWin->SetSize( rect ); - } - if ( m_colLabelWin->IsShown() ) - { - rect = wxRect(rowLabelWidth, 0, cw-rowLabelWidth, colLabelHeight); - if (rect != m_colLabelWin->GetRect()) - m_colLabelWin->SetSize( rect ); - } - if ( m_rowLabelWin->IsShown() ) - { - rect = wxRect(0, colLabelHeight, rowLabelWidth, ch-colLabelHeight); - if (rect != m_rowLabelWin->GetRect()) - m_rowLabelWin->SetSize( rect ); - } - if ( m_gridWin->IsShown() ) - { - rect = wxRect(rowLabelWidth, colLabelHeight, cw-rowLabelWidth, ch-colLabelHeight); - if (rect != m_gridWin->GetRect()) - m_gridWin->SetSize( rect ); - - //PRINT_RECT("Set grid rect ", rect); - //PRINT_RECT("Get grid rect ", wxRect(wxPoint(0,0), m_gridWin->GetSize())); - } - - m_resizing = false; + if (!m_gridWin || m_resizing) { + return; + } + + if (adjustScrollBars) { + AdjustScrollbars(false); + } + + m_resizing = true; + + int cw, ch; + GetClientSize(&cw, &ch); + wxRect rect; + + const int rowLabelWidth = GetRowLabelWidth(); + const int colLabelHeight = GetColLabelHeight(); + int sb_width = m_vertScrollBar->GetSize().x; + int sb_height = m_horizScrollBar->GetSize().y; + bool horiz_sb = m_horizScrollBar->IsShown(); + bool vert_sb = m_vertScrollBar->IsShown(); + if (horiz_sb) { + ch -= sb_width; + } + if (vert_sb) { + cw -= sb_width; + } + + bool horiz_splitter = horiz_sb && m_enable_split_horiz; + bool vert_splitter = vert_sb && m_enable_split_vert; + + if (horiz_sb) { + rect = wxRect(0, ch, cw, sb_height); + if (horiz_splitter) { + rect.width -= SPLIT_BUTTON_WIDTH; + m_horizSplitRect = + wxRect(rect.GetRight(), rect.GetTop(), SPLIT_BUTTON_WIDTH, rect.GetHeight()); + } + else { + m_horizSplitRect = wxRect(0, 0, 0, 0); + } + + if (rect != m_horizScrollBar->GetRect()) { + m_horizScrollBar->SetSize(rect); + } + } + if (vert_sb) { + rect = wxRect(cw, 0, sb_width, ch); + if (vert_splitter) { + rect.height -= SPLIT_BUTTON_WIDTH; + m_vertSplitRect = wxRect(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), SPLIT_BUTTON_WIDTH); + rect.y += SPLIT_BUTTON_WIDTH; + } + else { + m_vertSplitRect = wxRect(0, 0, 0, 0); + } + + if (rect != m_vertScrollBar->GetRect()) { + m_vertScrollBar->SetSize(rect); + } + } + if (m_cornerLabelWin->IsShown()) { + rect = wxRect(0, 0, rowLabelWidth, colLabelHeight); + if (rect != m_cornerLabelWin->GetRect()) { + m_cornerLabelWin->SetSize(rect); + } + } + if (m_colLabelWin->IsShown()) { + rect = wxRect(rowLabelWidth, 0, cw - rowLabelWidth, colLabelHeight); + if (rect != m_colLabelWin->GetRect()) { + m_colLabelWin->SetSize(rect); + } + } + if (m_rowLabelWin->IsShown()) { + rect = wxRect(0, colLabelHeight, rowLabelWidth, ch - colLabelHeight); + if (rect != m_rowLabelWin->GetRect()) { + m_rowLabelWin->SetSize(rect); + } + } + if (m_gridWin->IsShown()) { + rect = wxRect(rowLabelWidth, colLabelHeight, cw - rowLabelWidth, ch - colLabelHeight); + if (rect != m_gridWin->GetRect()) { + m_gridWin->SetSize(rect); + } + + // PRINT_RECT("Set grid rect ", rect); + // PRINT_RECT("Get grid rect ", wxRect(wxPoint(0,0), m_gridWin->GetSize())); + } + + m_resizing = false; #ifdef __WXMSW__ - // MSW at least needs a little help making sure that the corner and - // the splitter rects get painted - wxClientDC dc(this); - PaintSheetWindow(dc, wxRect(0, 0, cw, ch)); + // MSW at least needs a little help making sure that the corner and + // the splitter rects get painted + wxClientDC dc(this); + PaintSheetWindow(dc, wxRect(0, 0, cw, ch)); #endif // __WXMSW__ } -void wxSheet::OnSize(wxSizeEvent& event) +void wxSheet::OnSize(wxSizeEvent &event) { - //PRINT_RECT(wxT("SheetRect"), GetRect()); - CalcWindowSizes(true); - SetGridOrigin(m_gridOrigin.x, m_gridOrigin.y, true, true); - SetEqualColWidths(GetSheetRefData()->m_equal_col_widths); + // PRINT_RECT(wxT("SheetRect"), GetRect()); + CalcWindowSizes(true); + SetGridOrigin(m_gridOrigin.x, m_gridOrigin.y, true, true); + SetEqualColWidths(GetSheetRefData()->m_equal_col_widths); - event.Skip(); + event.Skip(); } wxSize wxSheet::DoGetBestSize() const { - wxSize displaySize(wxGetClientDisplayRect().GetSize()); - wxSize size(GetGridVirtualSize(true)); - size.x += GetRowLabelWidth(); - size.y += GetColLabelHeight(); + wxSize displaySize(wxGetClientDisplayRect().GetSize()); + wxSize size(GetGridVirtualSize(true)); + size.x += GetRowLabelWidth(); + size.y += GetColLabelHeight(); - if ( size.x > displaySize.x/2 ) size.x = displaySize.x/2; - if ( size.y > displaySize.y/2 ) size.y = displaySize.y/2; + if (size.x > displaySize.x / 2) { + size.x = displaySize.x / 2; + } + if (size.y > displaySize.y / 2) { + size.y = displaySize.y / 2; + } - // NOTE: This size should be cached, but first we need to add calls to - // InvalidateBestSize everywhere that could change the results of this - // calculation. - // CacheBestSize(size); + // NOTE: This size should be cached, but first we need to add calls to + // InvalidateBestSize everywhere that could change the results of this + // calculation. + // CacheBestSize(size); - return size; + return size; } int wxSheet::GetKeyModifiers(wxEvent *mouseOrKeyEvent) const { - // In GTK meta is the numLock key - int mods = NO_MODIFIERS; - wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvent, wxMouseEvent); + // In GTK meta is the numLock key + int mods = NO_MODIFIERS; + wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvent, wxMouseEvent); - if (mouseEvt) - { - if (mouseEvt->ControlDown()) - mods |= CTRL_DOWN; - if (mouseEvt->ShiftDown()) - mods |= SHIFT_DOWN; - if (mouseEvt->AltDown()) - mods |= ALT_DOWN; - //if (mouseEvt->MetaDown()) // meta is numlock in GTK - // mods |= META_DOWN; + if (mouseEvt) { + if (mouseEvt->ControlDown()) { + mods |= CTRL_DOWN; } - else - { - wxKeyEvent *keyEvt = wxDynamicCast(mouseOrKeyEvent, wxKeyEvent); - if (keyEvt) - { - if (keyEvt->ControlDown()) - mods |= CTRL_DOWN; - if (keyEvt->ShiftDown()) - mods |= SHIFT_DOWN; - if (keyEvt->AltDown()) - mods |= ALT_DOWN; - //if (keyEvt->MetaDown()) - // mods |= META_DOWN; - } + if (mouseEvt->ShiftDown()) { + mods |= SHIFT_DOWN; } + if (mouseEvt->AltDown()) { + mods |= ALT_DOWN; + } + // if (mouseEvt->MetaDown()) // meta is numlock in GTK + // mods |= META_DOWN; + } + else { + wxKeyEvent *keyEvt = wxDynamicCast(mouseOrKeyEvent, wxKeyEvent); + if (keyEvt) { + if (keyEvt->ControlDown()) { + mods |= CTRL_DOWN; + } + if (keyEvt->ShiftDown()) { + mods |= SHIFT_DOWN; + } + if (keyEvt->AltDown()) { + mods |= ALT_DOWN; + } + // if (keyEvt->MetaDown()) + // mods |= META_DOWN; + } + } - //wxPrintf("Mods c%d s%d a%d m%d, %d\n", CTRL_DOWN, SHIFT_DOWN, ALT_DOWN, META_DOWN, mods); + // wxPrintf("Mods c%d s%d a%d m%d, %d\n", CTRL_DOWN, SHIFT_DOWN, ALT_DOWN, META_DOWN, mods); - return mods; + return mods; } // ---------------------------------------------------------------------------- @@ -6912,68 +6973,66 @@ DEFINE_EVENT_TYPE(wxEVT_SHEET_EDITOR_CREATED) // ---------------------------------------------------------------------------- // wxSheetEvent // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( wxSheetEvent, wxNotifyEvent ) +IMPLEMENT_DYNAMIC_CLASS(wxSheetEvent, wxNotifyEvent) -wxSheetEvent::wxSheetEvent(int id, wxEventType type, wxObject* obj, - const wxSheetCoords& coords, const wxPoint &pos, - bool sel ) - : wxNotifyEvent(type, id), m_coords(coords), m_pos(pos), m_selecting(sel), - m_control(false), m_shift(false), m_alt(false), m_meta(false) +wxSheetEvent::wxSheetEvent(int id, wxEventType type, wxObject *obj, const wxSheetCoords &coords, + const wxPoint &pos, bool sel) + : wxNotifyEvent(type, id), m_coords(coords), m_pos(pos), m_selecting(sel), m_control(false), + m_shift(false), m_alt(false), m_meta(false) { - SetEventObject(obj); + SetEventObject(obj); } void wxSheetEvent::SetKeysDownMousePos(wxEvent *mouseOrKeyEvent) { - wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvent, wxMouseEvent); - if (mouseEvt) - { - m_control = mouseEvt->ControlDown(); - m_shift = mouseEvt->ShiftDown(); - m_alt = mouseEvt->AltDown(); - m_meta = mouseEvt->MetaDown(); - m_pos = mouseEvt->GetPosition(); - } - else - { - wxKeyEvent *keyEvt = wxDynamicCast(mouseOrKeyEvent, wxKeyEvent); - if (keyEvt) - { - m_control = keyEvt->ControlDown(); - m_shift = keyEvt->ShiftDown(); - m_alt = keyEvt->AltDown(); - m_meta = keyEvt->MetaDown(); - m_pos = keyEvt->GetPosition(); - } - else - return; // neither mouse nor key event - } - - // FIXME - do I really want to scroll the position? or leave it as is - // we've set the position from the event, now scroll it - wxSheet *sheet = wxDynamicCast(GetEventObject(), wxSheet); - wxWindow *win = wxDynamicCast(mouseOrKeyEvent->GetEventObject(), wxWindow); - if (sheet && win) - { - if ( win == sheet->GetGridWindow()) - m_pos = sheet->CalcUnscrolledPosition(m_pos); - else if (win == sheet->GetRowLabelWindow()) - sheet->CalcUnscrolledPosition(0, m_pos.y, NULL, &m_pos.y); - else if (win == sheet->GetColLabelWindow()) - sheet->CalcUnscrolledPosition(m_pos.x, 0, &m_pos.x, NULL); - } + wxMouseEvent *mouseEvt = wxDynamicCast(mouseOrKeyEvent, wxMouseEvent); + if (mouseEvt) { + m_control = mouseEvt->ControlDown(); + m_shift = mouseEvt->ShiftDown(); + m_alt = mouseEvt->AltDown(); + m_meta = mouseEvt->MetaDown(); + m_pos = mouseEvt->GetPosition(); + } + else { + wxKeyEvent *keyEvt = wxDynamicCast(mouseOrKeyEvent, wxKeyEvent); + if (keyEvt) { + m_control = keyEvt->ControlDown(); + m_shift = keyEvt->ShiftDown(); + m_alt = keyEvt->AltDown(); + m_meta = keyEvt->MetaDown(); + m_pos = keyEvt->GetPosition(); + } + else { + return; // neither mouse nor key event + } + } + + // FIXME - do I really want to scroll the position? or leave it as is + // we've set the position from the event, now scroll it + wxSheet *sheet = wxDynamicCast(GetEventObject(), wxSheet); + wxWindow *win = wxDynamicCast(mouseOrKeyEvent->GetEventObject(), wxWindow); + if (sheet && win) { + if (win == sheet->GetGridWindow()) { + m_pos = sheet->CalcUnscrolledPosition(m_pos); + } + else if (win == sheet->GetRowLabelWindow()) { + sheet->CalcUnscrolledPosition(0, m_pos.y, NULL, &m_pos.y); + } + else if (win == sheet->GetColLabelWindow()) { + sheet->CalcUnscrolledPosition(m_pos.x, 0, &m_pos.x, NULL); + } + } } // ---------------------------------------------------------------------------- // wxSheetRangeSelectEvent // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( wxSheetRangeSelectEvent, wxSheetEvent ) +IMPLEMENT_DYNAMIC_CLASS(wxSheetRangeSelectEvent, wxSheetEvent) -wxSheetRangeSelectEvent::wxSheetRangeSelectEvent(int id, wxEventType type, wxObject* obj, - const wxSheetBlock& block, - bool sel, bool add ) - : wxSheetEvent(id, type, obj, wxNullSheetCoords, wxPoint(-1, -1), sel), - m_block(block), m_add(add) +wxSheetRangeSelectEvent::wxSheetRangeSelectEvent(int id, wxEventType type, wxObject *obj, + const wxSheetBlock &block, bool sel, bool add) + : wxSheetEvent(id, type, obj, wxNullSheetCoords, wxPoint(-1, -1), sel), m_block(block), + m_add(add) { } @@ -6982,16 +7041,13 @@ wxSheetRangeSelectEvent::wxSheetRangeSelectEvent(int id, wxEventType type, wxObj // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxSheetEditorCreatedEvent, wxCommandEvent) -wxSheetEditorCreatedEvent::wxSheetEditorCreatedEvent(int id, wxEventType type, - wxObject* obj, - const wxSheetCoords& coords, - wxWindow* ctrl) - : wxCommandEvent(type, id), m_coords(coords), m_ctrl(ctrl) +wxSheetEditorCreatedEvent::wxSheetEditorCreatedEvent(int id, wxEventType type, wxObject *obj, + const wxSheetCoords &coords, wxWindow *ctrl) + : wxCommandEvent(type, id), m_coords(coords), m_ctrl(ctrl) { - SetEventObject(obj); + SetEventObject(obj); } - // Notes: // Regex to CSV // http://dotnetjunkies.com/WebLog/chris.taylor/archive/2004/04/09/11039.aspx @@ -7027,116 +7083,139 @@ End Function #include "wx/regex.h" +class wxCSV_IO { +public: + wxCSV_IO(bool t = false); + wxArrayString ParseLine(const wxString &line); + bool Test(); -class wxCSV_IO -{ -public : - wxCSV_IO( bool t=false ); - - - wxArrayString ParseLine(const wxString& line); - bool Test(); - - wxRegEx m_regex; + wxRegEx m_regex; }; wxCSV_IO::wxCSV_IO(bool t) { + // "(\s*""[^""]*""\s*,)|(\s*[^,]*\s*,)" 'The magic... + // m_regex.Compile(wxT("(\\s*\"[^\"]*\"\\s*,)|(\\s*[^,]*\\s*,)"), wxRE_ICASE); + m_regex.Compile(wxT("(\\s*\"[^\"]*\"\\s*,)|(\\s*[^,]*\\s*,)"), wxRE_ICASE); + // m_regex.Compile(wxT(",(?=([^\"]*"[^\"]*\")*(?![^\"]*\"))"), wxRE_ICASE); + // m_regex.Compile(wxT(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"), wxRE_ICASE); -// "(\s*""[^""]*""\s*,)|(\s*[^,]*\s*,)" 'The magic... -// m_regex.Compile(wxT("(\\s*\"[^\"]*\"\\s*,)|(\\s*[^,]*\\s*,)"), wxRE_ICASE); - m_regex.Compile(wxT("(\\s*\"[^\"]*\"\\s*,)|(\\s*[^,]*\\s*,)"), wxRE_ICASE); - //m_regex.Compile(wxT(",(?=([^\"]*"[^\"]*\")*(?![^\"]*\"))"), wxRE_ICASE); - //m_regex.Compile(wxT(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"), wxRE_ICASE); - - if (t) Test(); + if (t) { + Test(); + } } -wxArrayString wxCSV_IO::ParseLine(const wxString& line_) +wxArrayString wxCSV_IO::ParseLine(const wxString &line_) { - wxArrayString values; - wxString line(line_ + wxT(",")); // add trailing ',' for "a,b" case - - // See if there is a match at all - while ( m_regex.Matches(line) ) - { - // Get the first match (BUG? can't use GetMatch(line, n)) - wxString val(m_regex.GetMatch(line, 0)); - size_t len = val.Length(); - if ((len > 0u) && val.Last() == wxT(',')) // GetMatch returns "val," - val = val.Mid(0, len-1); - - //wxPrintf(wxT("VALUE '")+val+wxT("' LINE '")+line+wxT("'\n")); + wxArrayString values; + wxString line(line_ + wxT(",")); // add trailing ',' for "a,b" case - line = line.Mid(len); // remove the value from the line - val = val.Strip(wxString::both); // strip blank spaces from value - // should've quoted ie. " a a " - len = val.Length(); - // remove the leading and trailing quotes - if ((len > 1u) && (val.GetChar(0) == wxT('\"')) && (val.GetChar(len-1) == wxT('\"'))) - val = val.AfterFirst(wxT('\"')).BeforeLast(wxT('\"')); - - values.Add(val); + // See if there is a match at all + while (m_regex.Matches(line)) { + // Get the first match (BUG? can't use GetMatch(line, n)) + wxString val(m_regex.GetMatch(line, 0)); + size_t len = val.Length(); + if ((len > 0u) && val.Last() == wxT(',')) { // GetMatch returns "val," + val = val.Mid(0, len - 1); } - return values; -} + // wxPrintf(wxT("VALUE '")+val+wxT("' LINE '")+line+wxT("'\n")); + line = line.Mid(len); // remove the value from the line + val = val.Strip(wxString::both); // strip blank spaces from value + // should've quoted ie. " a a " + len = val.Length(); + // remove the leading and trailing quotes + if ((len > 1u) && (val.GetChar(0) == wxT('\"')) && (val.GetChar(len - 1) == wxT('\"'))) { + val = val.AfterFirst(wxT('\"')).BeforeLast(wxT('\"')); + } -wxString Joint(const wxArrayString& a) -{ - if (a.GetCount() == 0u) return wxEmptyString; + values.Add(val); + } - wxString s = wxT("'")+ a[0] + wxT("'\t "); - for (size_t n = 1u; n < a.GetCount(); n++) s += wxT("'")+ a[n] + wxT("'\t "); - return s; + return values; } -void CSV_TEST(const wxString& instr, const wxArrayString& ans, const wxArrayString &res) +wxString Joint(const wxArrayString &a) { - wxString msg(wxT("'") + instr + wxT("'\t ") + Joint(ans) + wxT(" ** \t ") + Joint(res)); - - if ( ans.GetCount() != res.GetCount() ) - wxPrintf(wxT("COUNT MISMATCH ERROR! \n")); - - for (size_t n = 0; n < wxMin(ans.GetCount(), res.GetCount()); n++) - if (ans[n] != res[n]) wxPrintf(wxT("Error in item %u\n"), n); - - wxPrintf(msg + wxT("\n")); -} - -#define CSVT1(str, a1) { wxArrayString ar; ar.Add(wxT(a1)); CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); } -#define CSVT2(str, a1, a2) { wxArrayString ar; ar.Add(wxT(a1)); ar.Add(wxT(a2)); CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); } -#define CSVT3(str, a1, a2, a3) { wxArrayString ar; ar.Add(wxT(a1)); ar.Add(wxT(a2)); ar.Add(wxT(a3)); CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); } + if (a.GetCount() == 0u) { + return wxEmptyString; + } + + wxString s = wxT("'") + a[0] + wxT("'\t "); + for (size_t n = 1u; n < a.GetCount(); n++) { + s += wxT("'") + a[n] + wxT("'\t "); + } + return s; +} + +void CSV_TEST(const wxString &instr, const wxArrayString &ans, const wxArrayString &res) +{ + wxString msg(wxT("'") + instr + wxT("'\t ") + Joint(ans) + wxT(" ** \t ") + Joint(res)); + + if (ans.GetCount() != res.GetCount()) { + wxPrintf(wxT("COUNT MISMATCH ERROR! \n")); + } + + for (size_t n = 0; n < wxMin(ans.GetCount(), res.GetCount()); n++) { + if (ans[n] != res[n]) { + wxPrintf(wxT("Error in item %u\n"), n); + } + } + + wxPrintf(msg + wxT("\n")); +} + +#define CSVT1(str, a1) \ + { \ + wxArrayString ar; \ + ar.Add(wxT(a1)); \ + CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); \ + } +#define CSVT2(str, a1, a2) \ + { \ + wxArrayString ar; \ + ar.Add(wxT(a1)); \ + ar.Add(wxT(a2)); \ + CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); \ + } +#define CSVT3(str, a1, a2, a3) \ + { \ + wxArrayString ar; \ + ar.Add(wxT(a1)); \ + ar.Add(wxT(a2)); \ + ar.Add(wxT(a3)); \ + CSV_TEST(wxT(str), ar, ParseLine(wxT(str))); \ + } bool wxCSV_IO::Test() { - CSVT3("a,b,c", "a", "b", "c") - CSVT3("\"a\",b,c", "a", "b", "c") - CSVT3("'a',b,c", "'a'", "b", "c") - CSVT3(" a , b , c ", "a", "b", "c") - CSVT2("aa,bb;cc", "aa", "bb;cc") - CSVT1("", "") - CSVT1("a", "a") - CSVT3(",b,", "", "b", "") - CSVT3(",,c", "", "", "c") - CSVT3(",,", "", "", "") - CSVT2("\"\",b", "", "b") - CSVT2("\" \",b", " ", "b") - CSVT1("\"a,b\"", "a,b") - CSVT2("\"a,b\",c", "a,b", "c") - CSVT2("\" a , b \", c", " a , b ", "c") - CSVT2("a b,c", "a b", "c") - CSVT2("a\"b,c", "a\"b", "c") - CSVT2("\"a\"\"b\",c", "a\"b", "c") - CSVT2("a\"\"b,c", "a\"\"b", "c") // BROKEN - CSVT3("a,b\",c", "a", "b\"", "c") - CSVT3("a,b\"\",c", "a", "b\"\"", "c") - CSVT3("a,\"B: \"\"Hi, I'm B\"\"\",c", "a", "B: \"Hi, I'm B\"", "c") - - return true; -} - -//wxCSV_IO csvTest(true); + CSVT3("a,b,c", "a", "b", "c") + CSVT3("\"a\",b,c", "a", "b", "c") + CSVT3("'a',b,c", "'a'", "b", "c") + CSVT3(" a , b , c ", "a", "b", "c") + CSVT2("aa,bb;cc", "aa", "bb;cc") + CSVT1("", "") + CSVT1("a", "a") + CSVT3(",b,", "", "b", "") + CSVT3(",,c", "", "", "c") + CSVT3(",,", "", "", "") + CSVT2("\"\",b", "", "b") + CSVT2("\" \",b", " ", "b") + CSVT1("\"a,b\"", "a,b") + CSVT2("\"a,b\",c", "a,b", "c") + CSVT2("\" a , b \", c", " a , b ", "c") + CSVT2("a b,c", "a b", "c") + CSVT2("a\"b,c", "a\"b", "c") + CSVT2("\"a\"\"b\",c", "a\"b", "c") + CSVT2("a\"\"b,c", "a\"\"b", "c") // BROKEN + CSVT3("a,b\",c", "a", "b\"", "c") + CSVT3("a,b\"\",c", "a", "b\"\"", "c") + CSVT3("a,\"B: \"\"Hi, I'm B\"\"\",c", "a", "B: \"Hi, I'm B\"", "c") + + return true; +} + +// wxCSV_IO csvTest(true); diff --git a/src/labenski/src/sheetatr.cpp b/src/labenski/src/sheetatr.cpp index a8cb9c6d3..491b213e1 100644 --- a/src/labenski/src/sheetatr.cpp +++ b/src/labenski/src/sheetatr.cpp @@ -13,7 +13,7 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #include "wx/sheet/sheetatr.h" @@ -22,8 +22,12 @@ #ifndef WX_PRECOMP #endif // WX_PRECOMP -#define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); -#define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_BLOCK(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_RECT(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); // ---------------------------------------------------------------------------- // constants @@ -39,33 +43,30 @@ DEFINE_PAIRED_INT_DATA_ARRAYS(wxSheetCellAttr, wxPairArrayIntSheetCellAttr) // ---------------------------------------------------------------------------- // wxSheetCellAttrRefData // ---------------------------------------------------------------------------- -#define M_CELLATTRDATA ((wxSheetCellAttrRefData*)m_refData) +#define M_CELLATTRDATA ((wxSheetCellAttrRefData *)m_refData) wxSheetCellAttrRefData::wxSheetCellAttrRefData() - : wxObjectRefData(), - // other m_attrTypes unset values are 0 - m_attrTypes(wxSHEET_AttrCell|wxSHEET_AttrAlignUnset), - m_renderer(NULL), m_editor(NULL), m_defaultAttr(NULL) + : wxObjectRefData(), + // other m_attrTypes unset values are 0 + m_attrTypes(wxSHEET_AttrCell | wxSHEET_AttrAlignUnset), m_renderer(NULL), m_editor(NULL), + m_defaultAttr(NULL) { } -wxSheetCellAttrRefData::wxSheetCellAttrRefData( const wxSheetCellAttrRefData& data ) - : wxObjectRefData(), - m_foreColour(data.m_foreColour), - m_backColour(data.m_backColour), - m_font(data.m_font), - m_attrTypes(data.m_attrTypes) +wxSheetCellAttrRefData::wxSheetCellAttrRefData(const wxSheetCellAttrRefData &data) + : wxObjectRefData(), m_foreColour(data.m_foreColour), m_backColour(data.m_backColour), + m_font(data.m_font), m_attrTypes(data.m_attrTypes) { - m_renderer = !data.m_renderer ? NULL : new wxSheetCellRenderer(*data.m_renderer); - m_editor = !data.m_editor ? NULL : new wxSheetCellEditor(*data.m_editor); - m_defaultAttr = !data.m_defaultAttr ? NULL : new wxSheetCellAttr(*data.m_defaultAttr); + m_renderer = !data.m_renderer ? NULL : new wxSheetCellRenderer(*data.m_renderer); + m_editor = !data.m_editor ? NULL : new wxSheetCellEditor(*data.m_editor); + m_defaultAttr = !data.m_defaultAttr ? NULL : new wxSheetCellAttr(*data.m_defaultAttr); } wxSheetCellAttrRefData::~wxSheetCellAttrRefData() { - delete m_renderer; - delete m_editor; - delete m_defaultAttr; + delete m_renderer; + delete m_editor; + delete m_defaultAttr; } // ---------------------------------------------------------------------------- @@ -75,383 +76,413 @@ IMPLEMENT_DYNAMIC_CLASS(wxSheetCellAttr, wxObject) wxSheetCellAttr::wxSheetCellAttr(bool create) : wxObject() { - if (create) - m_refData = new wxSheetCellAttrRefData; + if (create) { + m_refData = new wxSheetCellAttrRefData; + } } bool wxSheetCellAttr::Create() { - UnRef(); - m_refData = new wxSheetCellAttrRefData; - return m_refData != NULL; + UnRef(); + m_refData = new wxSheetCellAttrRefData; + return m_refData != NULL; } -wxObjectRefData *wxSheetCellAttr::CreateRefData() const -{ - return new wxSheetCellAttrRefData; -} +wxObjectRefData *wxSheetCellAttr::CreateRefData() const { return new wxSheetCellAttrRefData; } wxObjectRefData *wxSheetCellAttr::CloneRefData(const wxObjectRefData *data) const { - wxCHECK_MSG(data, new wxSheetCellAttrRefData, wxT("Invalid data for CloneRefData")); - return new wxSheetCellAttrRefData(*(const wxSheetCellAttrRefData *)data); + wxCHECK_MSG(data, new wxSheetCellAttrRefData, wxT("Invalid data for CloneRefData")); + return new wxSheetCellAttrRefData(*(const wxSheetCellAttrRefData *)data); } -bool wxSheetCellAttr::Copy(const wxSheetCellAttr& other) +bool wxSheetCellAttr::Copy(const wxSheetCellAttr &other) { - wxCHECK_MSG(other.Ok(), false, wxT("Attr to copy from is not created")); - - if (!Create()) - return false; - - M_CELLATTRDATA->m_foreColour = ((wxSheetCellAttrRefData*)other.GetRefData())->m_foreColour; - M_CELLATTRDATA->m_backColour = ((wxSheetCellAttrRefData*)other.GetRefData())->m_backColour; - M_CELLATTRDATA->m_font = ((wxSheetCellAttrRefData*)other.GetRefData())->m_font; - M_CELLATTRDATA->m_attrTypes = ((wxSheetCellAttrRefData*)other.GetRefData())->m_attrTypes; - if (other.HasEditor()) - SetEditor(((wxSheetCellAttrRefData*)other.m_refData)->m_editor->Clone()); - if (other.HasRenderer()) - SetRenderer(((wxSheetCellAttrRefData*)other.m_refData)->m_renderer->Clone()); + wxCHECK_MSG(other.Ok(), false, wxT("Attr to copy from is not created")); + if (!Create()) { + return false; + } + + M_CELLATTRDATA->m_foreColour = ((wxSheetCellAttrRefData *)other.GetRefData())->m_foreColour; + M_CELLATTRDATA->m_backColour = ((wxSheetCellAttrRefData *)other.GetRefData())->m_backColour; + M_CELLATTRDATA->m_font = ((wxSheetCellAttrRefData *)other.GetRefData())->m_font; + M_CELLATTRDATA->m_attrTypes = ((wxSheetCellAttrRefData *)other.GetRefData())->m_attrTypes; + if (other.HasEditor()) { + SetEditor(((wxSheetCellAttrRefData *)other.m_refData)->m_editor->Clone()); + } + if (other.HasRenderer()) { + SetRenderer(((wxSheetCellAttrRefData *)other.m_refData)->m_renderer->Clone()); + } + + SetDefaultAttr(other.GetDefaultAttr()); + return true; +} + +bool wxSheetCellAttr::UpdateWith(const wxSheetCellAttr &other) +{ + wxCHECK_MSG(Ok() && other.Ok(), false, wxT("this or Attr to UpdateWith from is not created")); + + if (other.HasForegoundColour()) { + SetForegroundColour(other.GetForegroundColour()); + } + if (other.HasBackgroundColour()) { + SetBackgroundColour(other.GetBackgroundColour()); + } + if (other.HasFont()) { + SetFont(other.GetFont()); + } + if (other.HasAlignment()) { + SetAlignment(other.GetAlignment()); + } + if (other.HasOrientation()) { + SetOrientation(other.GetOrientation()); + } + if (other.HasLevel()) { + SetLevel(other.GetLevel()); + } + if (other.HasReadWriteMode()) { + SetReadOnly(other.GetReadOnly()); + } + if (other.HasOverflowMode()) { + SetOverflow(other.GetOverflow()); + } + if (other.HasOverflowMarkerMode()) { + SetOverflowMarker(other.GetOverflowMarker()); + } + if (other.HasShowEditorMode()) { + SetShowEditor(other.GetShowEditor()); + } + + // Directly access m_renderer/m_editor as GetRender/Editor may return different one + + // Maybe add support for merge of Render and Editor? + if (other.HasRenderer()) { + SetRenderer(((wxSheetCellAttrRefData *)other.m_refData)->m_renderer->Clone()); + } + if (other.HasEditor()) { + SetEditor(((wxSheetCellAttrRefData *)other.m_refData)->m_editor->Clone()); + } + + if (other.HasDefaultAttr()) { SetDefaultAttr(other.GetDefaultAttr()); - return true; -} + } -bool wxSheetCellAttr::UpdateWith(const wxSheetCellAttr& other) -{ - wxCHECK_MSG(Ok() && other.Ok(), false, wxT("this or Attr to UpdateWith from is not created")); - - if ( other.HasForegoundColour() ) - SetForegroundColour(other.GetForegroundColour()); - if ( other.HasBackgroundColour() ) - SetBackgroundColour(other.GetBackgroundColour()); - if ( other.HasFont() ) - SetFont(other.GetFont()); - if ( other.HasAlignment() ) - SetAlignment(other.GetAlignment()); - if ( other.HasOrientation() ) - SetOrientation(other.GetOrientation()); - if ( other.HasLevel() ) - SetLevel(other.GetLevel()); - if ( other.HasReadWriteMode() ) - SetReadOnly(other.GetReadOnly()); - if ( other.HasOverflowMode() ) - SetOverflow(other.GetOverflow()); - if ( other.HasOverflowMarkerMode() ) - SetOverflowMarker(other.GetOverflowMarker()); - if ( other.HasShowEditorMode() ) - SetShowEditor(other.GetShowEditor()); - - // Directly access m_renderer/m_editor as GetRender/Editor may return different one - - // Maybe add support for merge of Render and Editor? - if ( other.HasRenderer() ) - SetRenderer(((wxSheetCellAttrRefData*)other.m_refData)->m_renderer->Clone()); - if ( other.HasEditor() ) - SetEditor(((wxSheetCellAttrRefData*)other.m_refData)->m_editor->Clone()); - - if ( other.HasDefaultAttr() ) - SetDefaultAttr(other.GetDefaultAttr()); - - return true; + return true; } bool wxSheetCellAttr::MergeWith(const wxSheetCellAttr &other) { - wxCHECK_MSG(Ok() && other.Ok(), false, wxT("this or Attr to MergeWith from is not created")); - - if ( !HasForegoundColour() && other.HasForegoundColour() ) - SetForegroundColour(other.GetForegroundColour()); - if ( !HasBackgroundColour() && other.HasBackgroundColour() ) - SetBackgroundColour(other.GetBackgroundColour()); - if ( !HasFont() && other.HasFont() ) - SetFont(other.GetFont()); - if ( !HasAlignment() && other.HasAlignment() ) - SetAlignment(other.GetAlignment()); - if ( !HasOrientation() && other.HasOrientation() ) - SetOrientation(other.GetOrientation()); - if ( !HasLevel() && other.HasLevel() ) - SetLevel(other.GetLevel()); - if ( !HasReadWriteMode() && other.HasReadWriteMode() ) - SetReadOnly(other.GetReadOnly()); - if ( !HasOverflowMode() && other.HasOverflowMode() ) - SetOverflow(other.GetOverflow()); - if ( !HasOverflowMarkerMode() && other.HasOverflowMarkerMode() ) - SetOverflowMarker(other.GetOverflowMarker()); - if ( !HasShowEditorMode() && other.HasShowEditorMode() ) - SetShowEditor(other.GetShowEditor()); - - // Directly access m_renderer/m_editor as GetRender/Editor may return different one - - // Maybe add support for merge of Render and Editor? - if ( !HasRenderer() && other.HasRenderer() ) - SetRenderer(((wxSheetCellAttrRefData*)other.m_refData)->m_renderer->Clone()); - if ( !HasEditor() && other.HasEditor() ) - SetEditor(((wxSheetCellAttrRefData*)other.m_refData)->m_editor->Clone()); - - if ( !HasDefaultAttr() && other.HasDefaultAttr() ) - SetDefaultAttr(other.GetDefaultAttr()); + wxCHECK_MSG(Ok() && other.Ok(), false, wxT("this or Attr to MergeWith from is not created")); + + if (!HasForegoundColour() && other.HasForegoundColour()) { + SetForegroundColour(other.GetForegroundColour()); + } + if (!HasBackgroundColour() && other.HasBackgroundColour()) { + SetBackgroundColour(other.GetBackgroundColour()); + } + if (!HasFont() && other.HasFont()) { + SetFont(other.GetFont()); + } + if (!HasAlignment() && other.HasAlignment()) { + SetAlignment(other.GetAlignment()); + } + if (!HasOrientation() && other.HasOrientation()) { + SetOrientation(other.GetOrientation()); + } + if (!HasLevel() && other.HasLevel()) { + SetLevel(other.GetLevel()); + } + if (!HasReadWriteMode() && other.HasReadWriteMode()) { + SetReadOnly(other.GetReadOnly()); + } + if (!HasOverflowMode() && other.HasOverflowMode()) { + SetOverflow(other.GetOverflow()); + } + if (!HasOverflowMarkerMode() && other.HasOverflowMarkerMode()) { + SetOverflowMarker(other.GetOverflowMarker()); + } + if (!HasShowEditorMode() && other.HasShowEditorMode()) { + SetShowEditor(other.GetShowEditor()); + } + + // Directly access m_renderer/m_editor as GetRender/Editor may return different one + + // Maybe add support for merge of Render and Editor? + if (!HasRenderer() && other.HasRenderer()) { + SetRenderer(((wxSheetCellAttrRefData *)other.m_refData)->m_renderer->Clone()); + } + if (!HasEditor() && other.HasEditor()) { + SetEditor(((wxSheetCellAttrRefData *)other.m_refData)->m_editor->Clone()); + } + + if (!HasDefaultAttr() && other.HasDefaultAttr()) { + SetDefaultAttr(other.GetDefaultAttr()); + } - return true; + return true; } -void wxSheetCellAttr::SetForegroundColour(const wxColour& foreColour) -{ - wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); - M_CELLATTRDATA->m_foreColour = foreColour; -} -void wxSheetCellAttr::SetBackgroundColour(const wxColour& backColour) +void wxSheetCellAttr::SetForegroundColour(const wxColour &foreColour) { - wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); - M_CELLATTRDATA->m_backColour = backColour; + wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); + M_CELLATTRDATA->m_foreColour = foreColour; } -void wxSheetCellAttr::SetFont(const wxFont& font) +void wxSheetCellAttr::SetBackgroundColour(const wxColour &backColour) { - wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); - M_CELLATTRDATA->m_font = font; + wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); + M_CELLATTRDATA->m_backColour = backColour; } -void wxSheetCellAttr::SetAlignment(int align) +void wxSheetCellAttr::SetFont(const wxFont &font) { - SetType(align, wxSHEET_AttrAlignType_Mask); + wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); + M_CELLATTRDATA->m_font = font; } +void wxSheetCellAttr::SetAlignment(int align) { SetType(align, wxSHEET_AttrAlignType_Mask); } void wxSheetCellAttr::SetAlignment(int horizAlign, int vertAlign) { - SetType(wxSheet::SetAlignment(M_CELLATTRDATA->m_attrTypes, horizAlign, vertAlign), - wxSHEET_AttrAlignType_Mask); + SetType(wxSheet::SetAlignment(M_CELLATTRDATA->m_attrTypes, horizAlign, vertAlign), + wxSHEET_AttrAlignType_Mask); } void wxSheetCellAttr::SetOrientation(int orientation) { - SetType(orientation, wxSHEET_AttrOrientType_Mask); + SetType(orientation, wxSHEET_AttrOrientType_Mask); } void wxSheetCellAttr::SetLevel(wxSheetAttrLevel_Type level) { - SetType(level, wxSHEET_AttrLevelType_Mask); + SetType(level, wxSHEET_AttrLevelType_Mask); } void wxSheetCellAttr::SetOverflow(bool allow) { - SetType(allow ? wxSHEET_AttrOverflow : wxSHEET_AttrOverflowNot, - wxSHEET_AttrOverflowType_Mask); + SetType(allow ? wxSHEET_AttrOverflow : wxSHEET_AttrOverflowNot, wxSHEET_AttrOverflowType_Mask); } void wxSheetCellAttr::SetOverflowMarker(bool draw_marker) { - SetType(draw_marker ? wxSHEET_AttrOverflowMarker : wxSHEET_AttrOverflowMarkerNot, - wxSHEET_AttrOverflowMarkerType_Mask); + SetType(draw_marker ? wxSHEET_AttrOverflowMarker : wxSHEET_AttrOverflowMarkerNot, + wxSHEET_AttrOverflowMarkerType_Mask); } void wxSheetCellAttr::SetShowEditor(bool show_editor) { - SetType(show_editor ? wxSHEET_AttrShowEditor : wxSHEET_AttrShowEditorNot, - wxSHEET_AttrShowEditorType_Mask); + SetType(show_editor ? wxSHEET_AttrShowEditor : wxSHEET_AttrShowEditorNot, + wxSHEET_AttrShowEditorType_Mask); } void wxSheetCellAttr::SetReadOnly(bool isReadOnly) { - SetType(isReadOnly ? wxSHEET_AttrReadOnly : wxSHEET_AttrReadWrite, - wxSHEET_AttrReadType_Mask); + SetType(isReadOnly ? wxSHEET_AttrReadOnly : wxSHEET_AttrReadWrite, wxSHEET_AttrReadType_Mask); } -void wxSheetCellAttr::SetRenderer(const wxSheetCellRenderer& renderer) +void wxSheetCellAttr::SetRenderer(const wxSheetCellRenderer &renderer) { - wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); - if (M_CELLATTRDATA->m_renderer) - { - delete M_CELLATTRDATA->m_renderer; - M_CELLATTRDATA->m_renderer = NULL; - } - if (renderer.Ok()) - M_CELLATTRDATA->m_renderer = new wxSheetCellRenderer(renderer); -} -void wxSheetCellAttr::SetEditor(const wxSheetCellEditor& editor) -{ - wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); - if (M_CELLATTRDATA->m_editor) - { - delete M_CELLATTRDATA->m_editor; - M_CELLATTRDATA->m_editor = NULL; - } - if (editor.Ok()) - M_CELLATTRDATA->m_editor = new wxSheetCellEditor(editor); + wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); + if (M_CELLATTRDATA->m_renderer) { + delete M_CELLATTRDATA->m_renderer; + M_CELLATTRDATA->m_renderer = NULL; + } + if (renderer.Ok()) { + M_CELLATTRDATA->m_renderer = new wxSheetCellRenderer(renderer); + } } -void wxSheetCellAttr::SetKind(wxSheetAttr_Type kind) +void wxSheetCellAttr::SetEditor(const wxSheetCellEditor &editor) { - SetType(kind, wxSHEET_AttrAny); + wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); + if (M_CELLATTRDATA->m_editor) { + delete M_CELLATTRDATA->m_editor; + M_CELLATTRDATA->m_editor = NULL; + } + if (editor.Ok()) { + M_CELLATTRDATA->m_editor = new wxSheetCellEditor(editor); + } } +void wxSheetCellAttr::SetKind(wxSheetAttr_Type kind) { SetType(kind, wxSHEET_AttrAny); } bool wxSheetCellAttr::HasForegoundColour() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - return M_CELLATTRDATA->m_foreColour.Ok(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + return M_CELLATTRDATA->m_foreColour.Ok(); } bool wxSheetCellAttr::HasBackgroundColour() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - return M_CELLATTRDATA->m_backColour.Ok(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + return M_CELLATTRDATA->m_backColour.Ok(); } bool wxSheetCellAttr::HasFont() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - return M_CELLATTRDATA->m_font.Ok(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + return M_CELLATTRDATA->m_font.Ok(); } bool wxSheetCellAttr::HasAlignment() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - // note: Left and Top is 0 - return (((M_CELLATTRDATA->m_attrTypes) & wxSHEET_AttrAlignHorizUnset) == 0) && - (((M_CELLATTRDATA->m_attrTypes) & wxSHEET_AttrAlignVertUnset ) == 0); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + // note: Left and Top is 0 + return (((M_CELLATTRDATA->m_attrTypes) & wxSHEET_AttrAlignHorizUnset) == 0) && + (((M_CELLATTRDATA->m_attrTypes) & wxSHEET_AttrAlignVertUnset) == 0); } bool wxSheetCellAttr::HasOrientation() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - return ((M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientHoriz) != 0) || - ((M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientVert ) != 0); -} -bool wxSheetCellAttr::HasLevel() const -{ - return HasType(wxSHEET_AttrLevelType_Mask); -} -bool wxSheetCellAttr::HasOverflowMode() const -{ - return HasType(wxSHEET_AttrOverflowType_Mask); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + return ((M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientHoriz) != 0) || + ((M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientVert) != 0); } +bool wxSheetCellAttr::HasLevel() const { return HasType(wxSHEET_AttrLevelType_Mask); } +bool wxSheetCellAttr::HasOverflowMode() const { return HasType(wxSHEET_AttrOverflowType_Mask); } bool wxSheetCellAttr::HasOverflowMarkerMode() const { - return HasType(wxSHEET_AttrOverflowMarkerType_Mask); + return HasType(wxSHEET_AttrOverflowMarkerType_Mask); } bool wxSheetCellAttr::HasShowEditorMode() const { - return HasType(wxSHEET_AttrShowEditorType_Mask); -} -bool wxSheetCellAttr::HasReadWriteMode() const -{ - return HasType(wxSHEET_AttrReadType_Mask); + return HasType(wxSHEET_AttrShowEditorType_Mask); } +bool wxSheetCellAttr::HasReadWriteMode() const { return HasType(wxSHEET_AttrReadType_Mask); } bool wxSheetCellAttr::HasRenderer() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - return M_CELLATTRDATA->m_renderer && M_CELLATTRDATA->m_renderer->Ok(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + return M_CELLATTRDATA->m_renderer && M_CELLATTRDATA->m_renderer->Ok(); } bool wxSheetCellAttr::HasEditor() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - return M_CELLATTRDATA->m_editor && M_CELLATTRDATA->m_editor->Ok(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + return M_CELLATTRDATA->m_editor && M_CELLATTRDATA->m_editor->Ok(); } bool wxSheetCellAttr::HasDefaultAttr() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - return M_CELLATTRDATA->m_defaultAttr && M_CELLATTRDATA->m_defaultAttr->Ok(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + return M_CELLATTRDATA->m_defaultAttr && M_CELLATTRDATA->m_defaultAttr->Ok(); } bool wxSheetCellAttr::IsComplete() const { - return Ok() && HasForegoundColour() && HasBackgroundColour() && HasFont() && - HasAlignment() && HasOverflowMode() && HasLevel() && - HasReadWriteMode() && HasRenderer() && HasEditor(); + return Ok() && HasForegoundColour() && HasBackgroundColour() && HasFont() && HasAlignment() && + HasOverflowMode() && HasLevel() && HasReadWriteMode() && HasRenderer() && HasEditor(); } -const wxColour& wxSheetCellAttr::GetForegroundColour() const +const wxColour &wxSheetCellAttr::GetForegroundColour() const { - wxCHECK_MSG(m_refData, *wxBLACK, wxT("wxSheetCellAttr not initializied")); - if (HasForegoundColour()) - return M_CELLATTRDATA->m_foreColour; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasForegoundColour()) - return GetDefaultAttr().GetForegroundColour(); + wxCHECK_MSG(m_refData, *wxBLACK, wxT("wxSheetCellAttr not initializied")); + if (HasForegoundColour()) { + return M_CELLATTRDATA->m_foreColour; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasForegoundColour()) + return GetDefaultAttr().GetForegroundColour(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return *wxBLACK; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return *wxBLACK; } -const wxColour& wxSheetCellAttr::GetBackgroundColour() const +const wxColour &wxSheetCellAttr::GetBackgroundColour() const { - wxCHECK_MSG(m_refData, *wxWHITE, wxT("wxSheetCellAttr not initializied")); - if (HasBackgroundColour()) - return M_CELLATTRDATA->m_backColour; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasBackgroundColour()) - return GetDefaultAttr().GetBackgroundColour(); + wxCHECK_MSG(m_refData, *wxWHITE, wxT("wxSheetCellAttr not initializied")); + if (HasBackgroundColour()) { + return M_CELLATTRDATA->m_backColour; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasBackgroundColour()) + return GetDefaultAttr().GetBackgroundColour(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return *wxWHITE; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return *wxWHITE; } -const wxFont& wxSheetCellAttr::GetFont() const +const wxFont &wxSheetCellAttr::GetFont() const { - wxCHECK_MSG(m_refData, *wxNORMAL_FONT, wxT("wxSheetCellAttr not initializied")); - if (HasFont()) - return M_CELLATTRDATA->m_font; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasFont()) - return GetDefaultAttr().GetFont(); + wxCHECK_MSG(m_refData, *wxNORMAL_FONT, wxT("wxSheetCellAttr not initializied")); + if (HasFont()) { + return M_CELLATTRDATA->m_font; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasFont()) + return GetDefaultAttr().GetFont(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return *wxNORMAL_FONT; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return *wxNORMAL_FONT; } int wxSheetCellAttr::GetAlignment() const { - wxCHECK_MSG(m_refData, wxSHEET_AttrAlignLeft|wxSHEET_AttrAlignCenterVert, wxT("wxSheetCellAttr not initializied")); - if (HasAlignment()) - return M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrAlignType_Mask; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasAlignment()) - return GetDefaultAttr().GetAlignment(); + wxCHECK_MSG(m_refData, wxSHEET_AttrAlignLeft | wxSHEET_AttrAlignCenterVert, + wxT("wxSheetCellAttr not initializied")); + if (HasAlignment()) { + return M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrAlignType_Mask; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasAlignment()) + return GetDefaultAttr().GetAlignment(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return wxSHEET_AttrAlignLeft|wxSHEET_AttrAlignCenterVert; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return wxSHEET_AttrAlignLeft | wxSHEET_AttrAlignCenterVert; } wxOrientation wxSheetCellAttr::GetOrientation() const { - wxCHECK_MSG(m_refData, wxHORIZONTAL, wxT("wxSheetCellAttr not initializied")); - if (HasOrientation()) - return wxOrientation(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientType_Mask); - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasOrientation()) - return GetDefaultAttr().GetOrientation(); + wxCHECK_MSG(m_refData, wxHORIZONTAL, wxT("wxSheetCellAttr not initializied")); + if (HasOrientation()) { + return wxOrientation(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOrientType_Mask); + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasOrientation()) + return GetDefaultAttr().GetOrientation(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return wxHORIZONTAL; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return wxHORIZONTAL; } wxSheetAttrLevel_Type wxSheetCellAttr::GetLevel() const { - wxCHECK_MSG(m_refData, wxSHEET_AttrLevelTop, wxT("wxSheetCellAttr not initializied")); - if (HasLevel()) - return wxSheetAttrLevel_Type(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrLevelType_Mask); - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasLevel()) - return GetDefaultAttr().GetLevel(); + wxCHECK_MSG(m_refData, wxSHEET_AttrLevelTop, wxT("wxSheetCellAttr not initializied")); + if (HasLevel()) { + return wxSheetAttrLevel_Type(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrLevelType_Mask); + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasLevel()) + return GetDefaultAttr().GetLevel(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return wxSHEET_AttrLevelTop; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return wxSHEET_AttrLevelTop; } bool wxSheetCellAttr::GetOverflow() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - if (HasOverflowMode()) - return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOverflow) != 0; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasOverflowMode()) - return GetDefaultAttr().GetOverflow(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + if (HasOverflowMode()) { + return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOverflow) != 0; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasOverflowMode()) + return GetDefaultAttr().GetOverflow(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return false; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return false; } bool wxSheetCellAttr::GetOverflowMarker() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - if (HasOverflowMarkerMode()) - return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOverflowMarker) != 0; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasOverflowMarkerMode()) - return GetDefaultAttr().GetOverflowMarker(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + if (HasOverflowMarkerMode()) { + return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrOverflowMarker) != 0; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasOverflowMarkerMode()) + return GetDefaultAttr().GetOverflowMarker(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return false; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return false; } bool wxSheetCellAttr::GetShowEditor() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - if (HasShowEditorMode()) - return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrShowEditor) != 0; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasShowEditorMode()) - return GetDefaultAttr().GetShowEditor(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + if (HasShowEditorMode()) { + return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrShowEditor) != 0; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasShowEditorMode()) + return GetDefaultAttr().GetShowEditor(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return false; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return false; } bool wxSheetCellAttr::GetReadOnly() const { - wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); - if (HasReadWriteMode()) - return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrReadOnly) != 0; - else if (GetDefaultAttr().Ok()) // && GetDefaultAttr().HasReadWriteMode()) - return GetDefaultAttr().GetReadOnly(); + wxCHECK_MSG(m_refData, false, wxT("wxSheetCellAttr not initializied")); + if (HasReadWriteMode()) { + return (M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrReadOnly) != 0; + } + else if (GetDefaultAttr().Ok()) { // && GetDefaultAttr().HasReadWriteMode()) + return GetDefaultAttr().GetReadOnly(); + } - wxFAIL_MSG(wxT("Missing default cell attribute")); - return false; + wxFAIL_MSG(wxT("Missing default cell attribute")); + return false; } // Labenski - the logic is now different, I didn't understand what it was @@ -466,282 +497,306 @@ bool wxSheetCellAttr::GetReadOnly() const // NULL (because the table has a type that the sheet does not have in its // registry,) then the sheet's default editor or renderer is used." -wxSheetCellRenderer wxSheetCellAttr::GetRenderer(wxSheet* sheet, const wxSheetCoords& coords) const -{ - wxCHECK_MSG(m_refData, wxNullSheetCellRenderer, wxT("wxSheetCellAttr not initializied")); - wxSheetCellRenderer renderer; - - // first try to get the renderer for the cell from the sheet, if this is default - if (sheet && (sheet->GetDefaultAttr(coords) == *this)) - renderer = sheet->GetDefaultRendererForCell(coords); - - // then see if this has a renderer and return it if valid - if ( !renderer.Ok() ) - { - if ( M_CELLATTRDATA->m_renderer && M_CELLATTRDATA->m_renderer->Ok() ) - renderer = *M_CELLATTRDATA->m_renderer; - else - { - // couldn't get it from the sheet try attr default - wxSheetCellAttr defAttr(GetDefaultAttr()); - if ( defAttr.Ok() ) - renderer = defAttr.GetRenderer(sheet, coords); - } +wxSheetCellRenderer wxSheetCellAttr::GetRenderer(wxSheet *sheet, const wxSheetCoords &coords) const +{ + wxCHECK_MSG(m_refData, wxNullSheetCellRenderer, wxT("wxSheetCellAttr not initializied")); + wxSheetCellRenderer renderer; + + // first try to get the renderer for the cell from the sheet, if this is default + if (sheet && (sheet->GetDefaultAttr(coords) == *this)) { + renderer = sheet->GetDefaultRendererForCell(coords); + } + + // then see if this has a renderer and return it if valid + if (!renderer.Ok()) { + if (M_CELLATTRDATA->m_renderer && M_CELLATTRDATA->m_renderer->Ok()) { + renderer = *M_CELLATTRDATA->m_renderer; } + else { + // couldn't get it from the sheet try attr default + wxSheetCellAttr defAttr(GetDefaultAttr()); + if (defAttr.Ok()) { + renderer = defAttr.GetRenderer(sheet, coords); + } + } + } + + // we're supposed to always find something + wxASSERT_MSG(renderer.Ok(), wxT("Missing default cell renderer")); + return renderer; +} +wxSheetCellEditor wxSheetCellAttr::GetEditor(wxSheet *sheet, const wxSheetCoords &coords) const +{ + wxCHECK_MSG(m_refData, wxNullSheetCellEditor, wxT("wxSheetCellAttr not initializied")); + wxSheetCellEditor editor; - // we're supposed to always find something - wxASSERT_MSG(renderer.Ok(), wxT("Missing default cell renderer")); - return renderer; -} -wxSheetCellEditor wxSheetCellAttr::GetEditor(wxSheet* sheet, const wxSheetCoords& coords) const -{ - wxCHECK_MSG(m_refData, wxNullSheetCellEditor, wxT("wxSheetCellAttr not initializied")); - wxSheetCellEditor editor; - - // first try to get the editor for the cell from the sheet, if this is default - if (sheet && (sheet->GetDefaultAttr(coords) == *this)) - editor = sheet->GetDefaultEditorForCell(coords); - - // then see if this has a editor and return it if valid - if ( !editor.Ok() ) - { - if ( M_CELLATTRDATA->m_editor && M_CELLATTRDATA->m_editor->Ok() ) - editor = *M_CELLATTRDATA->m_editor; - else - { - // couldn't get it from the sheet try attr default - wxSheetCellAttr defAttr(GetDefaultAttr()); - if ( defAttr.Ok() ) - editor = defAttr.GetEditor(sheet, coords); - } + // first try to get the editor for the cell from the sheet, if this is default + if (sheet && (sheet->GetDefaultAttr(coords) == *this)) { + editor = sheet->GetDefaultEditorForCell(coords); + } + + // then see if this has a editor and return it if valid + if (!editor.Ok()) { + if (M_CELLATTRDATA->m_editor && M_CELLATTRDATA->m_editor->Ok()) { + editor = *M_CELLATTRDATA->m_editor; + } + else { + // couldn't get it from the sheet try attr default + wxSheetCellAttr defAttr(GetDefaultAttr()); + if (defAttr.Ok()) { + editor = defAttr.GetEditor(sheet, coords); + } } + } - // we're supposed to always find something - wxASSERT_MSG(editor.Ok(), wxT("Missing default cell editor")); - return editor; + // we're supposed to always find something + wxASSERT_MSG(editor.Ok(), wxT("Missing default cell editor")); + return editor; } wxSheetAttr_Type wxSheetCellAttr::GetKind() const { - wxCHECK_MSG(m_refData, wxSHEET_AttrCell, wxT("wxSheetCellAttr not initializied")); - return wxSheetAttr_Type(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrAny); + wxCHECK_MSG(m_refData, wxSHEET_AttrCell, wxT("wxSheetCellAttr not initializied")); + return wxSheetAttr_Type(M_CELLATTRDATA->m_attrTypes & wxSHEET_AttrAny); } -const wxSheetCellAttr& wxSheetCellAttr::GetDefaultAttr() const +const wxSheetCellAttr &wxSheetCellAttr::GetDefaultAttr() const { - wxCHECK_MSG(m_refData, wxNullSheetCellAttr, wxT("wxSheetCellAttr not initializied")); - if (M_CELLATTRDATA->m_defaultAttr != NULL) - return *M_CELLATTRDATA->m_defaultAttr; + wxCHECK_MSG(m_refData, wxNullSheetCellAttr, wxT("wxSheetCellAttr not initializied")); + if (M_CELLATTRDATA->m_defaultAttr != NULL) { + return *M_CELLATTRDATA->m_defaultAttr; + } - return wxNullSheetCellAttr; + return wxNullSheetCellAttr; } -void wxSheetCellAttr::SetDefaultAttr(const wxSheetCellAttr& defAttr) +void wxSheetCellAttr::SetDefaultAttr(const wxSheetCellAttr &defAttr) { - wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); - if (M_CELLATTRDATA->m_defaultAttr) - { - delete M_CELLATTRDATA->m_defaultAttr; - M_CELLATTRDATA->m_defaultAttr = NULL; - } - // don't set defAttr to this, you don't gain anything, but a memory leak - //if (defAttr.Ok() && (defAttr.m_refData != m_refData)) - // M_CELLATTRDATA->m_defaultAttr = new wxSheetCellAttr(defAttr); - - if (defAttr.Ok()) - { - wxSheetCellAttr attr(defAttr); - while (attr.Ok()) - { - wxCHECK_RET((*this) != attr, wxT("wxSheet attributes are linked recursively")); - attr = attr.GetDefaultAttr(); - } - - M_CELLATTRDATA->m_defaultAttr = new wxSheetCellAttr(defAttr); + wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); + if (M_CELLATTRDATA->m_defaultAttr) { + delete M_CELLATTRDATA->m_defaultAttr; + M_CELLATTRDATA->m_defaultAttr = NULL; + } + // don't set defAttr to this, you don't gain anything, but a memory leak + // if (defAttr.Ok() && (defAttr.m_refData != m_refData)) + // M_CELLATTRDATA->m_defaultAttr = new wxSheetCellAttr(defAttr); + + if (defAttr.Ok()) { + wxSheetCellAttr attr(defAttr); + while (attr.Ok()) { + wxCHECK_RET((*this) != attr, wxT("wxSheet attributes are linked recursively")); + attr = attr.GetDefaultAttr(); } + + M_CELLATTRDATA->m_defaultAttr = new wxSheetCellAttr(defAttr); + } } void wxSheetCellAttr::SetType(int type, int mask) { - wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); - M_CELLATTRDATA->m_attrTypes &= ~mask; // clear old - M_CELLATTRDATA->m_attrTypes |= (mask ? (type & mask) : type); // set new + wxCHECK_RET(m_refData, wxT("wxSheetCellAttr not initializied")); + M_CELLATTRDATA->m_attrTypes &= ~mask; // clear old + M_CELLATTRDATA->m_attrTypes |= (mask ? (type & mask) : type); // set new } int wxSheetCellAttr::GetType(int mask) const { - wxCHECK_MSG(m_refData, 0, wxT("wxSheetCellAttr not initializied")); - return (M_CELLATTRDATA->m_attrTypes & mask); + wxCHECK_MSG(m_refData, 0, wxT("wxSheetCellAttr not initializied")); + return (M_CELLATTRDATA->m_attrTypes & mask); } // ---------------------------------------------------------------------------- // wxSheetCellAttrProvider // ---------------------------------------------------------------------------- -wxSheetCellAttr wxSheetCellAttrProvider::GetAttr(const wxSheetCoords& coords, - wxSheetAttr_Type type ) -{ - switch (wxSheet::GetCellCoordsType(coords)) - { - case wxSHEET_CELL_GRID : - { - switch (type) - { - case wxSHEET_AttrAny: - { - wxSheetCellAttr attrCell(m_cellAttrs.GetValue(coords)); - wxSheetCellAttr attrRow(m_rowAttrs.GetValue(coords.GetRow())); - wxSheetCellAttr attrCol(m_colAttrs.GetValue(coords.GetCol())); - - // points system, greater the level you get added last - // if two levels match use ordering col, row, cell on top. - wxPairArrayIntSheetCellAttr data; - if (attrCol.Ok()) data.SetValue(attrCol.GetLevel()+2, attrCol); - if (attrRow.Ok()) data.SetValue(attrRow.GetLevel()+1, attrRow); - if (attrCell.Ok()) data.SetValue(attrCell.GetLevel()+0, attrCell); - - // the attr are sorted from low priority to high - const int count = data.GetCount(); - - switch (count) - { - case 0 : return wxNullSheetCellAttr; - case 1 : return data.GetItemValue(0); - default : break; - } - - // This is the preferred way - link them together - // but you must make sure that it doesn't loop - // see check in wxSheetCellAttr::SetDefaultAttr - wxSheetCellAttr attr; - attr.Copy(data.GetItemValue(0)); - attr.SetDefaultAttr(data.GetItemValue(1)); - if (count > 2) - data.GetItemValue(1).SetDefaultAttr(data.GetItemValue(2)); -/* - // This is the old way of copying the values to a single attr - wxSheetCellAttr attr; - attr.Copy(data.GetItemValue(0)); - attr.MergeWith(data.GetItemValue(1)); - if (count > 2) - attr.MergeWith(data.GetItemValue(2)); -*/ - // This is not a "real" attr but created - attr.SetKind(wxSHEET_AttrAny); - - return attr; - } - case wxSHEET_AttrCell : return m_cellAttrs.GetValue(coords); - case wxSHEET_AttrRow : return m_rowAttrs.GetValue(coords.GetRow()); - case wxSHEET_AttrCol : return m_colAttrs.GetValue(coords.GetCol()); - default: - // unused as yet... - // (wxSheetCellAttr::Default): - // (wxSheetCellAttr::Merged): - break; - } - break; - } - case wxSHEET_CELL_ROWLABEL : return m_rowLabelAttrs.GetValue(coords.m_row); - case wxSHEET_CELL_COLLABEL : return m_colLabelAttrs.GetValue(coords.m_col); - default : - wxFAIL_MSG(wxString::Format(wxT("Unhandled coords (%d, %d) in wxSheetCellAttrProvider::GetAttr"), coords.m_row, coords.m_col)); - break; +wxSheetCellAttr wxSheetCellAttrProvider::GetAttr(const wxSheetCoords &coords, + wxSheetAttr_Type type) +{ + switch (wxSheet::GetCellCoordsType(coords)) { + case wxSHEET_CELL_GRID: { + switch (type) { + case wxSHEET_AttrAny: { + wxSheetCellAttr attrCell(m_cellAttrs.GetValue(coords)); + wxSheetCellAttr attrRow(m_rowAttrs.GetValue(coords.GetRow())); + wxSheetCellAttr attrCol(m_colAttrs.GetValue(coords.GetCol())); + + // points system, greater the level you get added last + // if two levels match use ordering col, row, cell on top. + wxPairArrayIntSheetCellAttr data; + if (attrCol.Ok()) { + data.SetValue(attrCol.GetLevel() + 2, attrCol); + } + if (attrRow.Ok()) { + data.SetValue(attrRow.GetLevel() + 1, attrRow); + } + if (attrCell.Ok()) { + data.SetValue(attrCell.GetLevel() + 0, attrCell); + } + + // the attr are sorted from low priority to high + const int count = data.GetCount(); + + switch (count) { + case 0: + return wxNullSheetCellAttr; + case 1: + return data.GetItemValue(0); + default: + break; + } + + // This is the preferred way - link them together + // but you must make sure that it doesn't loop + // see check in wxSheetCellAttr::SetDefaultAttr + wxSheetCellAttr attr; + attr.Copy(data.GetItemValue(0)); + attr.SetDefaultAttr(data.GetItemValue(1)); + if (count > 2) { + data.GetItemValue(1).SetDefaultAttr(data.GetItemValue(2)); + } + /* + // This is the old way of copying the values to a single attr + wxSheetCellAttr attr; + attr.Copy(data.GetItemValue(0)); + attr.MergeWith(data.GetItemValue(1)); + if (count > 2) + attr.MergeWith(data.GetItemValue(2)); + */ + // This is not a "real" attr but created + attr.SetKind(wxSHEET_AttrAny); + + return attr; } - - return wxNullSheetCellAttr; -} - -void wxSheetCellAttrProvider::SetAttr(const wxSheetCoords& coords, - const wxSheetCellAttr &attr, + case wxSHEET_AttrCell: + return m_cellAttrs.GetValue(coords); + case wxSHEET_AttrRow: + return m_rowAttrs.GetValue(coords.GetRow()); + case wxSHEET_AttrCol: + return m_colAttrs.GetValue(coords.GetCol()); + default: + // unused as yet... + // (wxSheetCellAttr::Default): + // (wxSheetCellAttr::Merged): + break; + } + break; + } + case wxSHEET_CELL_ROWLABEL: + return m_rowLabelAttrs.GetValue(coords.m_row); + case wxSHEET_CELL_COLLABEL: + return m_colLabelAttrs.GetValue(coords.m_col); + default: + wxFAIL_MSG( + wxString::Format(wxT("Unhandled coords (%d, %d) in wxSheetCellAttrProvider::GetAttr"), + coords.m_row, coords.m_col)); + break; + } + + return wxNullSheetCellAttr; +} + +void wxSheetCellAttrProvider::SetAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr, wxSheetAttr_Type type) { - switch (wxSheet::GetCellCoordsType(coords)) - { - case wxSHEET_CELL_GRID : - { - switch (type) - { - case wxSHEET_AttrCell : - { - if (attr.Ok()) m_cellAttrs.SetValue(coords, attr); - else m_cellAttrs.RemoveValue(coords); - return; - } - case wxSHEET_AttrRow : - { - if (attr.Ok()) m_rowAttrs.SetValue(coords.m_row, attr); - else m_rowAttrs.RemoveValue(coords.m_row); - return; - } - case wxSHEET_AttrCol : - { - if (attr.Ok()) m_colAttrs.SetValue(coords.m_col, attr); - else m_colAttrs.RemoveValue(coords.m_col); - return; - } - default : - { - wxFAIL_MSG(wxT("Unhandled attr type for grid coords")); - return; - } - } - break; - } - case wxSHEET_CELL_ROWLABEL : - { - switch (type) - { - case wxSHEET_AttrCell : - { - if (attr.Ok()) m_rowLabelAttrs.SetValue(coords.m_row, attr); - else m_rowLabelAttrs.RemoveValue(coords.m_row); - return; - } - default : - { - wxFAIL_MSG(wxT("Unhandled attr type for row label coords")); - return; - } - } - break; - } - case wxSHEET_CELL_COLLABEL : - { - switch (type) - { - case wxSHEET_AttrCell : - { - if (attr.Ok()) m_colLabelAttrs.SetValue(coords.m_col, attr); - else m_colLabelAttrs.RemoveValue(coords.m_col); - return; - } - default : - { - wxFAIL_MSG(wxT("Unhandled attr type for col label coords")); - return; - } - } - break; - } - default : - wxFAIL_MSG(wxString::Format(wxT("Unhandled coords (%d, %d) in wxSheetCellAttrProvider::SetAttr"), coords.m_row, coords.m_col)); - break; + switch (wxSheet::GetCellCoordsType(coords)) { + case wxSHEET_CELL_GRID: { + switch (type) { + case wxSHEET_AttrCell: { + if (attr.Ok()) { + m_cellAttrs.SetValue(coords, attr); + } + else { + m_cellAttrs.RemoveValue(coords); + } + return; } -} -void wxSheetCellAttrProvider::UpdateRows( size_t row, int numRows, int update ) -{ - // no errors here since the pair arrays don't need to know about size - if ((update & wxSHEET_UpdateGridCellAttrs) != 0) - m_rowAttrs.UpdatePos( row, numRows ); - if ((update & wxSHEET_UpdateGridCellAttrs) != 0) - m_cellAttrs.UpdateRows( row, numRows ); - if ((update & wxSHEET_UpdateRowLabelAttrs) != 0) - m_rowLabelAttrs.UpdatePos( row, numRows ); -} - -void wxSheetCellAttrProvider::UpdateCols( size_t col, int numCols, int update ) -{ - if ((update & wxSHEET_UpdateGridCellAttrs) != 0) - m_colAttrs.UpdatePos( col, numCols ); - if ((update & wxSHEET_UpdateGridCellAttrs) != 0) - m_cellAttrs.UpdateCols( col, numCols ); - if ((update & wxSHEET_UpdateColLabelAttrs) != 0) - m_colLabelAttrs.UpdatePos( col, numCols ); + case wxSHEET_AttrRow: { + if (attr.Ok()) { + m_rowAttrs.SetValue(coords.m_row, attr); + } + else { + m_rowAttrs.RemoveValue(coords.m_row); + } + return; + } + case wxSHEET_AttrCol: { + if (attr.Ok()) { + m_colAttrs.SetValue(coords.m_col, attr); + } + else { + m_colAttrs.RemoveValue(coords.m_col); + } + return; + } + default: { + wxFAIL_MSG(wxT("Unhandled attr type for grid coords")); + return; + } + } + break; + } + case wxSHEET_CELL_ROWLABEL: { + switch (type) { + case wxSHEET_AttrCell: { + if (attr.Ok()) { + m_rowLabelAttrs.SetValue(coords.m_row, attr); + } + else { + m_rowLabelAttrs.RemoveValue(coords.m_row); + } + return; + } + default: { + wxFAIL_MSG(wxT("Unhandled attr type for row label coords")); + return; + } + } + break; + } + case wxSHEET_CELL_COLLABEL: { + switch (type) { + case wxSHEET_AttrCell: { + if (attr.Ok()) { + m_colLabelAttrs.SetValue(coords.m_col, attr); + } + else { + m_colLabelAttrs.RemoveValue(coords.m_col); + } + return; + } + default: { + wxFAIL_MSG(wxT("Unhandled attr type for col label coords")); + return; + } + } + break; + } + default: + wxFAIL_MSG( + wxString::Format(wxT("Unhandled coords (%d, %d) in wxSheetCellAttrProvider::SetAttr"), + coords.m_row, coords.m_col)); + break; + } +} +void wxSheetCellAttrProvider::UpdateRows(size_t row, int numRows, int update) +{ + // no errors here since the pair arrays don't need to know about size + if ((update & wxSHEET_UpdateGridCellAttrs) != 0) { + m_rowAttrs.UpdatePos(row, numRows); + } + if ((update & wxSHEET_UpdateGridCellAttrs) != 0) { + m_cellAttrs.UpdateRows(row, numRows); + } + if ((update & wxSHEET_UpdateRowLabelAttrs) != 0) { + m_rowLabelAttrs.UpdatePos(row, numRows); + } +} + +void wxSheetCellAttrProvider::UpdateCols(size_t col, int numCols, int update) +{ + if ((update & wxSHEET_UpdateGridCellAttrs) != 0) { + m_colAttrs.UpdatePos(col, numCols); + } + if ((update & wxSHEET_UpdateGridCellAttrs) != 0) { + m_cellAttrs.UpdateCols(col, numCols); + } + if ((update & wxSHEET_UpdateColLabelAttrs) != 0) { + m_colLabelAttrs.UpdatePos(col, numCols); + } } diff --git a/src/labenski/src/sheetedg.cpp b/src/labenski/src/sheetedg.cpp index 0da90efbc..c5a408bdc 100644 --- a/src/labenski/src/sheetedg.cpp +++ b/src/labenski/src/sheetedg.cpp @@ -13,11 +13,11 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/defs.h" +#include "wx/defs.h" #endif // WX_PRECOMP #include "wx/sheet/sheetedg.h" @@ -28,270 +28,291 @@ DEFINE_PAIRED_INT_DATA_ARRAYS(int, wxPairArrayIntInt) // ---------------------------------------------------------------------------- // wxSheetArrayEdge - a wxArrayInt container that sums its values // ---------------------------------------------------------------------------- -wxSheetArrayEdge::wxSheetArrayEdge(size_t count, size_t default_size, - size_t min_allowed_size) - : m_count(count), m_default_size(default_size), - m_min_allowed_size(min_allowed_size) -{} +wxSheetArrayEdge::wxSheetArrayEdge(size_t count, size_t default_size, size_t min_allowed_size) + : m_count(count), m_default_size(default_size), m_min_allowed_size(min_allowed_size) +{ +} int wxSheetArrayEdge::FindIndex(int coord, bool clipToMinMax) const { - //wxCHECK_MSG(m_count != 0, -1, wxT("No edges to find index of")); - if (m_count < 0) return -1; - - // < 0 is never valid, check for clip - if (coord < 0) - return clipToMinMax ? 0 : -1; - - // need default size to at least be 1 - const int default_size = (m_default_size > 0) ? m_default_size : 1; - const int count = m_data.GetCount(); - int i_max = coord / default_size; - int i_min = 0; - - // if no edges in array then they're all of the default size - if (count == 0) - return (i_max < m_count) ? i_max : (clipToMinMax ? m_count-1 : -1); - - // quick checks for past end and in first element - if ( coord > m_data[count-1] ) - return clipToMinMax ? (count-1) : -1; - if ( coord <= m_data[0] ) - return 0; - - // reset the values of max and min if necessary and trim range down - if ( i_max >= count ) - i_max = count - 1; - if ( coord > m_data[i_max] ) - { - i_min = i_max; - i_max = count - 1; + // wxCHECK_MSG(m_count != 0, -1, wxT("No edges to find index of")); + if (m_count < 0) { + return -1; + } + + // < 0 is never valid, check for clip + if (coord < 0) { + return clipToMinMax ? 0 : -1; + } + + // need default size to at least be 1 + const int default_size = (m_default_size > 0) ? m_default_size : 1; + const int count = m_data.GetCount(); + int i_max = coord / default_size; + int i_min = 0; + + // if no edges in array then they're all of the default size + if (count == 0) { + return (i_max < m_count) ? i_max : (clipToMinMax ? m_count - 1 : -1); + } + + // quick checks for past end and in first element + if (coord > m_data[count - 1]) { + return clipToMinMax ? (count - 1) : -1; + } + if (coord <= m_data[0]) { + return 0; + } + + // reset the values of max and min if necessary and trim range down + if (i_max >= count) { + i_max = count - 1; + } + if (coord > m_data[i_max]) { + i_min = i_max; + i_max = count - 1; + } + + int median; + while (i_min < i_max) { + // no check for == since it's not very likely, at most 1 extra iteration + median = (i_min + i_max) / 2; + if (m_data[median] > coord) { + i_max = median; } - - int median; - while ( i_min < i_max ) - { - // no check for == since it's not very likely, at most 1 extra iteration - median = (i_min + i_max)/2; - if (m_data[median] > coord) - i_max = median; - else - i_min = median + 1; + else { + i_min = median + 1; } + } - return i_min; + return i_min; } int wxSheetArrayEdge::FindMaxEdgeIndex(int val, int edge_size) const { - const int index = FindIndex(val, true); - if (index < 0) return -1; - // we know we're inside the 'index' element (or above or below the array) - // find which side is closer and if < edge_size return index - const int diff = abs(GetMax(index) - val); - const int diff_min = (index > 0) ? abs(GetMax(index-1) - val) : diff+edge_size+1; - - const int min_diff = wxMin(diff, diff_min); - if (min_diff > edge_size) - return -1; - else if (min_diff == diff) - return index; - else if (min_diff == diff_min) - return index - 1; - + const int index = FindIndex(val, true); + if (index < 0) { return -1; - -/* - // FIXME I wonder if this really makes complete sense? check it... - // eg. what would happen if size of cell was only 1 pixel, you couldn't resize it? - if ( GetSize(index) > edge_size ) - { - // We know that we are in index, test whether we are - // close enough to lower or upper border, respectively. - if ( abs(GetMax(index) - val) < edge_size ) - return index; - else if ( (index > 0) && (val - GetMin(index) < edge_size) ) - return index - 1; - } - + } + // we know we're inside the 'index' element (or above or below the array) + // find which side is closer and if < edge_size return index + const int diff = abs(GetMax(index) - val); + const int diff_min = (index > 0) ? abs(GetMax(index - 1) - val) : diff + edge_size + 1; + + const int min_diff = wxMin(diff, diff_min); + if (min_diff > edge_size) { return -1; -*/ + } + else if (min_diff == diff) { + return index; + } + else if (min_diff == diff_min) { + return index - 1; + } + + return -1; + + /* + // FIXME I wonder if this really makes complete sense? check it... + // eg. what would happen if size of cell was only 1 pixel, you couldn't resize it? + if ( GetSize(index) > edge_size ) + { + // We know that we are in index, test whether we are + // close enough to lower or upper border, respectively. + if ( abs(GetMax(index) - val) < edge_size ) + return index; + else if ( (index > 0) && (val - GetMin(index) < edge_size) ) + return index - 1; + } + + return -1; + */ } int wxSheetArrayEdge::GetMin(size_t item) const { - wxCHECK_MSG(int(item) < m_count, item*m_default_size, _T("invalid index") ); - return m_data.IsEmpty() ? item*m_default_size : (item > 0 ? m_data[item-1] : 0); + wxCHECK_MSG(int(item) < m_count, item * m_default_size, _T("invalid index")); + return m_data.IsEmpty() ? item * m_default_size : (item > 0 ? m_data[item - 1] : 0); } int wxSheetArrayEdge::GetMax(size_t item) const { - wxCHECK_MSG(int(item) < m_count, (item+1)*m_default_size - 1, _T("invalid index") ); - return (m_data.IsEmpty() ? (item+1)*m_default_size : m_data[item]) - 1; + wxCHECK_MSG(int(item) < m_count, (item + 1) * m_default_size - 1, _T("invalid index")); + return (m_data.IsEmpty() ? (item + 1) * m_default_size : m_data[item]) - 1; } int wxSheetArrayEdge::GetSize(size_t item) const { - wxCHECK_MSG(int(item) < m_count, m_default_size, _T("invalid index") ); - return m_data.IsEmpty() ? m_default_size : (m_data[item] - (item > 0 ? m_data[item-1] : 0)); + wxCHECK_MSG(int(item) < m_count, m_default_size, _T("invalid index")); + return m_data.IsEmpty() ? m_default_size : (m_data[item] - (item > 0 ? m_data[item - 1] : 0)); } void wxSheetArrayEdge::SetSize(size_t item, int size) { - wxCHECK_RET(int(item) < GetCount(), wxT("Invalid edge index")); - const int old_size = GetSize(item); - if (size == old_size) - return; - - // set to the min size if less than it - const int min_size = GetMinSize(item); - if (size < min_size) size = min_size; - - // need to really create the array - if ( m_data.IsEmpty() ) - InitArray(); - - const int diff = size - old_size; - const int count = m_data.GetCount(); - - for ( int i = item; i < count; i++ ) - m_data[i] += diff; - - if (size == m_default_size) - CheckMinimize(); + wxCHECK_RET(int(item) < GetCount(), wxT("Invalid edge index")); + const int old_size = GetSize(item); + if (size == old_size) { + return; + } + + // set to the min size if less than it + const int min_size = GetMinSize(item); + if (size < min_size) { + size = min_size; + } + + // need to really create the array + if (m_data.IsEmpty()) { + InitArray(); + } + + const int diff = size - old_size; + const int count = m_data.GetCount(); + + for (int i = item; i < count; i++) { + m_data[i] += diff; + } + + if (size == m_default_size) { + CheckMinimize(); + } } void wxSheetArrayEdge::SetDefaultSize(int default_size, bool resizeExisting) { - wxCHECK_RET(default_size >= 0, wxT("Edge default size must be greater than 0")); - m_default_size = default_size; - if (resizeExisting) - m_data.Clear(); - else - CheckMinimize(); + wxCHECK_RET(default_size >= 0, wxT("Edge default size must be greater than 0")); + m_default_size = default_size; + if (resizeExisting) { + m_data.Clear(); + } + else { + CheckMinimize(); + } } int wxSheetArrayEdge::GetMinSize(size_t index) const { - const int min_index = m_minSizes.FindIndex(index); - return (min_index != wxNOT_FOUND) ? m_minSizes.GetItemValue(min_index) : - m_min_allowed_size; + const int min_index = m_minSizes.FindIndex(index); + return (min_index != wxNOT_FOUND) ? m_minSizes.GetItemValue(min_index) : m_min_allowed_size; } void wxSheetArrayEdge::SetMinSize(size_t index, int size) { - if (size > m_min_allowed_size) - m_minSizes.GetOrCreateValue(index) = size; - else - m_minSizes.RemoveValue(index); + if (size > m_min_allowed_size) { + m_minSizes.GetOrCreateValue(index) = size; + } + else { + m_minSizes.RemoveValue(index); + } } bool wxSheetArrayEdge::SetMinAllowedSize(int min_allowed_size, bool resizeExisting) { - wxCHECK_MSG(m_default_size >= min_allowed_size, false, wxT("Invalid min allowed size")); - if (m_min_allowed_size == min_allowed_size) - return false; - - if (resizeExisting && (min_allowed_size < m_min_allowed_size)) - { - size_t n, count = m_minSizes.GetCount(); - for (n = 0; n < count; n++) - { - if (m_minSizes.GetItemValue(n) < min_allowed_size) - m_minSizes.RemoveValue(n); - } + wxCHECK_MSG(m_default_size >= min_allowed_size, false, wxT("Invalid min allowed size")); + if (m_min_allowed_size == min_allowed_size) { + return false; + } + + if (resizeExisting && (min_allowed_size < m_min_allowed_size)) { + size_t n, count = m_minSizes.GetCount(); + for (n = 0; n < count; n++) { + if (m_minSizes.GetItemValue(n) < min_allowed_size) { + m_minSizes.RemoveValue(n); + } + } - count = m_data.GetCount(); - if (count > 0) - { - int shift = m_data[0] < min_allowed_size ? min_allowed_size - m_data[0] : 0; - m_data[0] += shift; - - for (n = 1; n < count; n++) - { - m_data[n] += shift; - if (m_data[n] - m_data[n-1] < min_allowed_size) - { - int s = min_allowed_size - (m_data[n] - m_data[n-1]); - m_data[n] += s; - shift += s; - } - } + count = m_data.GetCount(); + if (count > 0) { + int shift = m_data[0] < min_allowed_size ? min_allowed_size - m_data[0] : 0; + m_data[0] += shift; + + for (n = 1; n < count; n++) { + m_data[n] += shift; + if (m_data[n] - m_data[n - 1] < min_allowed_size) { + int s = min_allowed_size - (m_data[n] - m_data[n - 1]); + m_data[n] += s; + shift += s; } + } } + } - m_min_allowed_size = min_allowed_size; - return true; + m_min_allowed_size = min_allowed_size; + return true; } void wxSheetArrayEdge::UpdatePos(size_t pos, int count) { - wxSHEET_CHECKUPDATE_RET(pos, count, m_count); - - m_count += count; - - const int old_count = m_data.GetCount(); - if ((count == 0) || (old_count == 0)) - return; - - int start_pos = pos, end_pos = old_count + count; - int i, edge = 0; - wxArrayInt sizes; // FIXME lazy way - sizes.Alloc(old_count); - sizes.Add( m_default_size, old_count); - - sizes[0] = m_data[0]; - for ( i = 1; i < old_count; i++ ) - sizes[i] = m_data[i] - m_data[i-1]; - - if (count > 0) // adding rows/cols - { - sizes.Insert( m_default_size, pos, count ); - m_data.Insert( 0, pos, count ); - edge = (pos > 0) ? m_data[pos-1] : 0; - } - else // if (count < 0) // deleting rows/cols - { - sizes.RemoveAt( pos, -count ); - m_data.RemoveAt( pos, -count ); - edge = (pos > 0) ? m_data[pos-1] : 0; - } - - for ( i = start_pos; i < end_pos; i++ ) - { - edge += sizes[i]; - m_data[i] = edge; - } - - if (count < 0) // maybe deleted non default - CheckMinimize(); + wxSHEET_CHECKUPDATE_RET(pos, count, m_count); + + m_count += count; + + const int old_count = m_data.GetCount(); + if ((count == 0) || (old_count == 0)) { + return; + } + + int start_pos = pos, end_pos = old_count + count; + int i, edge = 0; + wxArrayInt sizes; // FIXME lazy way + sizes.Alloc(old_count); + sizes.Add(m_default_size, old_count); + + sizes[0] = m_data[0]; + for (i = 1; i < old_count; i++) { + sizes[i] = m_data[i] - m_data[i - 1]; + } + + if (count > 0) // adding rows/cols + { + sizes.Insert(m_default_size, pos, count); + m_data.Insert(0, pos, count); + edge = (pos > 0) ? m_data[pos - 1] : 0; + } + else // if (count < 0) // deleting rows/cols + { + sizes.RemoveAt(pos, -count); + m_data.RemoveAt(pos, -count); + edge = (pos > 0) ? m_data[pos - 1] : 0; + } + + for (i = start_pos; i < end_pos; i++) { + edge += sizes[i]; + m_data[i] = edge; + } + + if (count < 0) { // maybe deleted non default + CheckMinimize(); + } } void wxSheetArrayEdge::InitArray() { - if (m_count == 0) return; - - m_data.Clear(); - m_data.Alloc( m_count ); - - int i, edge = 0; - for ( i = 0; i < m_count; i++ ) - { - edge += m_default_size; - m_data.Add( edge ); - } + if (m_count == 0) { + return; + } + + m_data.Clear(); + m_data.Alloc(m_count); + + int i, edge = 0; + for (i = 0; i < m_count; i++) { + edge += m_default_size; + m_data.Add(edge); + } } bool wxSheetArrayEdge::CheckMinimize() { - const int count = m_data.GetCount(); - if (count == 0) - return false; - - // start from end since it'll have a better chance of being off - for (int n = count - 1; n >= 0; n--) - { - if (m_data[n] != m_default_size*n) - return false; + const int count = m_data.GetCount(); + if (count == 0) { + return false; + } + + // start from end since it'll have a better chance of being off + for (int n = count - 1; n >= 0; n--) { + if (m_data[n] != m_default_size * n) { + return false; } + } - m_data.Clear(); - return true; + m_data.Clear(); + return true; } diff --git a/src/labenski/src/sheetedt.cpp b/src/labenski/src/sheetedt.cpp index 6ec591b5d..1d56a1584 100644 --- a/src/labenski/src/sheetedt.cpp +++ b/src/labenski/src/sheetedt.cpp @@ -12,21 +12,21 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/defs.h" - #include "wx/utils.h" - #include "wx/textctrl.h" - #include "wx/dc.h" - #include "wx/dcclient.h" - #include "wx/checkbox.h" - #include "wx/combobox.h" - #include "wx/log.h" - #include "wx/valtext.h" - #include "wx/settings.h" - #include "wx/intl.h" +#include "wx/defs.h" +#include "wx/utils.h" +#include "wx/textctrl.h" +#include "wx/dc.h" +#include "wx/dcclient.h" +#include "wx/checkbox.h" +#include "wx/combobox.h" +#include "wx/log.h" +#include "wx/valtext.h" +#include "wx/settings.h" +#include "wx/intl.h" #endif // WX_PRECOMP #include "wx/sheet/sheet.h" @@ -36,19 +36,20 @@ // Required for wxIs... functions #include -#define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); - +#define PRINT_RECT(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); #if defined(__WXMOTIF__) - #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier) +#define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier) #else - #define WXUNUSED_MOTIF(identifier) identifier +#define WXUNUSED_MOTIF(identifier) identifier #endif // defined(__WXMOTIF__) #if defined(__WXGTK__) - #define WXUNUSED_GTK(identifier) WXUNUSED(identifier) +#define WXUNUSED_GTK(identifier) WXUNUSED(identifier) #else - #define WXUNUSED_GTK(identifier) identifier +#define WXUNUSED_GTK(identifier) identifier #endif // defined(__WXGTK__) const wxSheetCellEditor wxNullSheetCellEditor; @@ -66,221 +67,214 @@ IMPLEMENT_DYNAMIC_CLASS(wxSheetCellAutoWrapStringEditorRefData, wxSheetCellTextE // ---------------------------------------------------------------------------- // wxSheetCellEditorEvtHandler // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( wxSheetCellEditorEvtHandler, wxEvtHandler ) +IMPLEMENT_DYNAMIC_CLASS(wxSheetCellEditorEvtHandler, wxEvtHandler) -BEGIN_EVENT_TABLE( wxSheetCellEditorEvtHandler, wxEvtHandler ) - EVT_KEY_DOWN ( wxSheetCellEditorEvtHandler::OnKeyDown ) - EVT_CHAR ( wxSheetCellEditorEvtHandler::OnChar ) - EVT_WINDOW_DESTROY ( wxSheetCellEditorEvtHandler::OnDestroy ) +BEGIN_EVENT_TABLE(wxSheetCellEditorEvtHandler, wxEvtHandler) +EVT_KEY_DOWN(wxSheetCellEditorEvtHandler::OnKeyDown) +EVT_CHAR(wxSheetCellEditorEvtHandler::OnChar) +EVT_WINDOW_DESTROY(wxSheetCellEditorEvtHandler::OnDestroy) END_EVENT_TABLE() -wxSheetCellEditorEvtHandler::wxSheetCellEditorEvtHandler(wxSheet* sheet, - const wxSheetCellEditor &editor) - : m_sheet(sheet) -{ - m_editor = (wxSheetCellEditorRefData*)editor.GetRefData(); - wxCHECK_RET(m_sheet && m_editor, wxT("Invalid sheet or editor in wxSheetCellEditorEvtHandler")); -} - -void wxSheetCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event) -{ - if (!m_editor->OnKeyDown(event)) - return; - - switch ( event.GetKeyCode() ) - { - case WXK_ESCAPE: - { - m_editor->ResetValue(); - m_sheet->DisableCellEditControl(false); - break; - } - case WXK_TAB: - { - m_sheet->GetEventHandler()->ProcessEvent( event ); - break; - } - case WXK_RETURN: - case WXK_NUMPAD_ENTER: - { - if (!m_sheet->GetEventHandler()->ProcessEvent(event)) - m_editor->HandleReturn(event); - break; - } - default: - event.Skip(); +wxSheetCellEditorEvtHandler::wxSheetCellEditorEvtHandler(wxSheet *sheet, + const wxSheetCellEditor &editor) + : m_sheet(sheet) +{ + m_editor = (wxSheetCellEditorRefData *)editor.GetRefData(); + wxCHECK_RET(m_sheet && m_editor, wxT("Invalid sheet or editor in wxSheetCellEditorEvtHandler")); +} + +void wxSheetCellEditorEvtHandler::OnKeyDown(wxKeyEvent &event) +{ + if (!m_editor->OnKeyDown(event)) { + return; + } + + switch (event.GetKeyCode()) { + case WXK_ESCAPE: { + m_editor->ResetValue(); + m_sheet->DisableCellEditControl(false); + break; + } + case WXK_TAB: { + m_sheet->GetEventHandler()->ProcessEvent(event); + break; + } + case WXK_RETURN: + case WXK_NUMPAD_ENTER: { + if (!m_sheet->GetEventHandler()->ProcessEvent(event)) { + m_editor->HandleReturn(event); } + break; + } + default: + event.Skip(); + } } -void wxSheetCellEditorEvtHandler::OnChar(wxKeyEvent& event) +void wxSheetCellEditorEvtHandler::OnChar(wxKeyEvent &event) { - if (!m_editor->OnChar(event)) - return; + if (!m_editor->OnChar(event)) { + return; + } - switch ( event.GetKeyCode() ) - { - case WXK_ESCAPE: - case WXK_TAB: - case WXK_RETURN: - case WXK_NUMPAD_ENTER: - break; - - default: - event.Skip(); - } + switch (event.GetKeyCode()) { + case WXK_ESCAPE: + case WXK_TAB: + case WXK_RETURN: + case WXK_NUMPAD_ENTER: + break; + + default: + event.Skip(); + } } -void wxSheetCellEditorEvtHandler::OnDestroy(wxWindowDestroyEvent& event) +void wxSheetCellEditorEvtHandler::OnDestroy(wxWindowDestroyEvent &event) { - event.Skip(); + event.Skip(); - // when parent window is destroyed pop event handler and NULL the control - if (m_editor->m_control && (m_editor->m_control->GetEventHandler() == this)) - { - // see if anyone else wants to process the event before we delete ourselves - if (!GetNextHandler()->ProcessEvent(event)) - { - wxWindow *win = m_editor->m_control; - m_editor->m_control = NULL; - win->PopEventHandler(true); - } - - event.Skip(false); + // when parent window is destroyed pop event handler and NULL the control + if (m_editor->m_control && (m_editor->m_control->GetEventHandler() == this)) { + // see if anyone else wants to process the event before we delete ourselves + if (!GetNextHandler()->ProcessEvent(event)) { + wxWindow *win = m_editor->m_control; + m_editor->m_control = NULL; + win->PopEventHandler(true); } + + event.Skip(false); + } } // ---------------------------------------------------------------------------- // wxSheetCellEditor // ---------------------------------------------------------------------------- -#define M_CELLEDITORDATA ((wxSheetCellEditorRefData*)m_refData) +#define M_CELLEDITORDATA ((wxSheetCellEditorRefData *)m_refData) -wxSheetCellEditor::wxSheetCellEditor( wxSheetCellEditorRefData *editor ) -{ - m_refData = editor; -} +wxSheetCellEditor::wxSheetCellEditor(wxSheetCellEditorRefData *editor) { m_refData = editor; } bool wxSheetCellEditor::IsCreated() const { - wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->IsCreated(); + wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->IsCreated(); } bool wxSheetCellEditor::IsShown() const { - wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->IsShown(); + wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->IsShown(); } -wxWindow* wxSheetCellEditor::GetControl() const +wxWindow *wxSheetCellEditor::GetControl() const { - wxCHECK_MSG(Ok(), NULL, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->GetControl(); + wxCHECK_MSG(Ok(), NULL, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->GetControl(); } -void wxSheetCellEditor::SetControl(wxWindow* control) +void wxSheetCellEditor::SetControl(wxWindow *control) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->SetControl(control); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->SetControl(control); } void wxSheetCellEditor::DestroyControl() { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->DestroyControl(); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->DestroyControl(); } -void wxSheetCellEditor::CreateEditor(wxWindow* parent, wxWindowID id, - wxEvtHandler* evtHandler, wxSheet* sheet) +void wxSheetCellEditor::CreateEditor(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler, + wxSheet *sheet) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->CreateEditor(parent, id, evtHandler, sheet); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->CreateEditor(parent, id, evtHandler, sheet); } -void wxSheetCellEditor::SetSize(const wxRect& rect, const wxSheetCellAttr &attr) +void wxSheetCellEditor::SetSize(const wxRect &rect, const wxSheetCellAttr &attr) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->SetSize(rect, attr); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->SetSize(rect, attr); } -wxSize wxSheetCellEditor::GetBestSize(wxSheet& grid, const wxSheetCellAttr& attr, - const wxSheetCoords& coords) +wxSize wxSheetCellEditor::GetBestSize(wxSheet &grid, const wxSheetCellAttr &attr, + const wxSheetCoords &coords) { - wxCHECK_MSG(Ok(), grid.GetCellSize(coords), wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->GetBestSize(grid, attr, coords); + wxCHECK_MSG(Ok(), grid.GetCellSize(coords), wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->GetBestSize(grid, attr, coords); } void wxSheetCellEditor::Show(bool show, const wxSheetCellAttr &attr) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->Show(show, attr); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->Show(show, attr); } -void wxSheetCellEditor::PaintBackground(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected) +void wxSheetCellEditor::PaintBackground(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect, const wxSheetCoords &coords, + bool isSelected) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->PaintBackground(sheet, attr, dc, rect, coords, isSelected); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->PaintBackground(sheet, attr, dc, rect, coords, isSelected); } -void wxSheetCellEditor::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) +void wxSheetCellEditor::BeginEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->BeginEdit(coords, sheet); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->BeginEdit(coords, sheet); } -bool wxSheetCellEditor::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) +bool wxSheetCellEditor::EndEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->EndEdit(coords, sheet); + wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->EndEdit(coords, sheet); } void wxSheetCellEditor::ResetValue() { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->ResetValue(); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->ResetValue(); } -bool wxSheetCellEditor::IsAcceptedKey(wxKeyEvent& event) +bool wxSheetCellEditor::IsAcceptedKey(wxKeyEvent &event) { - wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->IsAcceptedKey(event); + wxCHECK_MSG(Ok(), false, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->IsAcceptedKey(event); } -void wxSheetCellEditor::StartingKey(wxKeyEvent& event) +void wxSheetCellEditor::StartingKey(wxKeyEvent &event) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->StartingKey(event); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->StartingKey(event); } void wxSheetCellEditor::StartingClick() { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->StartingClick(); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->StartingClick(); } -void wxSheetCellEditor::HandleReturn(wxKeyEvent& event) +void wxSheetCellEditor::HandleReturn(wxKeyEvent &event) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->HandleReturn(event); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->HandleReturn(event); } -bool wxSheetCellEditor::OnKeyDown(wxKeyEvent& event) +bool wxSheetCellEditor::OnKeyDown(wxKeyEvent &event) { - wxCHECK_MSG(Ok(), true, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->OnKeyDown(event); + wxCHECK_MSG(Ok(), true, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->OnKeyDown(event); } -bool wxSheetCellEditor::OnChar(wxKeyEvent& event) +bool wxSheetCellEditor::OnChar(wxKeyEvent &event) { - wxCHECK_MSG(Ok(), true, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->OnChar(event); + wxCHECK_MSG(Ok(), true, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->OnChar(event); } -void wxSheetCellEditor::SetParameters(const wxString& params) +void wxSheetCellEditor::SetParameters(const wxString ¶ms) { - wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); - M_CELLEDITORDATA->SetParameters(params); + wxCHECK_RET(Ok(), wxT("wxSheetCellEditor not created")); + M_CELLEDITORDATA->SetParameters(params); } wxString wxSheetCellEditor::GetValue() const { - wxCHECK_MSG(Ok(), wxEmptyString, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->GetValue(); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->GetValue(); } wxString wxSheetCellEditor::GetInitValue() const { - wxCHECK_MSG(Ok(), wxEmptyString, wxT("wxSheetCellEditor not created")); - return M_CELLEDITORDATA->GetInitValue(); + wxCHECK_MSG(Ok(), wxEmptyString, wxT("wxSheetCellEditor not created")); + return M_CELLEDITORDATA->GetInitValue(); } -bool wxSheetCellEditor::Copy(const wxSheetCellEditor& other) +bool wxSheetCellEditor::Copy(const wxSheetCellEditor &other) { - wxCHECK_MSG(other.Ok(), false, wxT("wxSheetCellEditor not created")); + wxCHECK_MSG(other.Ok(), false, wxT("wxSheetCellEditor not created")); - UnRef(); - m_refData = ((wxSheetCellEditorRefData*)other.m_refData)->Clone(); - return true; + UnRef(); + m_refData = ((wxSheetCellEditorRefData *)other.m_refData)->Clone(); + return true; } // ---------------------------------------------------------------------------- @@ -288,124 +282,120 @@ bool wxSheetCellEditor::Copy(const wxSheetCellEditor& other) // ---------------------------------------------------------------------------- wxSheetCellEditorRefData::~wxSheetCellEditorRefData() { - if (GetControl()) - DestroyControl(); + if (GetControl()) { + DestroyControl(); + } } -bool wxSheetCellEditorRefData::IsShown() const -{ - return GetControl() && GetControl()->IsShown(); -} +bool wxSheetCellEditorRefData::IsShown() const { return GetControl() && GetControl()->IsShown(); } -void wxSheetCellEditorRefData::CreateEditor(wxWindow* WXUNUSED(parent), - wxWindowID WXUNUSED(id), - wxEvtHandler* evtHandler, - wxSheet* WXUNUSED(sheet)) +void wxSheetCellEditorRefData::CreateEditor(wxWindow *WXUNUSED(parent), wxWindowID WXUNUSED(id), + wxEvtHandler *evtHandler, wxSheet *WXUNUSED(sheet)) { - if (evtHandler && GetControl()) - GetControl()->PushEventHandler(evtHandler); + if (evtHandler && GetControl()) { + GetControl()->PushEventHandler(evtHandler); + } } -void wxSheetCellEditorRefData::SetControl(wxWindow* control) +void wxSheetCellEditorRefData::SetControl(wxWindow *control) { - DestroyControl(); - m_control = control; + DestroyControl(); + m_control = control; } void wxSheetCellEditorRefData::DestroyControl() { - if (m_control) - { - wxWindow *win = m_control; - m_control = NULL; - - // if pushed event handler, pop and delete the handler - if (win != win->GetEventHandler()) - win->PopEventHandler(true); + if (m_control) { + wxWindow *win = m_control; + m_control = NULL; - win->Destroy(); + // if pushed event handler, pop and delete the handler + if (win != win->GetEventHandler()) { + win->PopEventHandler(true); } -} -void wxSheetCellEditorRefData::PaintBackground(wxSheet& , const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& , bool ) -{ - // erase the background because we might not fill the cell - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(wxBrush(attr.GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); - - // only draw exactly what's needed -/* FIXME - the checkbox in GTK doesn't draw it's full background - wxRect ctrlRect(GetControl()->GetRect()); - - // top - if (ctrlRect.GetTop() > rect.GetTop()) - dc.DrawRectangle(wxRect(rect.x, rect.y, - rect.width, - ctrlRect.GetTop()-rect.GetTop())); - // bottom - if (ctrlRect.GetBottom() < rect.GetBottom()) - dc.DrawRectangle(wxRect(rect.x, ctrlRect.GetBottom(), - rect.width, - rect.GetBottom()-ctrlRect.GetBottom())); - // left - if (ctrlRect.GetLeft() > rect.GetLeft()) - dc.DrawRectangle(wxRect(rect.x, ctrlRect.y, - ctrlRect.GetLeft() - rect.GetLeft(), - ctrlRect.height)); - // right - if (ctrlRect.GetRight() < rect.GetRight()) - dc.DrawRectangle(wxRect(ctrlRect.GetRight(), ctrlRect.y, - rect.GetRight() - ctrlRect.GetRight(), - ctrlRect.height)); -*/ - dc.DrawRectangle(rect); - // redraw the control we just painted over - if (GetControl()) - GetControl()->Refresh(); + win->Destroy(); + } +} + +void wxSheetCellEditorRefData::PaintBackground(wxSheet &, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect, const wxSheetCoords &, bool) +{ + // erase the background because we might not fill the cell + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(attr.GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); + + // only draw exactly what's needed + /* FIXME - the checkbox in GTK doesn't draw it's full background + wxRect ctrlRect(GetControl()->GetRect()); + + // top + if (ctrlRect.GetTop() > rect.GetTop()) + dc.DrawRectangle(wxRect(rect.x, rect.y, + rect.width, + ctrlRect.GetTop()-rect.GetTop())); + // bottom + if (ctrlRect.GetBottom() < rect.GetBottom()) + dc.DrawRectangle(wxRect(rect.x, ctrlRect.GetBottom(), + rect.width, + rect.GetBottom()-ctrlRect.GetBottom())); + // left + if (ctrlRect.GetLeft() > rect.GetLeft()) + dc.DrawRectangle(wxRect(rect.x, ctrlRect.y, + ctrlRect.GetLeft() - rect.GetLeft(), + ctrlRect.height)); + // right + if (ctrlRect.GetRight() < rect.GetRight()) + dc.DrawRectangle(wxRect(ctrlRect.GetRight(), ctrlRect.y, + rect.GetRight() - ctrlRect.GetRight(), + ctrlRect.height)); + */ + dc.DrawRectangle(rect); + // redraw the control we just painted over + if (GetControl()) { + GetControl()->Refresh(); + } } void wxSheetCellEditorRefData::Show(bool show, const wxSheetCellAttr &attr) { - wxCHECK_RET(GetControl(), wxT("wxSheetCellEditor not created")); + wxCHECK_RET(GetControl(), wxT("wxSheetCellEditor not created")); - // set the colours/fonts if we have any - if ( show && attr.Ok() ) - { - GetControl()->SetForegroundColour(attr.GetForegroundColour()); + // set the colours/fonts if we have any + if (show && attr.Ok()) { + GetControl()->SetForegroundColour(attr.GetForegroundColour()); - // FIXME this is weird, in GTK you can't set the background of a textctrl - // to the default window background colour, ie. label textctrls - // this doesn't happen anymore in > 2.5.3 needs test in 2.4 maybe - //wxColour c = attr.GetBackgroundColour(); - //c.Set(wxMin(c.Red()+1, 255), c.Green(), c.Blue()); - //GetControl()->SetBackgroundColour(c); + // FIXME this is weird, in GTK you can't set the background of a textctrl + // to the default window background colour, ie. label textctrls + // this doesn't happen anymore in > 2.5.3 needs test in 2.4 maybe + // wxColour c = attr.GetBackgroundColour(); + // c.Set(wxMin(c.Red()+1, 255), c.Green(), c.Blue()); + // GetControl()->SetBackgroundColour(c); - GetControl()->SetBackgroundColour(attr.GetBackgroundColour()); - GetControl()->SetFont(attr.GetFont()); - } + GetControl()->SetBackgroundColour(attr.GetBackgroundColour()); + GetControl()->SetFont(attr.GetFont()); + } - GetControl()->Show(show); + GetControl()->Show(show); } -void wxSheetCellEditorRefData::SetSize(const wxRect& rect, const wxSheetCellAttr &) +void wxSheetCellEditorRefData::SetSize(const wxRect &rect, const wxSheetCellAttr &) { - wxCHECK_RET(GetControl(), wxT("wxSheetCellEditor not created")); - GetControl()->SetSize(rect, wxSIZE_ALLOW_MINUS_ONE); + wxCHECK_RET(GetControl(), wxT("wxSheetCellEditor not created")); + GetControl()->SetSize(rect, wxSIZE_ALLOW_MINUS_ONE); } -wxSize wxSheetCellEditorRefData::GetBestSize(wxSheet& grid, const wxSheetCellAttr& , - const wxSheetCoords& coords) +wxSize wxSheetCellEditorRefData::GetBestSize(wxSheet &grid, const wxSheetCellAttr &, + const wxSheetCoords &coords) { - wxCHECK_MSG(GetControl(), grid.GetCellSize(coords), wxT("wxSheetCellEditor not created")); - return GetControl()->GetBestSize(); + wxCHECK_MSG(GetControl(), grid.GetCellSize(coords), wxT("wxSheetCellEditor not created")); + return GetControl()->GetBestSize(); } -bool wxSheetCellEditorRefData::IsAcceptedKey(wxKeyEvent& event) +bool wxSheetCellEditorRefData::IsAcceptedKey(wxKeyEvent &event) { - // accept the simple key presses, not anything with Ctrl/Alt - return !(event.ControlDown() || event.AltDown()); + // accept the simple key presses, not anything with Ctrl/Alt + return !(event.ControlDown() || event.AltDown()); } // ---------------------------------------------------------------------------- @@ -413,251 +403,259 @@ bool wxSheetCellEditorRefData::IsAcceptedKey(wxKeyEvent& event) // ---------------------------------------------------------------------------- #if wxUSE_TEXTCTRL -void wxSheetCellTextEditorRefData::CreateEditor(wxWindow* parent, - wxWindowID id, - wxEvtHandler* evtHandler, - wxSheet* sheet) +void wxSheetCellTextEditorRefData::CreateEditor(wxWindow *parent, wxWindowID id, + wxEvtHandler *evtHandler, wxSheet *sheet) { - SetControl(new wxTextCtrl(parent, id, wxEmptyString, - wxDefaultPosition, wxDefaultSize //,wxBORDER_NONE + SetControl(new wxTextCtrl(parent, id, wxEmptyString, wxDefaultPosition, + wxDefaultSize //,wxBORDER_NONE #if defined(__WXMSW__) - , wxTE_PROCESS_TAB + , + wxTE_PROCESS_TAB #endif // defined(__WXMSW__) - )); + )); - // set max length allowed in the textctrl, if the parameter was set - if (m_maxChars != 0) - ((wxTextCtrl*)GetControl())->SetMaxLength(m_maxChars); + // set max length allowed in the textctrl, if the parameter was set + if (m_maxChars != 0) { + ((wxTextCtrl *)GetControl())->SetMaxLength(m_maxChars); + } - wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); + wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } -void wxSheetCellTextEditorRefData::SetSize(const wxRect& rectOrig, const wxSheetCellAttr &attr) +void wxSheetCellTextEditorRefData::SetSize(const wxRect &rectOrig, const wxSheetCellAttr &attr) { - wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); - wxRect rect(rectOrig); + wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); + wxRect rect(rectOrig); - // Put the control inside the grid lines on all sides. + // Put the control inside the grid lines on all sides. #if defined(__WXGTK__) - // these are good for GTK 1.2, wx ver 2.5 - //if (rect.x != 0) rect.x += 1; - //if (rect.y != 0) rect.y += 1; + // these are good for GTK 1.2, wx ver 2.5 + // if (rect.x != 0) rect.x += 1; + // if (rect.y != 0) rect.y += 1; #elif defined(__WXMSW__) - // This works for wxMSW ver 2.5 - //if (rect.x != 0) rect.x += 1; - //if (rect.y != 0) rect.y += 1; + // This works for wxMSW ver 2.5 + // if (rect.x != 0) rect.x += 1; + // if (rect.y != 0) rect.y += 1; #elif defined(__WXMOTIF__) - // This is untested ??? - int extra_x = ( rect.x > 2 ) ? 2 : 1; - int extra_y = ( rect.y > 2 ) ? 2 : 1; - extra_x *= 2; - extra_y *= 2; + // This is untested ??? + int extra_x = (rect.x > 2) ? 2 : 1; + int extra_y = (rect.y > 2) ? 2 : 1; + extra_x *= 2; + extra_y *= 2; - rect.SetLeft( wxMax(0, rect.x - extra_x) ); - rect.SetTop( wxMax(0, rect.y - extra_y) ); - rect.SetRight( rect.GetRight() + 2*extra_x ); - rect.SetBottom( rect.GetBottom() + 2*extra_y ); + rect.SetLeft(wxMax(0, rect.x - extra_x)); + rect.SetTop(wxMax(0, rect.y - extra_y)); + rect.SetRight(rect.GetRight() + 2 * extra_x); + rect.SetBottom(rect.GetBottom() + 2 * extra_y); #endif - wxSheetCellEditorRefData::SetSize(rect, attr); + wxSheetCellEditorRefData::SetSize(rect, attr); } -void wxSheetCellTextEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) +void wxSheetCellTextEditorRefData::BeginEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_RET(IsCreated() && sheet, wxT("The wxSheetCellEditor must be Created first!")); + wxCHECK_RET(IsCreated() && sheet, wxT("The wxSheetCellEditor must be Created first!")); - m_startValue = sheet->GetCellValue(coords); - m_maxLength = 0; - DoBeginEdit(m_startValue); + m_startValue = sheet->GetCellValue(coords); + m_maxLength = 0; + DoBeginEdit(m_startValue); } -void wxSheetCellTextEditorRefData::DoBeginEdit(const wxString& startValue) +void wxSheetCellTextEditorRefData::DoBeginEdit(const wxString &startValue) { - wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); - GetTextCtrl()->SetValue(startValue); - GetTextCtrl()->SetInsertionPointEnd(); - GetTextCtrl()->SetSelection(-1,-1); - GetTextCtrl()->SetFocus(); + wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); + GetTextCtrl()->SetValue(startValue); + GetTextCtrl()->SetInsertionPointEnd(); + GetTextCtrl()->SetSelection(-1, -1); + GetTextCtrl()->SetFocus(); } -bool wxSheetCellTextEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) +bool wxSheetCellTextEditorRefData::EndEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); + wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); - wxString value = GetTextCtrl()->GetValue(); - bool changed = (value != m_startValue); + wxString value = GetTextCtrl()->GetValue(); + bool changed = (value != m_startValue); - if (changed) - { - if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) - changed = false; - else - sheet->SetCellValue(coords, value); + if (changed) { + if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) { + changed = false; } + else { + sheet->SetCellValue(coords, value); + } + } - m_startValue.Clear(); - m_maxLength = 0; + m_startValue.Clear(); + m_maxLength = 0; - return changed; + return changed; } void wxSheetCellTextEditorRefData::ResetValue() { - wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); - DoResetValue(m_startValue); + wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); + DoResetValue(m_startValue); } -void wxSheetCellTextEditorRefData::DoResetValue(const wxString& startValue) +void wxSheetCellTextEditorRefData::DoResetValue(const wxString &startValue) { - wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); - GetTextCtrl()->SetValue(startValue); - GetTextCtrl()->SetInsertionPointEnd(); + wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); + GetTextCtrl()->SetValue(startValue); + GetTextCtrl()->SetInsertionPointEnd(); } -bool wxSheetCellTextEditorRefData::IsAcceptedKey(wxKeyEvent& event) +bool wxSheetCellTextEditorRefData::IsAcceptedKey(wxKeyEvent &event) { - if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) - { - int keycode = event.GetKeyCode(); - switch ( keycode ) - { - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - case WXK_MULTIPLY: - case WXK_NUMPAD_MULTIPLY: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - case WXK_DECIMAL: - case WXK_NUMPAD_DECIMAL: - case WXK_DIVIDE: - case WXK_NUMPAD_DIVIDE: - return true; - - default: - // accept 8 bit chars too if isprint() agrees - if ( (keycode < 255) && (wxIsprint(keycode)) ) - return true; - } + if (wxSheetCellEditorRefData::IsAcceptedKey(event)) { + int keycode = event.GetKeyCode(); + switch (keycode) { + case WXK_NUMPAD0: + case WXK_NUMPAD1: + case WXK_NUMPAD2: + case WXK_NUMPAD3: + case WXK_NUMPAD4: + case WXK_NUMPAD5: + case WXK_NUMPAD6: + case WXK_NUMPAD7: + case WXK_NUMPAD8: + case WXK_NUMPAD9: + case WXK_MULTIPLY: + case WXK_NUMPAD_MULTIPLY: + case WXK_ADD: + case WXK_NUMPAD_ADD: + case WXK_SUBTRACT: + case WXK_NUMPAD_SUBTRACT: + case WXK_DECIMAL: + case WXK_NUMPAD_DECIMAL: + case WXK_DIVIDE: + case WXK_NUMPAD_DIVIDE: + return true; + + default: + // accept 8 bit chars too if isprint() agrees + if ((keycode < 255) && (wxIsprint(keycode))) { + return true; + } } + } - return false; + return false; } -void wxSheetCellTextEditorRefData::StartingKey(wxKeyEvent& event) +void wxSheetCellTextEditorRefData::StartingKey(wxKeyEvent &event) { - wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); - if ( !GetTextCtrl()->EmulateKeyPress(event) ) - event.Skip(); + wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); + if (!GetTextCtrl()->EmulateKeyPress(event)) { + event.Skip(); + } } -void wxSheetCellTextEditorRefData::HandleReturn( wxKeyEvent& - WXUNUSED_GTK(WXUNUSED_MOTIF(event)) ) +void wxSheetCellTextEditorRefData::HandleReturn(wxKeyEvent &WXUNUSED_GTK(WXUNUSED_MOTIF(event))) { - wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); + wxCHECK_RET(IsCreated(), wxT("The wxSheetCellEditor must be Created first!")); #if defined(__WXMOTIF__) || defined(__WXGTK__) - // wxMotif needs a little extra help... - size_t pos = (size_t)( GetTextCtrl()->GetInsertionPoint() ); - wxString s( GetTextCtrl()->GetValue() ); - s = s.Left(pos) + wxT("\n") + s.Mid(pos); - GetTextCtrl()->SetValue(s); - GetTextCtrl()->SetInsertionPoint( pos ); + // wxMotif needs a little extra help... + size_t pos = (size_t)(GetTextCtrl()->GetInsertionPoint()); + wxString s(GetTextCtrl()->GetValue()); + s = s.Left(pos) + wxT("\n") + s.Mid(pos); + GetTextCtrl()->SetValue(s); + GetTextCtrl()->SetInsertionPoint(pos); #else - // the other ports can handle a Return key press - event.Skip(); + // the other ports can handle a Return key press + event.Skip(); #endif // defined(__WXMOTIF__) || defined(__WXGTK__) } -bool wxSheetCellTextEditorRefData::OnChar( wxKeyEvent& WXUNUSED(event) ) +bool wxSheetCellTextEditorRefData::OnChar(wxKeyEvent &WXUNUSED(event)) { - wxCHECK_MSG(IsCreated(), true, wxT("The wxSheetCellEditor must be Created first!")); - // This function is used to expand the textctrl as you type - // it doesn't stop the event, just looks at it - wxString value = GetTextCtrl()->GetValue(); - if (int(value.Length()) <= m_maxLength) - return true; - - m_maxLength = value.Length(); + wxCHECK_MSG(IsCreated(), true, wxT("The wxSheetCellEditor must be Created first!")); + // This function is used to expand the textctrl as you type + // it doesn't stop the event, just looks at it + wxString value = GetTextCtrl()->GetValue(); + if (int(value.Length()) <= m_maxLength) { + return true; + } - wxRect rect(GetTextCtrl()->GetRect()); - int clientWidth = GetTextCtrl()->GetParent()->GetClientSize().x; - // already at edge of window, maybe the win should scroll? - if (rect.GetRight() >= clientWidth) - return true; + m_maxLength = value.Length(); - int w, h; - wxFont font = GetTextCtrl()->GetFont(); - GetTextCtrl()->GetTextExtent(value, &w, &h, NULL, NULL, &font); + wxRect rect(GetTextCtrl()->GetRect()); + int clientWidth = GetTextCtrl()->GetParent()->GetClientSize().x; + // already at edge of window, maybe the win should scroll? + if (rect.GetRight() >= clientWidth) { + return true; + } - // can't just use w/value.Len since it might be "iii", too small for "WWW" - int chW; - GetTextCtrl()->GetTextExtent(wxT("W"), &chW, &h, NULL, NULL, &font); - int extra = int(chW*1.5); - //if (rect.width < w+extra) - //GetTextCtrl()->SetSize(wxMin(w+extra, clientWidth-rect.x), rect.height); + int w, h; + wxFont font = GetTextCtrl()->GetFont(); + GetTextCtrl()->GetTextExtent(value, &w, &h, NULL, NULL, &font); - w += extra; + // can't just use w/value.Len since it might be "iii", too small for "WWW" + int chW; + GetTextCtrl()->GetTextExtent(wxT("W"), &chW, &h, NULL, NULL, &font); + int extra = int(chW * 1.5); + // if (rect.width < w+extra) + // GetTextCtrl()->SetSize(wxMin(w+extra, clientWidth-rect.x), rect.height); - wxSheet* sheet = wxDynamicCast(GetTextCtrl()->GetParent()->GetParent(), wxSheet); - if (!sheet) - return true; + w += extra; - wxSheetCoords c(sheet->GetEditControlCoords()); - if (!sheet->GetAttrOverflow(c)) - return true; + wxSheet *sheet = wxDynamicCast(GetTextCtrl()->GetParent()->GetParent(), wxSheet); + if (!sheet) { + return true; + } - wxSheetCoords oneCell(1,1); - int numCols = sheet->GetNumberCols(); - wxRect scrollRect(sheet->CalcUnscrolledRect(rect)); - for (c.m_col = sheet->XToGridCol(scrollRect.GetRight())+1; c.m_col < numCols; c.m_col++) - { - wxSheetCoords cellSize(sheet->GetCellSpan(c)); - // looks weird going over a spanned cell - if ((rect.width < w) && (rect.GetRight() < clientWidth) && (cellSize == oneCell)) - rect.width += sheet->GetColWidth(c.m_col); - else - break; + wxSheetCoords c(sheet->GetEditControlCoords()); + if (!sheet->GetAttrOverflow(c)) { + return true; + } + + wxSheetCoords oneCell(1, 1); + int numCols = sheet->GetNumberCols(); + wxRect scrollRect(sheet->CalcUnscrolledRect(rect)); + for (c.m_col = sheet->XToGridCol(scrollRect.GetRight()) + 1; c.m_col < numCols; c.m_col++) { + wxSheetCoords cellSize(sheet->GetCellSpan(c)); + // looks weird going over a spanned cell + if ((rect.width < w) && (rect.GetRight() < clientWidth) && (cellSize == oneCell)) { + rect.width += sheet->GetColWidth(c.m_col); + } + else { + break; } + } - // clip width to window size - rect.width = wxMin(rect.width, clientWidth - rect.x); - GetTextCtrl()->SetSize(rect.width, rect.height); + // clip width to window size + rect.width = wxMin(rect.width, clientWidth - rect.x); + GetTextCtrl()->SetSize(rect.width, rect.height); - return true; + return true; } -void wxSheetCellTextEditorRefData::SetParameters(const wxString& params) +void wxSheetCellTextEditorRefData::SetParameters(const wxString ¶ms) { - if ( params.IsEmpty() ) - m_maxChars = 0; // reset to default - else - { - long tmp; - if ( !params.ToLong(&tmp) ) - wxLogDebug(_T("Invalid wxSheetCellTextEditor parameter string '%s' ignored"), params.c_str()); - else - m_maxChars = (size_t)tmp; + if (params.IsEmpty()) { + m_maxChars = 0; // reset to default + } + else { + long tmp; + if (!params.ToLong(&tmp)) { + wxLogDebug(_T("Invalid wxSheetCellTextEditor parameter string '%s' ignored"), + params.c_str()); + } + else { + m_maxChars = (size_t)tmp; } + } } wxString wxSheetCellTextEditorRefData::GetValue() const { - wxCHECK_MSG(IsCreated(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); - return GetTextCtrl()->GetValue(); + wxCHECK_MSG(IsCreated(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); + return GetTextCtrl()->GetValue(); } #endif // wxUSE_TEXTCTRL @@ -667,16 +665,13 @@ wxString wxSheetCellTextEditorRefData::GetValue() const // ---------------------------------------------------------------------------- #if wxUSE_TEXTCTRL -void wxSheetCellAutoWrapStringEditorRefData::CreateEditor(wxWindow* parent, - wxWindowID id, - wxEvtHandler* evtHandler, - wxSheet* sheet) +void wxSheetCellAutoWrapStringEditorRefData::CreateEditor(wxWindow *parent, wxWindowID id, + wxEvtHandler *evtHandler, wxSheet *sheet) { - SetControl( new wxTextCtrl(parent, id, wxEmptyString, - wxDefaultPosition, wxDefaultSize, - wxTE_MULTILINE | wxTE_RICH) ); + SetControl(new wxTextCtrl(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, + wxTE_MULTILINE | wxTE_RICH)); - wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); + wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } #endif // wxUSE_TEXTCTRL @@ -685,427 +680,375 @@ void wxSheetCellAutoWrapStringEditorRefData::CreateEditor(wxWindow* parent, // ---------------------------------------------------------------------------- #if defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) -bool wxSheetCellNumberEditorRefData::Copy(const wxSheetCellNumberEditorRefData& other) +bool wxSheetCellNumberEditorRefData::Copy(const wxSheetCellNumberEditorRefData &other) { - m_min = other.m_min; - m_max = other.m_max; - return wxSheetCellTextEditorRefData::Copy(other); + m_min = other.m_min; + m_max = other.m_max; + return wxSheetCellTextEditorRefData::Copy(other); } -void wxSheetCellNumberEditorRefData::CreateEditor(wxWindow* parent, - wxWindowID id, - wxEvtHandler* evtHandler, - wxSheet* sheet) +void wxSheetCellNumberEditorRefData::CreateEditor(wxWindow *parent, wxWindowID id, + wxEvtHandler *evtHandler, wxSheet *sheet) { - if ( HasRange() ) - { - // create a spin ctrl - SetControl( new wxSpinCtrl(parent, wxID_ANY, wxEmptyString, - wxDefaultPosition, wxDefaultSize, - wxSP_ARROW_KEYS, m_min, m_max) ); + if (HasRange()) { + // create a spin ctrl + SetControl(new wxSpinCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, + wxSP_ARROW_KEYS, m_min, m_max)); - wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); - } - else - { - // just a text control - wxSheetCellTextEditorRefData::CreateEditor(parent, id, evtHandler, sheet); + wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); + } + else { + // just a text control + wxSheetCellTextEditorRefData::CreateEditor(parent, id, evtHandler, sheet); #if wxUSE_VALIDATORS - GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); + GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); #endif // wxUSE_VALIDATORS + } +} + +void wxSheetCellNumberEditorRefData::BeginEdit(const wxSheetCoords &coords, wxSheet *sheet) +{ + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + // first get the value + wxSheetTable *table = sheet->GetTable(); + if (table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER)) { + m_startValue = table->GetValueAsLong(coords); + } + else { + m_startValue = 0; + wxString sValue = sheet->GetCellValue(coords); + if (!sValue.IsEmpty() && !sValue.ToLong(&m_startValue)) { + wxFAIL_MSG(_T("this cell doesn't have numeric value")); + return; } -} - -void wxSheetCellNumberEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) -{ - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - // first get the value - wxSheetTable *table = sheet->GetTable(); - if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) - { - m_startValue = table->GetValueAsLong(coords); - } - else - { - m_startValue = 0; - wxString sValue = sheet->GetCellValue(coords); - if (!sValue.IsEmpty() && !sValue.ToLong(&m_startValue)) - { - wxFAIL_MSG( _T("this cell doesn't have numeric value") ); - return; - } - } + } - if ( HasRange() ) - { - GetSpinCtrl()->SetValue((int)m_startValue); - GetSpinCtrl()->SetFocus(); - } - else - { - DoBeginEdit(GetInitValue()); - } + if (HasRange()) { + GetSpinCtrl()->SetValue((int)m_startValue); + GetSpinCtrl()->SetFocus(); + } + else { + DoBeginEdit(GetInitValue()); + } } -bool wxSheetCellNumberEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) +bool wxSheetCellNumberEditorRefData::EndEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); + wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); - bool changed; - long value = 0; - long oldValue = m_startValue; - wxString text; + bool changed; + long value = 0; + long oldValue = m_startValue; + wxString text; - if ( HasRange() ) - { - value = GetSpinCtrl()->GetValue(); - changed = value != oldValue; - if (changed) - text = wxString::Format(wxT("%ld"), value); + if (HasRange()) { + value = GetSpinCtrl()->GetValue(); + changed = value != oldValue; + if (changed) { + text = wxString::Format(wxT("%ld"), value); } - else - { - text = GetTextCtrl()->GetValue(); - changed = (text.IsEmpty() || text.ToLong(&value)) && (value != oldValue); + } + else { + text = GetTextCtrl()->GetValue(); + changed = (text.IsEmpty() || text.ToLong(&value)) && (value != oldValue); + } + + if (changed) { + if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) { + return false; } - if ( changed ) - { - if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) - return false; - - if (sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_NUMBER)) - sheet->GetTable()->SetValueAsLong(coords, value); - else - sheet->GetTable()->SetValue(coords, text); + if (sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_NUMBER)) { + sheet->GetTable()->SetValueAsLong(coords, value); } + else { + sheet->GetTable()->SetValue(coords, text); + } + } - return changed; + return changed; } void wxSheetCellNumberEditorRefData::ResetValue() { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - if ( HasRange() ) - GetSpinCtrl()->SetValue((int)m_startValue); - else - DoResetValue(GetInitValue()); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + if (HasRange()) { + GetSpinCtrl()->SetValue((int)m_startValue); + } + else { + DoResetValue(GetInitValue()); + } } -bool wxSheetCellNumberEditorRefData::IsAcceptedKey(wxKeyEvent& event) +bool wxSheetCellNumberEditorRefData::IsAcceptedKey(wxKeyEvent &event) { - if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) - { - int keycode = event.GetKeyCode(); - switch ( keycode ) - { - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - case WXK_UP: - case WXK_DOWN: - return true; - - default: - if ( (keycode < 128) && wxIsdigit(keycode) ) - return true; - } + if (wxSheetCellEditorRefData::IsAcceptedKey(event)) { + int keycode = event.GetKeyCode(); + switch (keycode) { + case WXK_NUMPAD0: + case WXK_NUMPAD1: + case WXK_NUMPAD2: + case WXK_NUMPAD3: + case WXK_NUMPAD4: + case WXK_NUMPAD5: + case WXK_NUMPAD6: + case WXK_NUMPAD7: + case WXK_NUMPAD8: + case WXK_NUMPAD9: + case WXK_ADD: + case WXK_NUMPAD_ADD: + case WXK_SUBTRACT: + case WXK_NUMPAD_SUBTRACT: + case WXK_UP: + case WXK_DOWN: + return true; + + default: + if ((keycode < 128) && wxIsdigit(keycode)) { + return true; + } } + } - return false; + return false; } -void wxSheetCellNumberEditorRefData::StartingKey(wxKeyEvent& event) +void wxSheetCellNumberEditorRefData::StartingKey(wxKeyEvent &event) { - if ( !HasRange() ) - { - int keycode = event.GetKeyCode(); - if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' - || keycode == WXK_NUMPAD0 - || keycode == WXK_NUMPAD1 - || keycode == WXK_NUMPAD2 - || keycode == WXK_NUMPAD3 - || keycode == WXK_NUMPAD4 - || keycode == WXK_NUMPAD5 - || keycode == WXK_NUMPAD6 - || keycode == WXK_NUMPAD7 - || keycode == WXK_NUMPAD8 - || keycode == WXK_NUMPAD9 - || keycode == WXK_ADD - || keycode == WXK_NUMPAD_ADD - || keycode == WXK_SUBTRACT - || keycode == WXK_NUMPAD_SUBTRACT) - { - wxSheetCellTextEditorRefData::StartingKey(event); - - // skip Skip() below - return; - } + if (!HasRange()) { + int keycode = event.GetKeyCode(); + if (wxIsdigit(keycode) || keycode == '+' || keycode == '-' || keycode == WXK_NUMPAD0 || + keycode == WXK_NUMPAD1 || keycode == WXK_NUMPAD2 || keycode == WXK_NUMPAD3 || + keycode == WXK_NUMPAD4 || keycode == WXK_NUMPAD5 || keycode == WXK_NUMPAD6 || + keycode == WXK_NUMPAD7 || keycode == WXK_NUMPAD8 || keycode == WXK_NUMPAD9 || + keycode == WXK_ADD || keycode == WXK_NUMPAD_ADD || keycode == WXK_SUBTRACT || + keycode == WXK_NUMPAD_SUBTRACT) { + wxSheetCellTextEditorRefData::StartingKey(event); + + // skip Skip() below + return; } + } - event.Skip(); + event.Skip(); } -void wxSheetCellNumberEditorRefData::SetParameters(const wxString& params) +void wxSheetCellNumberEditorRefData::SetParameters(const wxString ¶ms) { - if ( params.IsEmpty() ) - { - m_min = m_max = -1; // reset to default - } - else - { - long tmp; - if ( params.BeforeFirst(_T(',')).ToLong(&tmp) ) - { - m_min = (int)tmp; - - if ( params.AfterFirst(_T(',')).ToLong(&tmp) ) - { - m_max = (int)tmp; + if (params.IsEmpty()) { + m_min = m_max = -1; // reset to default + } + else { + long tmp; + if (params.BeforeFirst(_T(',')).ToLong(&tmp)) { + m_min = (int)tmp; - // skip the error message below - return; - } - } + if (params.AfterFirst(_T(',')).ToLong(&tmp)) { + m_max = (int)tmp; - wxLogDebug(_T("Invalid wxSheetCellNumberEditor parameter string '%s' ignored"), params.c_str()); + // skip the error message below + return; + } } + + wxLogDebug(_T("Invalid wxSheetCellNumberEditor parameter string '%s' ignored"), + params.c_str()); + } } // return the value in the spin control if it is there (the text control otherwise) wxString wxSheetCellNumberEditorRefData::GetValue() const { - wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); - wxString s; + wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); + wxString s; - if ( HasRange() ) - { - long value = GetSpinCtrl()->GetValue(); - s.Printf(wxT("%ld"), value); - } - else - { - s = GetTextCtrl()->GetValue(); - } - return s; + if (HasRange()) { + long value = GetSpinCtrl()->GetValue(); + s.Printf(wxT("%ld"), value); + } + else { + s = GetTextCtrl()->GetValue(); + } + return s; } wxString wxSheetCellNumberEditorRefData::GetInitValue() const { - return wxString::Format(_T("%ld"), m_startValue); + return wxString::Format(_T("%ld"), m_startValue); } -#endif //defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) +#endif // defined(wxUSE_TEXTCTRL) && defined(wxUSE_SPINCTRL) // ---------------------------------------------------------------------------- // wxSheetCellFloatEditorRefData // ---------------------------------------------------------------------------- #if wxUSE_TEXTCTRL -bool wxSheetCellFloatEditorRefData::Copy(const wxSheetCellFloatEditorRefData& other) +bool wxSheetCellFloatEditorRefData::Copy(const wxSheetCellFloatEditorRefData &other) { - m_width = other.m_width; - m_precision = other.m_precision; - return wxSheetCellTextEditorRefData::Copy(other); + m_width = other.m_width; + m_precision = other.m_precision; + return wxSheetCellTextEditorRefData::Copy(other); } -void wxSheetCellFloatEditorRefData::CreateEditor(wxWindow* parent, - wxWindowID id, - wxEvtHandler* evtHandler, - wxSheet* sheet) +void wxSheetCellFloatEditorRefData::CreateEditor(wxWindow *parent, wxWindowID id, + wxEvtHandler *evtHandler, wxSheet *sheet) { - wxSheetCellTextEditorRefData::CreateEditor(parent, id, evtHandler, sheet); + wxSheetCellTextEditorRefData::CreateEditor(parent, id, evtHandler, sheet); #if wxUSE_VALIDATORS - GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); + GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); #endif // wxUSE_VALIDATORS } -void wxSheetCellFloatEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) -{ - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - // first get the value - wxSheetTable *table = sheet->GetTable(); - if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_FLOAT) ) - { - m_startValue = table->GetValueAsDouble(coords); - } - else - { - m_startValue = 0.0; - wxString sValue = sheet->GetCellValue(coords); - if (!sValue.ToDouble(&m_startValue) && !sValue.IsEmpty()) - { - wxFAIL_MSG( _T("this cell doesn't have float value") ); - return; - } +void wxSheetCellFloatEditorRefData::BeginEdit(const wxSheetCoords &coords, wxSheet *sheet) +{ + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + // first get the value + wxSheetTable *table = sheet->GetTable(); + if (table && table->CanGetValueAs(coords, wxSHEET_VALUE_FLOAT)) { + m_startValue = table->GetValueAsDouble(coords); + } + else { + m_startValue = 0.0; + wxString sValue = sheet->GetCellValue(coords); + if (!sValue.ToDouble(&m_startValue) && !sValue.IsEmpty()) { + wxFAIL_MSG(_T("this cell doesn't have float value")); + return; } + } - DoBeginEdit(GetInitValue()); + DoBeginEdit(GetInitValue()); } -bool wxSheetCellFloatEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) +bool wxSheetCellFloatEditorRefData::EndEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); - - double value = 0.0; - wxString text(GetTextCtrl()->GetValue()); - - if ( (text.IsEmpty() || text.ToDouble(&value)) && (value != m_startValue) ) - { - if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) - return false; + wxCHECK_MSG(IsCreated() && sheet, false, wxT("The wxSheetCellEditor must be Created first!")); - if (sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_FLOAT)) - sheet->GetTable()->SetValueAsDouble(coords, value); - else - sheet->GetTable()->SetValue(coords, text.IsEmpty() ? GetStringValue(value) : text); + double value = 0.0; + wxString text(GetTextCtrl()->GetValue()); - return true; + if ((text.IsEmpty() || text.ToDouble(&value)) && (value != m_startValue)) { + if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) { + return false; } - return false; -} - -void wxSheetCellFloatEditorRefData::ResetValue() -{ - DoResetValue(GetInitValue()); -} -void wxSheetCellFloatEditorRefData::StartingKey(wxKeyEvent& event) -{ - int keycode = event.GetKeyCode(); - char tmpbuf[2]; - tmpbuf[0] = (char) keycode; - tmpbuf[1] = '\0'; - wxString strbuf(tmpbuf, *wxConvCurrent); - bool is_decimal_point = ( strbuf == - wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) ); - if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' - || is_decimal_point - || keycode == WXK_NUMPAD0 - || keycode == WXK_NUMPAD1 - || keycode == WXK_NUMPAD2 - || keycode == WXK_NUMPAD3 - || keycode == WXK_NUMPAD4 - || keycode == WXK_NUMPAD5 - || keycode == WXK_NUMPAD6 - || keycode == WXK_NUMPAD7 - || keycode == WXK_NUMPAD8 - || keycode == WXK_NUMPAD9 - || keycode == WXK_ADD - || keycode == WXK_NUMPAD_ADD - || keycode == WXK_SUBTRACT - || keycode == WXK_NUMPAD_SUBTRACT) - { - wxSheetCellTextEditorRefData::StartingKey(event); - return; // skip Skip() below + if (sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_FLOAT)) { + sheet->GetTable()->SetValueAsDouble(coords, value); } - - event.Skip(); -} - -void wxSheetCellFloatEditorRefData::SetParameters(const wxString& params) -{ - if ( params.IsEmpty() ) - { - m_width = m_precision = -1; // reset to default + else { + sheet->GetTable()->SetValue(coords, text.IsEmpty() ? GetStringValue(value) : text); } - else - { - long tmp; - if ( params.BeforeFirst(_T(',')).ToLong(&tmp) ) - { - m_width = (int)tmp; - - if ( params.AfterFirst(_T(',')).ToLong(&tmp) ) - { - m_precision = (int)tmp; - return; // skip the error message below - } - } - - wxLogDebug(_T("Invalid wxSheetCellFloatEditor parameter string '%s' ignored"), params.c_str()); + + return true; + } + return false; +} + +void wxSheetCellFloatEditorRefData::ResetValue() { DoResetValue(GetInitValue()); } + +void wxSheetCellFloatEditorRefData::StartingKey(wxKeyEvent &event) +{ + int keycode = event.GetKeyCode(); + char tmpbuf[2]; + tmpbuf[0] = (char)keycode; + tmpbuf[1] = '\0'; + wxString strbuf(tmpbuf, *wxConvCurrent); + bool is_decimal_point = + (strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER)); + if (wxIsdigit(keycode) || keycode == '+' || keycode == '-' || is_decimal_point || + keycode == WXK_NUMPAD0 || keycode == WXK_NUMPAD1 || keycode == WXK_NUMPAD2 || + keycode == WXK_NUMPAD3 || keycode == WXK_NUMPAD4 || keycode == WXK_NUMPAD5 || + keycode == WXK_NUMPAD6 || keycode == WXK_NUMPAD7 || keycode == WXK_NUMPAD8 || + keycode == WXK_NUMPAD9 || keycode == WXK_ADD || keycode == WXK_NUMPAD_ADD || + keycode == WXK_SUBTRACT || keycode == WXK_NUMPAD_SUBTRACT) { + wxSheetCellTextEditorRefData::StartingKey(event); + return; // skip Skip() below + } + + event.Skip(); +} + +void wxSheetCellFloatEditorRefData::SetParameters(const wxString ¶ms) +{ + if (params.IsEmpty()) { + m_width = m_precision = -1; // reset to default + } + else { + long tmp; + if (params.BeforeFirst(_T(',')).ToLong(&tmp)) { + m_width = (int)tmp; + + if (params.AfterFirst(_T(',')).ToLong(&tmp)) { + m_precision = (int)tmp; + return; // skip the error message below + } } + + wxLogDebug(_T("Invalid wxSheetCellFloatEditor parameter string '%s' ignored"), params.c_str()); + } } wxString wxSheetCellFloatEditorRefData::GetStringValue(double value) const { - wxString fmt; - if ( m_width == -1 ) - { - // default width/precision - fmt = _T("%f"); - } - else if ( m_precision == -1 ) - { - // default precision - fmt.Printf(_T("%%%d.f"), m_width); - } - else - { - fmt.Printf(_T("%%%d.%df"), m_width, m_precision); - } + wxString fmt; + if (m_width == -1) { + // default width/precision + fmt = _T("%f"); + } + else if (m_precision == -1) { + // default precision + fmt.Printf(_T("%%%d.f"), m_width); + } + else { + fmt.Printf(_T("%%%d.%df"), m_width, m_precision); + } - return wxString::Format(fmt, value); + return wxString::Format(fmt, value); } -bool wxSheetCellFloatEditorRefData::IsAcceptedKey(wxKeyEvent& event) +bool wxSheetCellFloatEditorRefData::IsAcceptedKey(wxKeyEvent &event) { - if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) - { - int keycode = event.GetKeyCode(); - - switch ( keycode ) - { - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - case WXK_DECIMAL: - case WXK_NUMPAD_DECIMAL: - return true; - - default: - { - // additionally accept 'e' as in '1e+6', also '-', '+', and '.' - char tmpbuf[2]; - tmpbuf[0] = (char) keycode; - tmpbuf[1] = '\0'; - wxString strbuf(tmpbuf, *wxConvCurrent); - bool is_decimal_point = - ( strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, - wxLOCALE_CAT_NUMBER) ); - if ( (keycode < 128) && - (wxIsdigit(keycode) || tolower(keycode) == 'e' || - is_decimal_point || keycode == '+' || keycode == '-') ) - return true; - } - } + if (wxSheetCellEditorRefData::IsAcceptedKey(event)) { + int keycode = event.GetKeyCode(); + + switch (keycode) { + case WXK_NUMPAD0: + case WXK_NUMPAD1: + case WXK_NUMPAD2: + case WXK_NUMPAD3: + case WXK_NUMPAD4: + case WXK_NUMPAD5: + case WXK_NUMPAD6: + case WXK_NUMPAD7: + case WXK_NUMPAD8: + case WXK_NUMPAD9: + case WXK_ADD: + case WXK_NUMPAD_ADD: + case WXK_SUBTRACT: + case WXK_NUMPAD_SUBTRACT: + case WXK_DECIMAL: + case WXK_NUMPAD_DECIMAL: + return true; + + default: { + // additionally accept 'e' as in '1e+6', also '-', '+', and '.' + char tmpbuf[2]; + tmpbuf[0] = (char)keycode; + tmpbuf[1] = '\0'; + wxString strbuf(tmpbuf, *wxConvCurrent); + bool is_decimal_point = + (strbuf == wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER)); + if ((keycode < 128) && (wxIsdigit(keycode) || tolower(keycode) == 'e' || is_decimal_point || + keycode == '+' || keycode == '-')) { + return true; + } + } } + } - return false; + return false; } #endif // wxUSE_TEXTCTRL @@ -1135,172 +1078,163 @@ BEGIN_EVENT_TABLE( wxSheetCellBoolEditorControl, wxControl ) END_EVENT_TABLE() */ -void wxSheetCellBoolEditorRefData::CreateEditor(wxWindow* parent, - wxWindowID id, - wxEvtHandler* evtHandler, - wxSheet* sheet) +void wxSheetCellBoolEditorRefData::CreateEditor(wxWindow *parent, wxWindowID id, + wxEvtHandler *evtHandler, wxSheet *sheet) { - SetControl( new wxCheckBox(parent, id, wxEmptyString, - wxDefaultPosition, wxDefaultSize, - wxNO_BORDER) ); + SetControl( + new wxCheckBox(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxNO_BORDER)); - wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); + wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } -void wxSheetCellBoolEditorRefData::SetSize(const wxRect& r, const wxSheetCellAttr &attr) +void wxSheetCellBoolEditorRefData::SetSize(const wxRect &r, const wxSheetCellAttr &attr) { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - bool resize = false; - wxSize size = GetControl()->GetSize(); - wxCoord minSize = wxMin(r.width, r.height); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + bool resize = false; + wxSize size = GetControl()->GetSize(); + wxCoord minSize = wxMin(r.width, r.height); - // check if the checkbox is not too big/small for this cell - wxSize sizeBest = GetControl()->GetBestSize(); - if ( !(size == sizeBest) ) - { - // reset to default size if it had been made smaller - size = sizeBest; - resize = true; - } + // check if the checkbox is not too big/small for this cell + wxSize sizeBest = GetControl()->GetBestSize(); + if (!(size == sizeBest)) { + // reset to default size if it had been made smaller + size = sizeBest; + resize = true; + } - if ( (size.x >= minSize) || (size.y >= minSize) ) - { - // leave 1 pixel margin - size.x = size.y = minSize - 2; - resize = true; - } + if ((size.x >= minSize) || (size.y >= minSize)) { + // leave 1 pixel margin + size.x = size.y = minSize - 2; + resize = true; + } - if ( resize ) - { - GetControl()->SetSize(size); - } + if (resize) { + GetControl()->SetSize(size); + } - // position it in the centre of the rectangle (TODO: support alignment?) + // position it in the centre of the rectangle (TODO: support alignment?) -#if defined(__WXGTK__) || defined (__WXMOTIF__) - // the checkbox without label still has some space to the right in wxGTK, - // so shift it to the right - size.x -= 8; +#if defined(__WXGTK__) || defined(__WXMOTIF__) + // the checkbox without label still has some space to the right in wxGTK, + // so shift it to the right + size.x -= 8; #elif defined(__WXMSW__) - // here too, but in other way - size.x += 1; - size.y -= 2; + // here too, but in other way + size.x += 1; + size.y -= 2; #endif // defined(__WXGTK__) || defined (__WXMOTIF__) - int align = attr.Ok() ? attr.GetAlignment() : wxALIGN_CENTRE; - - int x = 0, y = 0; - if ((align & wxALIGN_RIGHT) != 0) - { - x = r.x + r.width - size.x - 2; - y = r.y + r.height/2 - size.y/2; - } - else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) - { - x = r.x + r.width/2 - size.x/2; - y = r.y + r.height/2 - size.y/2; - } - else // wxALIGN_LEFT - { - x = r.x + 2; + int align = attr.Ok() ? attr.GetAlignment() : wxALIGN_CENTRE; + + int x = 0, y = 0; + if ((align & wxALIGN_RIGHT) != 0) { + x = r.x + r.width - size.x - 2; + y = r.y + r.height / 2 - size.y / 2; + } + else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) { + x = r.x + r.width / 2 - size.x / 2; + y = r.y + r.height / 2 - size.y / 2; + } + else // wxALIGN_LEFT + { + x = r.x + 2; #ifdef __WXMSW__ - x += 2; + x += 2; #endif //__WXMSW__ - y = r.y + r.height/2 - size.y/2; - } + y = r.y + r.height / 2 - size.y / 2; + } - GetControl()->Move(x, y); + GetControl()->Move(x, y); } void wxSheetCellBoolEditorRefData::Show(bool show, const wxSheetCellAttr &attr) { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - GetControl()->Show(show); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + GetControl()->Show(show); - if ( show ) - { - wxColour colBg = attr.Ok() ? attr.GetBackgroundColour() : *wxLIGHT_GREY; - GetCheckBox()->SetBackgroundColour(colBg); - } + if (show) { + wxColour colBg = attr.Ok() ? attr.GetBackgroundColour() : *wxLIGHT_GREY; + GetCheckBox()->SetBackgroundColour(colBg); + } } -void wxSheetCellBoolEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) +void wxSheetCellBoolEditorRefData::BeginEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - if (sheet->GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL)) - m_startValue = sheet->GetTable()->GetValueAsBool(coords); - else - { - wxString cellval( sheet->GetTable()->GetValue(coords) ); - m_startValue = !( !cellval || (cellval == wxT("0")) ); - } - GetCheckBox()->SetValue(m_startValue); - GetCheckBox()->SetFocus(); + if (sheet->GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL)) { + m_startValue = sheet->GetTable()->GetValueAsBool(coords); + } + else { + wxString cellval(sheet->GetTable()->GetValue(coords)); + m_startValue = !(!cellval || (cellval == wxT("0"))); + } + GetCheckBox()->SetValue(m_startValue); + GetCheckBox()->SetFocus(); } -bool wxSheetCellBoolEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) +bool wxSheetCellBoolEditorRefData::EndEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); + wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); - bool value = GetCheckBox()->GetValue(); - bool changed = ( value != m_startValue ); + bool value = GetCheckBox()->GetValue(); + bool changed = (value != m_startValue); - if ( changed ) - { - if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) - return false; + if (changed) { + if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) { + return false; + } - if (sheet->GetTable() && sheet->GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL)) - sheet->GetTable()->SetValueAsBool(coords, value); - else - sheet->SetCellValue(coords, value ? _T("1") : wxEmptyString); + if (sheet->GetTable() && sheet->GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL)) { + sheet->GetTable()->SetValueAsBool(coords, value); + } + else { + sheet->SetCellValue(coords, value ? _T("1") : wxEmptyString); } + } - return changed; + return changed; } void wxSheetCellBoolEditorRefData::ResetValue() { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - GetCheckBox()->SetValue(m_startValue); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + GetCheckBox()->SetValue(m_startValue); } void wxSheetCellBoolEditorRefData::StartingClick() { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - GetCheckBox()->SetValue(!GetCheckBox()->GetValue()); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + GetCheckBox()->SetValue(!GetCheckBox()->GetValue()); } -bool wxSheetCellBoolEditorRefData::IsAcceptedKey(wxKeyEvent& event) +bool wxSheetCellBoolEditorRefData::IsAcceptedKey(wxKeyEvent &event) { - if ( wxSheetCellEditorRefData::IsAcceptedKey(event) ) - { - int keycode = event.GetKeyCode(); - switch ( keycode ) - { - case WXK_MULTIPLY: - case WXK_NUMPAD_MULTIPLY: - case WXK_ADD: - case WXK_NUMPAD_ADD: - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - case WXK_SPACE: - case '+': - case '-': - return true; - } + if (wxSheetCellEditorRefData::IsAcceptedKey(event)) { + int keycode = event.GetKeyCode(); + switch (keycode) { + case WXK_MULTIPLY: + case WXK_NUMPAD_MULTIPLY: + case WXK_ADD: + case WXK_NUMPAD_ADD: + case WXK_SUBTRACT: + case WXK_NUMPAD_SUBTRACT: + case WXK_SPACE: + case '+': + case '-': + return true; } + } - return false; + return false; } // return the value as "1" for true and the empty string for false wxString wxSheetCellBoolEditorRefData::GetValue() const { - wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); - bool bSet = GetCheckBox()->GetValue(); - return bSet ? _T("1") : wxEmptyString; + wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); + bool bSet = GetCheckBox()->GetValue(); + return bSet ? _T("1") : wxEmptyString; } #endif // wxUSE_CHECKBOX @@ -1310,128 +1244,131 @@ wxString wxSheetCellBoolEditorRefData::GetValue() const // ---------------------------------------------------------------------------- #if wxUSE_COMBOBOX -wxSheetCellChoiceEditorRefData::wxSheetCellChoiceEditorRefData(const wxArrayString& choices, +wxSheetCellChoiceEditorRefData::wxSheetCellChoiceEditorRefData(const wxArrayString &choices, bool allowOthers) - : m_choices(choices), m_allowOthers(allowOthers) {} + : m_choices(choices), m_allowOthers(allowOthers) +{ +} wxSheetCellChoiceEditorRefData::wxSheetCellChoiceEditorRefData(size_t count, - const wxString choices[], - bool allowOthers) - : m_allowOthers(allowOthers) + const wxString choices[], + bool allowOthers) + : m_allowOthers(allowOthers) { - if ( count > 0 ) - { - m_choices.Alloc(count); - for ( size_t n = 0; n < count; n++ ) - m_choices.Add(choices[n]); + if (count > 0) { + m_choices.Alloc(count); + for (size_t n = 0; n < count; n++) { + m_choices.Add(choices[n]); } + } } -bool wxSheetCellChoiceEditorRefData::Copy(const wxSheetCellChoiceEditorRefData& other) +bool wxSheetCellChoiceEditorRefData::Copy(const wxSheetCellChoiceEditorRefData &other) { - m_choices = other.m_choices; - m_allowOthers = other.m_allowOthers; - return wxSheetCellEditorRefData::Copy(other); + m_choices = other.m_choices; + m_allowOthers = other.m_allowOthers; + return wxSheetCellEditorRefData::Copy(other); } -void wxSheetCellChoiceEditorRefData::CreateEditor(wxWindow* parent, - wxWindowID id, - wxEvtHandler* evtHandler, - wxSheet* sheet) +void wxSheetCellChoiceEditorRefData::CreateEditor(wxWindow *parent, wxWindowID id, + wxEvtHandler *evtHandler, wxSheet *sheet) { #if wxCHECK_VERSION(2, 5, 0) - SetControl( new wxComboBox(parent, id, wxEmptyString, - wxDefaultPosition, wxDefaultSize, - m_choices, - m_allowOthers ? 0 : wxCB_READONLY) ); + SetControl(new wxComboBox(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, m_choices, + m_allowOthers ? 0 : wxCB_READONLY)); #else - const size_t count = m_choices.GetCount(); - wxString *choices = new wxString[count]; - for ( size_t n = 0; n < count; n++ ) - choices[n] = m_choices[n]; + const size_t count = m_choices.GetCount(); + wxString *choices = new wxString[count]; + for (size_t n = 0; n < count; n++) { + choices[n] = m_choices[n]; + } - SetControl( new wxComboBox(parent, id, wxEmptyString, - wxDefaultPosition, wxDefaultSize, - count, choices, - m_allowOthers ? 0 : wxCB_READONLY) ); + SetControl(new wxComboBox(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, count, + choices, m_allowOthers ? 0 : wxCB_READONLY)); - delete []choices; + delete[] choices; #endif // wxCHECK_VERSION - wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); + wxSheetCellEditorRefData::CreateEditor(parent, id, evtHandler, sheet); } -void wxSheetCellChoiceEditorRefData::PaintBackground(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected) +void wxSheetCellChoiceEditorRefData::PaintBackground(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxRect &rect, + const wxSheetCoords &coords, bool isSelected) { - // as we fill the entire client area, don't do anything here to minimize - // flicker + // as we fill the entire client area, don't do anything here to minimize + // flicker - // TODO: It doesn't actually fill the client area since the height of a - // combo always defaults to the standard... Until someone has time to - // figure out the right rectangle to paint, just do it the normal way... - wxSheetCellEditorRefData::PaintBackground(sheet, attr, dc, rect, coords, isSelected); + // TODO: It doesn't actually fill the client area since the height of a + // combo always defaults to the standard... Until someone has time to + // figure out the right rectangle to paint, just do it the normal way... + wxSheetCellEditorRefData::PaintBackground(sheet, attr, dc, rect, coords, isSelected); } -void wxSheetCellChoiceEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) +void wxSheetCellChoiceEditorRefData::BeginEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - m_startValue = sheet->GetTable()->GetValue(coords); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + m_startValue = sheet->GetTable()->GetValue(coords); - if (m_allowOthers) - GetComboBox()->SetValue(m_startValue); - else - { - // find the right position, or default to the first if not found - int pos = GetComboBox()->FindString(m_startValue); - if (pos == -1) - pos = 0; - if (static_cast(GetComboBox()->GetCount()) > pos) - GetComboBox()->SetSelection(pos); + if (m_allowOthers) { + GetComboBox()->SetValue(m_startValue); + } + else { + // find the right position, or default to the first if not found + int pos = GetComboBox()->FindString(m_startValue); + if (pos == -1) { + pos = 0; + } + if (static_cast(GetComboBox()->GetCount()) > pos) { + GetComboBox()->SetSelection(pos); } - GetComboBox()->SetInsertionPointEnd(); - GetComboBox()->SetFocus(); + } + GetComboBox()->SetInsertionPointEnd(); + GetComboBox()->SetFocus(); } -bool wxSheetCellChoiceEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) +bool wxSheetCellChoiceEditorRefData::EndEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); - wxString value = GetComboBox()->GetValue(); - if (value == m_startValue) - return false; + wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); + wxString value = GetComboBox()->GetValue(); + if (value == m_startValue) { + return false; + } - if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) - return false; + if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) { + return false; + } - sheet->GetTable()->SetValue(coords, value); - return true; + sheet->GetTable()->SetValue(coords, value); + return true; } void wxSheetCellChoiceEditorRefData::ResetValue() { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); - GetComboBox()->SetValue(m_startValue); - GetComboBox()->SetInsertionPointEnd(); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEditor must be Created first!")); + GetComboBox()->SetValue(m_startValue); + GetComboBox()->SetInsertionPointEnd(); } -void wxSheetCellChoiceEditorRefData::SetParameters(const wxString& params) +void wxSheetCellChoiceEditorRefData::SetParameters(const wxString ¶ms) { - // what can we do? - if ( params.IsEmpty() ) - return; + // what can we do? + if (params.IsEmpty()) { + return; + } - m_choices.Empty(); + m_choices.Empty(); - wxStringTokenizer tk(params, _T(',')); - while ( tk.HasMoreTokens() ) - m_choices.Add(tk.GetNextToken()); + wxStringTokenizer tk(params, _T(',')); + while (tk.HasMoreTokens()) { + m_choices.Add(tk.GetNextToken()); + } } // return the value in the text control wxString wxSheetCellChoiceEditorRefData::GetValue() const { - wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); - return GetComboBox()->GetValue(); + wxCHECK_MSG(GetControl(), wxEmptyString, wxT("The wxSheetCellEditor must be Created first!")); + return GetComboBox()->GetValue(); } #endif // wxUSE_COMBOBOX @@ -1444,49 +1381,53 @@ wxString wxSheetCellChoiceEditorRefData::GetValue() const // data in cell is 0,1,2 ... n the cell could be displayed as // "John","Fred"..."Bob" in the combo choice box -wxSheetCellEnumEditorRefData::wxSheetCellEnumEditorRefData(const wxString& choices) - : wxSheetCellChoiceEditorRefData(), m_startint(-1) +wxSheetCellEnumEditorRefData::wxSheetCellEnumEditorRefData(const wxString &choices) + : wxSheetCellChoiceEditorRefData(), m_startint(-1) { - if (!choices.IsEmpty()) - SetParameters(choices); + if (!choices.IsEmpty()) { + SetParameters(choices); + } } -void wxSheetCellEnumEditorRefData::BeginEdit(const wxSheetCoords& coords, wxSheet* sheet) +void wxSheetCellEnumEditorRefData::BeginEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_RET(GetControl(), wxT("The wxSheetCellEnumEditor must be Created first!")); - wxSheetTable *table = sheet->GetTable(); + wxCHECK_RET(GetControl(), wxT("The wxSheetCellEnumEditor must be Created first!")); + wxSheetTable *table = sheet->GetTable(); - if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) - m_startint = table->GetValueAsLong(coords); - else - { - wxString startValue = sheet->GetCellValue(coords); - if (startValue.IsEmpty() || !startValue.ToLong(&m_startint)) - m_startint = -1; + if (table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER)) { + m_startint = table->GetValueAsLong(coords); + } + else { + wxString startValue = sheet->GetCellValue(coords); + if (startValue.IsEmpty() || !startValue.ToLong(&m_startint)) { + m_startint = -1; } + } - GetComboBox()->SetSelection(m_startint); - GetComboBox()->SetInsertionPointEnd(); - GetComboBox()->SetFocus(); + GetComboBox()->SetSelection(m_startint); + GetComboBox()->SetInsertionPointEnd(); + GetComboBox()->SetFocus(); } -bool wxSheetCellEnumEditorRefData::EndEdit(const wxSheetCoords& coords, wxSheet* sheet) +bool wxSheetCellEnumEditorRefData::EndEdit(const wxSheetCoords &coords, wxSheet *sheet) { - wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); - int pos = GetComboBox()->GetSelection(); - bool changed = (pos != m_startint); - if (changed) - { - if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) - return false; + wxCHECK_MSG(GetControl(), false, wxT("The wxSheetCellEditor must be Created first!")); + int pos = GetComboBox()->GetSelection(); + bool changed = (pos != m_startint); + if (changed) { + if (sheet->SendEvent(wxEVT_SHEET_CELL_VALUE_CHANGING, coords) == wxSheet::EVT_VETOED) { + return false; + } - if (sheet->GetTable() && sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_NUMBER)) - sheet->GetTable()->SetValueAsLong(coords, pos); - else - sheet->SetCellValue(coords, wxString::Format(wxT("%i"),pos)); + if (sheet->GetTable() && sheet->GetTable()->CanSetValueAs(coords, wxSHEET_VALUE_NUMBER)) { + sheet->GetTable()->SetValueAsLong(coords, pos); + } + else { + sheet->SetCellValue(coords, wxString::Format(wxT("%i"), pos)); } + } - return changed; + return changed; } #endif // wxUSE_COMBOBOX diff --git a/src/labenski/src/sheetren.cpp b/src/labenski/src/sheetren.cpp index 22172749d..40e6b3503 100644 --- a/src/labenski/src/sheetren.cpp +++ b/src/labenski/src/sheetren.cpp @@ -12,19 +12,19 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/defs.h" - #include "wx/utils.h" - #include "wx/dc.h" - #include "wx/dcclient.h" - #include "wx/log.h" - #include "wx/valtext.h" - #include "wx/settings.h" - #include "wx/checkbox.h" - #include "wx/intl.h" +#include "wx/defs.h" +#include "wx/utils.h" +#include "wx/dc.h" +#include "wx/dcclient.h" +#include "wx/log.h" +#include "wx/valtext.h" +#include "wx/settings.h" +#include "wx/checkbox.h" +#include "wx/intl.h" #endif // WX_PRECOMP #include "wx/sheet/sheet.h" @@ -32,36 +32,30 @@ #include "wx/tokenzr.h" #include "wx/renderer.h" -#define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); - +#define PRINT_RECT(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); #if defined(__WXMOTIF__) - #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier) +#define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier) #else - #define WXUNUSED_MOTIF(identifier) identifier +#define WXUNUSED_MOTIF(identifier) identifier #endif // defined(__WXMOTIF__) #if defined(__WXGTK__) - #define WXUNUSED_GTK(identifier) WXUNUSED(identifier) +#define WXUNUSED_GTK(identifier) WXUNUSED(identifier) #else - #define WXUNUSED_GTK(identifier) identifier +#define WXUNUSED_GTK(identifier) identifier #endif // defined(__WXGTK__) const wxSheetCellRenderer wxNullSheetCellRenderer; /* XPM */ static const char *s_overflow_arrow_xpm_data[] = { -/* columns rows colors chars-per-pixel */ -"4 6 2 1", -" c None", -"a c Black", -/* pixels */ -"aa ", -"aaa ", -"aaaa", -"aaaa", -"aaa ", -"aa "}; + /* columns rows colors chars-per-pixel */ + "4 6 2 1", " c None", "a c Black", + /* pixels */ + "aa ", "aaa ", "aaaa", "aaaa", "aaa ", "aa "}; static wxBitmap s_overflowBitmap; // a bitmap to indicate cell overflows @@ -80,41 +74,40 @@ IMPLEMENT_DYNAMIC_CLASS(wxSheetCellRolColLabelRendererRefData, wxSheetCellString // ---------------------------------------------------------------------------- // wxSheetCellRenderer // ---------------------------------------------------------------------------- -#define M_CELLRENREFDATA ((wxSheetCellRendererRefData*)m_refData) +#define M_CELLRENREFDATA ((wxSheetCellRendererRefData *)m_refData) wxSheetCellRenderer::wxSheetCellRenderer(wxSheetCellRendererRefData *renderer) { - m_refData = renderer; + m_refData = renderer; } -void wxSheetCellRenderer::Draw(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, bool isSelected) +void wxSheetCellRenderer::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect, const wxSheetCoords &coords, bool isSelected) { - wxCHECK_RET(Ok(), wxT("wxSheetCellRenderer is not created")); - M_CELLRENREFDATA->Draw(sheet, attr, dc, rect, coords, isSelected); + wxCHECK_RET(Ok(), wxT("wxSheetCellRenderer is not created")); + M_CELLRENREFDATA->Draw(sheet, attr, dc, rect, coords, isSelected); } -wxSize wxSheetCellRenderer::GetBestSize(wxSheet& sheet, const wxSheetCellAttr& attr, - wxDC& dc, const wxSheetCoords& coords) +wxSize wxSheetCellRenderer::GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords) { - wxCHECK_MSG(Ok(), sheet.GetCellSize(coords), wxT("wxSheetCellRenderer is not created")); - return M_CELLRENREFDATA->GetBestSize(sheet, attr, dc, coords); + wxCHECK_MSG(Ok(), sheet.GetCellSize(coords), wxT("wxSheetCellRenderer is not created")); + return M_CELLRENREFDATA->GetBestSize(sheet, attr, dc, coords); } -void wxSheetCellRenderer::SetParameters(const wxString& params) +void wxSheetCellRenderer::SetParameters(const wxString ¶ms) { - wxCHECK_RET(Ok(), wxT("wxSheetCellRenderer is not created")); - M_CELLRENREFDATA->SetParameters(params); + wxCHECK_RET(Ok(), wxT("wxSheetCellRenderer is not created")); + M_CELLRENREFDATA->SetParameters(params); } -bool wxSheetCellRenderer::Copy(const wxSheetCellRenderer& other) +bool wxSheetCellRenderer::Copy(const wxSheetCellRenderer &other) { - wxCHECK_MSG(other.Ok(), false, wxT("wxSheetCellRenderer is not created")); + wxCHECK_MSG(other.Ok(), false, wxT("wxSheetCellRenderer is not created")); - UnRef(); - m_refData = ((wxSheetCellRendererRefData*)other.m_refData)->Clone(); - return true; + UnRef(); + m_refData = ((wxSheetCellRendererRefData *)other.m_refData)->Clone(); + return true; } // ---------------------------------------------------------------------------- @@ -122,81 +115,82 @@ bool wxSheetCellRenderer::Copy(const wxSheetCellRenderer& other) // ---------------------------------------------------------------------------- // This is testing code to show the different selection blocks with different colours -//#define TEST_SELECTION_BLOCKS +// #define TEST_SELECTION_BLOCKS #ifdef TEST_SELECTION_BLOCKS - #include "wx/sheet/sheetsel.h" - #include "math.h" - #define UNUSE(a) a - wxColour GetRainbow(double v) - { - double vmin = 0, vmax = 255, dv = vmax - vmin; - if (v < (vmin + 0.25 * dv)) - return wxColour(0, int(255.0*(4.0 * (v - vmin) / dv) + 0.5), 255); - else if (v < (vmin + 0.5 * dv)) - return wxColour(0, 255, int(255.0*(1.0 + 4.0 * (vmin + 0.25 * dv - v) / dv) + 0.5)); - else if (v < (vmin + 0.75 * dv)) - return wxColour(int(255.0*(4.0 * (v - vmin - 0.5 * dv) / dv) + 0.5), 255, 0); - else - return wxColour(255, int(255.0*(1.0 + 4.0 * (vmin + 0.75 * dv - v) / dv) + 0.5), 0); - } +#include "wx/sheet/sheetsel.h" +#include "math.h" +#define UNUSE(a) a +wxColour GetRainbow(double v) +{ + double vmin = 0, vmax = 255, dv = vmax - vmin; + if (v < (vmin + 0.25 * dv)) { + return wxColour(0, int(255.0 * (4.0 * (v - vmin) / dv) + 0.5), 255); + } + else if (v < (vmin + 0.5 * dv)) { + return wxColour(0, 255, int(255.0 * (1.0 + 4.0 * (vmin + 0.25 * dv - v) / dv) + 0.5)); + } + else if (v < (vmin + 0.75 * dv)) { + return wxColour(int(255.0 * (4.0 * (v - vmin - 0.5 * dv) / dv) + 0.5), 255, 0); + } + else { + return wxColour(255, int(255.0 * (1.0 + 4.0 * (vmin + 0.75 * dv - v) / dv) + 0.5), 0); + } +} #else - #define UNUSE(a) +#define UNUSE(a) #endif -void wxSheetCellRendererRefData::Draw( wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rect, - const wxSheetCoords& UNUSE(coords), - bool isSelected ) +void wxSheetCellRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect, const wxSheetCoords &UNUSE(coords), + bool isSelected) { - dc.SetBackgroundMode( wxSOLID ); + dc.SetBackgroundMode(wxSOLID); - // grey out fields if the sheet is disabled - if ( sheet.IsEnabled() ) - { - if ( isSelected ) - dc.SetBrush( wxBrush(sheet.GetSelectionBackground(), wxBRUSHSTYLE_SOLID) ); - else - dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxBRUSHSTYLE_SOLID) ); + // grey out fields if the sheet is disabled + if (sheet.IsEnabled()) { + if (isSelected) { + dc.SetBrush(wxBrush(sheet.GetSelectionBackground(), wxBRUSHSTYLE_SOLID)); + } + else { + dc.SetBrush(wxBrush(attr.GetBackgroundColour(), wxBRUSHSTYLE_SOLID)); } - else - dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxBRUSHSTYLE_SOLID)); + } + else { + dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxBRUSHSTYLE_SOLID)); + } - dc.SetPen( *wxTRANSPARENT_PEN ); - dc.DrawRectangle(rect); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(rect); #ifdef TEST_SELECTION_BLOCKS // colouring for identifying different blocks - if (isSelected) - { - int i = sheet.GetSelection()->Index(coords); - wxColour c(GetRainbow(i*10)); - dc.SetBrush( wxBrush(c, wxSOLID) ); - dc.DrawRectangle(rect); - - wxFont font = dc.GetFont(); - dc.SetFont(*wxSMALL_FONT); - dc.DrawText(wxString::Format(wxT("%d"), i), rect.x, rect.y); - } + if (isSelected) { + int i = sheet.GetSelection()->Index(coords); + wxColour c(GetRainbow(i * 10)); + dc.SetBrush(wxBrush(c, wxSOLID)); + dc.DrawRectangle(rect); + + wxFont font = dc.GetFont(); + dc.SetFont(*wxSMALL_FONT); + dc.DrawText(wxString::Format(wxT("%d"), i), rect.x, rect.y); + } #endif // TEST_SELECTION_BLOCKS - //FIXME - border drawing code, maybe it goes here? - //dc.SetPen( wxPen(sheet.GetGridLineColour(), 1, wxSOLID) ); - //dc.DrawRectangle(rect.x-1, rect.y-1, rect.width+2, rect.height+2); + // FIXME - border drawing code, maybe it goes here? + // dc.SetPen( wxPen(sheet.GetGridLineColour(), 1, wxSOLID) ); + // dc.DrawRectangle(rect.x-1, rect.y-1, rect.width+2, rect.height+2); } -wxSize wxSheetCellRendererRefData::GetBestSize(wxSheet& sheet, - const wxSheetCellAttr& WXUNUSED(attr), - wxDC& WXUNUSED(dc), - const wxSheetCoords& coords) +wxSize wxSheetCellRendererRefData::GetBestSize(wxSheet &sheet, + const wxSheetCellAttr &WXUNUSED(attr), + wxDC &WXUNUSED(dc), const wxSheetCoords &coords) { - return sheet.GetCellSize(coords); // return current size + return sheet.GetCellSize(coords); // return current size } -wxString wxSheetCellRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) +wxString wxSheetCellRendererRefData::GetString(wxSheet &sheet, const wxSheetCoords &coords) { - return sheet.GetCellValue(coords); + return sheet.GetCellValue(coords); } // ---------------------------------------------------------------------------- @@ -204,346 +198,308 @@ wxString wxSheetCellRendererRefData::GetString(wxSheet& sheet, const wxSheetCoor // ---------------------------------------------------------------------------- wxSheetCellStringRendererRefData::wxSheetCellStringRendererRefData() { - if (!s_overflowBitmap.Ok()) - s_overflowBitmap = wxBitmap(s_overflow_arrow_xpm_data); + if (!s_overflowBitmap.Ok()) { + s_overflowBitmap = wxBitmap(s_overflow_arrow_xpm_data); + } } -void wxSheetCellStringRendererRefData::SetTextColoursAndFont(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - bool isSelected) +void wxSheetCellStringRendererRefData::SetTextColoursAndFont(wxSheet &sheet, + const wxSheetCellAttr &attr, wxDC &dc, + bool isSelected) { - dc.SetBackgroundMode( wxTRANSPARENT ); + dc.SetBackgroundMode(wxTRANSPARENT); - // TODO some special colours for attr.IsReadOnly() case? + // TODO some special colours for attr.IsReadOnly() case? - // different coloured text when the sheet is disabled - if ( sheet.IsEnabled() ) - { - if ( isSelected ) - { - dc.SetTextBackground( sheet.GetSelectionBackground() ); - dc.SetTextForeground( sheet.GetSelectionForeground() ); - } - else - { - dc.SetTextBackground( attr.GetBackgroundColour() ); - dc.SetTextForeground( attr.GetForegroundColour() ); - } + // different coloured text when the sheet is disabled + if (sheet.IsEnabled()) { + if (isSelected) { + dc.SetTextBackground(sheet.GetSelectionBackground()); + dc.SetTextForeground(sheet.GetSelectionForeground()); } - else - { - dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); - dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); + else { + dc.SetTextBackground(attr.GetBackgroundColour()); + dc.SetTextForeground(attr.GetForegroundColour()); } + } + else { + dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT)); + } - dc.SetFont( attr.GetFont() ); + dc.SetFont(attr.GetFont()); } -wxSize wxSheetCellStringRendererRefData::DoGetBestSize(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxString& text) +wxSize wxSheetCellStringRendererRefData::DoGetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxString &text) { - wxArrayString lines; - long w=0, h=0; - if (sheet.StringToLines(text, lines) > 0) - { - dc.SetFont(attr.GetFont()); - sheet.GetTextBoxSize(dc, lines, &w, &h); - } + wxArrayString lines; + long w = 0, h = 0; + if (sheet.StringToLines(text, lines) > 0) { + dc.SetFont(attr.GetFont()); + sheet.GetTextBoxSize(dc, lines, &w, &h); + } - return (attr.GetOrientation() == wxHORIZONTAL) ? wxSize(w, h) : wxSize(h, w); + return (attr.GetOrientation() == wxHORIZONTAL) ? wxSize(w, h) : wxSize(h, w); } -wxSize wxSheetCellStringRendererRefData::GetBestSize(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxSheetCoords& coords) +wxSize wxSheetCellStringRendererRefData::GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxSheetCoords &coords) { - return DoGetBestSize(sheet, attr, dc, GetString(sheet, coords)); + return DoGetBestSize(sheet, attr, dc, GetString(sheet, coords)); } -void wxSheetCellStringRendererRefData::Draw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, +void wxSheetCellStringRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rectCell, const wxSheetCoords &coords, bool isSelected) { - wxRect rect = rectCell; - rect.Inflate(-1); - - // erase only this cells background, overflow cells should have been erased - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); - DoDraw(sheet, attr, dc, rectCell, coords, isSelected); - - //wxRendererNative &ren = wxRendererNative::Get(); - //ren.DrawComboBoxDropButton(&sheet, dc, rectCell); -} - -void wxSheetCellStringRendererRefData::DoDraw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, - bool isSelected) -{ - wxRect rect = rectCell; - rect.Inflate(-1); - - int align = attr.GetAlignment(); + wxRect rect = rectCell; + rect.Inflate(-1); + + // erase only this cells background, overflow cells should have been erased + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); + DoDraw(sheet, attr, dc, rectCell, coords, isSelected); + + // wxRendererNative &ren = wxRendererNative::Get(); + // ren.DrawComboBoxDropButton(&sheet, dc, rectCell); +} + +void wxSheetCellStringRendererRefData::DoDraw(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxRect &rectCell, + const wxSheetCoords &coords, bool isSelected) +{ + wxRect rect = rectCell; + rect.Inflate(-1); + + int align = attr.GetAlignment(); + + wxString value = sheet.GetCellValue(coords); + int best_width = DoGetBestSize(sheet, attr, dc, value).GetWidth(); + wxSheetCoords cellSpan(sheet.GetCellSpan(coords)); // shouldn't get here if <=0 + int cell_rows = cellSpan.m_row; + int cell_cols = cellSpan.m_col; + + bool is_grid_cell = wxSheet::IsGridCell(coords); + // no overflow for row/col/corner labels + bool overflow = is_grid_cell ? attr.GetOverflow() : false; + int overflowCols = 0; + int num_cols = sheet.GetNumberCols(); + // this is the right col which includes overflow + int rightCol = coords.m_col + cell_cols - 1; + + // Check if this cell should overflow to right and for how many cells + if (overflow) { + bool is_editing = sheet.IsCellEditControlShown(); + wxSheetCoords editorCell = is_editing ? sheet.GetEditControlCoords() : wxNullSheetCoords; + int row = coords.GetRow(), col = coords.GetCol(); + wxSheetCoords ownerCell; + if ((best_width > rectCell.width) && (col < num_cols - 1) && sheet.GetTable()) { + wxSheetCoords cell; + for (cell.m_col = col + cell_cols; cell.m_col < num_cols; cell.m_col++) { + bool is_empty = true; + for (cell.m_row = row; cell.m_row < row + cell_rows; cell.m_row++) { + // check w/ anchor cell for spanned cell block + ownerCell = sheet.GetCellOwner(cell); + if (sheet.GetTable()->HasValue(ownerCell) || (ownerCell == editorCell)) { + is_empty = false; + break; + } + } - wxString value = sheet.GetCellValue(coords); - int best_width = DoGetBestSize(sheet, attr, dc, value).GetWidth(); - wxSheetCoords cellSpan(sheet.GetCellSpan(coords)); // shouldn't get here if <=0 - int cell_rows = cellSpan.m_row; - int cell_cols = cellSpan.m_col; - - bool is_grid_cell = wxSheet::IsGridCell(coords); - // no overflow for row/col/corner labels - bool overflow = is_grid_cell ? attr.GetOverflow() : false; - int overflowCols = 0; - int num_cols = sheet.GetNumberCols(); - // this is the right col which includes overflow - int rightCol = coords.m_col + cell_cols - 1; - - // Check if this cell should overflow to right and for how many cells - if (overflow) - { - bool is_editing = sheet.IsCellEditControlShown(); - wxSheetCoords editorCell = is_editing ? sheet.GetEditControlCoords() : wxNullSheetCoords; - int row = coords.GetRow(), col = coords.GetCol(); - wxSheetCoords ownerCell; - if ((best_width > rectCell.width) && (col < num_cols-1) && sheet.GetTable()) - { - wxSheetCoords cell; - for (cell.m_col = col+cell_cols; cell.m_col < num_cols; cell.m_col++) - { - bool is_empty = true; - for (cell.m_row = row; cell.m_row < row+cell_rows; cell.m_row++) - { - // check w/ anchor cell for spanned cell block - ownerCell = sheet.GetCellOwner(cell); - if ( sheet.GetTable()->HasValue(ownerCell) || - (ownerCell == editorCell) ) - { - is_empty = false; - break; - } - } - - if (is_empty) - rect.width += sheet.GetColWidth(cell.m_col); - else - { - cell.m_col--; - break; - } - - if (rect.width >= best_width) - break; - } - // this may extend out of sheet - overflowCols = cell.m_col - col - cell_cols + 1; - rightCol = wxMin(coords.m_col+cell_cols-1+overflowCols, num_cols - 1); + if (is_empty) { + rect.width += sheet.GetColWidth(cell.m_col); + } + else { + cell.m_col--; + break; } - // redraw overflow cells individually for proper selection hilight - if (overflowCols > 0) - { - // if overflowed then it's left aligned (yes I know ALIGN_LEFT=0) - align &= ~wxSHEET_AttrAlignHoriz_Mask; - align |= wxSHEET_AttrAlignLeft; - - wxRect clip(rect); - clip.x += rectCell.width; - - int col_width; - wxSheetCoords cell(coords); - // draw each cell individually since it may be selected or not - for (cell.m_col = col+cell_cols; cell.m_col <= rightCol; cell.m_col++) - { - col_width = sheet.GetColWidth(cell.m_col); - clip.width = col_width - 1; - dc.DestroyClippingRegion(); - dc.SetClippingRegion(clip); - SetTextColoursAndFont(sheet, attr, dc, sheet.IsCellSelected(cell)); - sheet.DrawTextRectangle(dc, value, rect, align); - clip.x += col_width - 1; - } - - rect = rectCell; - rect.Inflate(-1); - rect.width++; - dc.DestroyClippingRegion(); + if (rect.width >= best_width) { + break; } + } + // this may extend out of sheet + overflowCols = cell.m_col - col - cell_cols + 1; + rightCol = wxMin(coords.m_col + cell_cols - 1 + overflowCols, num_cols - 1); } - // Draw the text - SetTextColoursAndFont(sheet, attr, dc, isSelected); - sheet.DrawTextRectangle(dc, value, rect, align); - - if (attr.GetOverflowMarker()) - { - // Draw a marker to show that the contents has been clipped off - int cellRight = sheet.GetColRight(rightCol); - if (cellRight - rect.x < best_width) - { - int bmpWidth = s_overflowBitmap.GetWidth(); - int bmpHeight = s_overflowBitmap.GetHeight(); - int cellWidth = sheet.GetColWidth(rightCol); - int cellHeight = sheet.GetRowHeight(coords.m_row); - - if ((bmpWidth < cellWidth-3) && (bmpHeight < cellHeight-3)) - { - int cellTop = sheet.GetRowTop(coords.m_row); - - int x = cellRight - bmpWidth - 2; - int y = cellTop + (cellHeight - bmpHeight)/2; - wxRect r(x-2, cellTop, bmpWidth+4-1, cellHeight-1); - wxSheetCellAttr rightAttr(attr); - if (overflowCols > 0) - { - wxSheetCoords clipCell(coords.m_row, rightCol); - isSelected = sheet.IsCellSelected(clipCell); - rightAttr = sheet.GetAttr(clipCell); - } - - // clear background for bitmap - wxSheetCellRendererRefData::Draw(sheet, rightAttr, dc, r, coords, isSelected); - dc.DrawBitmap( s_overflowBitmap, x, y, true ); - } + // redraw overflow cells individually for proper selection hilight + if (overflowCols > 0) { + // if overflowed then it's left aligned (yes I know ALIGN_LEFT=0) + align &= ~wxSHEET_AttrAlignHoriz_Mask; + align |= wxSHEET_AttrAlignLeft; + + wxRect clip(rect); + clip.x += rectCell.width; + + int col_width; + wxSheetCoords cell(coords); + // draw each cell individually since it may be selected or not + for (cell.m_col = col + cell_cols; cell.m_col <= rightCol; cell.m_col++) { + col_width = sheet.GetColWidth(cell.m_col); + clip.width = col_width - 1; + dc.DestroyClippingRegion(); + dc.SetClippingRegion(clip); + SetTextColoursAndFont(sheet, attr, dc, sheet.IsCellSelected(cell)); + sheet.DrawTextRectangle(dc, value, rect, align); + clip.x += col_width - 1; + } + + rect = rectCell; + rect.Inflate(-1); + rect.width++; + dc.DestroyClippingRegion(); + } + } + + // Draw the text + SetTextColoursAndFont(sheet, attr, dc, isSelected); + sheet.DrawTextRectangle(dc, value, rect, align); + + if (attr.GetOverflowMarker()) { + // Draw a marker to show that the contents has been clipped off + int cellRight = sheet.GetColRight(rightCol); + if (cellRight - rect.x < best_width) { + int bmpWidth = s_overflowBitmap.GetWidth(); + int bmpHeight = s_overflowBitmap.GetHeight(); + int cellWidth = sheet.GetColWidth(rightCol); + int cellHeight = sheet.GetRowHeight(coords.m_row); + + if ((bmpWidth < cellWidth - 3) && (bmpHeight < cellHeight - 3)) { + int cellTop = sheet.GetRowTop(coords.m_row); + + int x = cellRight - bmpWidth - 2; + int y = cellTop + (cellHeight - bmpHeight) / 2; + wxRect r(x - 2, cellTop, bmpWidth + 4 - 1, cellHeight - 1); + wxSheetCellAttr rightAttr(attr); + if (overflowCols > 0) { + wxSheetCoords clipCell(coords.m_row, rightCol); + isSelected = sheet.IsCellSelected(clipCell); + rightAttr = sheet.GetAttr(clipCell); } + + // clear background for bitmap + wxSheetCellRendererRefData::Draw(sheet, rightAttr, dc, r, coords, isSelected); + dc.DrawBitmap(s_overflowBitmap, x, y, true); + } } + } } // ---------------------------------------------------------------------------- // wxSheetCellAutoWrapStringRendererRefData // ---------------------------------------------------------------------------- -void wxSheetCellAutoWrapStringRendererRefData::Draw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, - bool isSelected) +void wxSheetCellAutoWrapStringRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxRect &rectCell, + const wxSheetCoords &coords, bool isSelected) { - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); - SetTextColoursAndFont(sheet, attr, dc, isSelected); + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); + SetTextColoursAndFont(sheet, attr, dc, isSelected); - int align = attr.GetAlignment(); + int align = attr.GetAlignment(); - wxRect rect = rectCell; - rect.Inflate(-1); + wxRect rect = rectCell; + rect.Inflate(-1); - sheet.DrawTextRectangle(dc, GetTextLines(sheet, dc, attr, rect, coords), - rect, align); + sheet.DrawTextRectangle(dc, GetTextLines(sheet, dc, attr, rect, coords), rect, align); } -wxArrayString -wxSheetCellAutoWrapStringRendererRefData::GetTextLines(wxSheet& sheet, - wxDC& dc, - const wxSheetCellAttr& attr, - const wxRect& rect, - const wxSheetCoords& coords) +wxArrayString wxSheetCellAutoWrapStringRendererRefData::GetTextLines(wxSheet &sheet, wxDC &dc, + const wxSheetCellAttr &attr, + const wxRect &rect, + const wxSheetCoords &coords) { - wxString data = sheet.GetCellValue(coords); + wxString data = sheet.GetCellValue(coords); - wxArrayString lines; - dc.SetFont(attr.GetFont()); + wxArrayString lines; + dc.SetFont(attr.GetFont()); - //Taken from wxSheet again! - wxCoord x = 0, y = 0, curr_x = 0; - wxCoord max_x = rect.GetWidth(); + // Taken from wxSheet again! + wxCoord x = 0, y = 0, curr_x = 0; + wxCoord max_x = rect.GetWidth(); - wxStringTokenizer tk(data, _T(" \n\t\r")); - wxString thisline; + wxStringTokenizer tk(data, _T(" \n\t\r")); + wxString thisline; - while ( tk.HasMoreTokens() ) - { - wxString tok = tk.GetNextToken(); - //FIXME: this causes us to print an extra unnecesary - // space at the end of the line. But it - // is invisible , simplifies the size calculation - // and ensures tokens are separated in the display - tok += _T(" "); - - dc.GetTextExtent(tok, &x, &y); - if ( curr_x + x > max_x) - { - lines.Add( thisline ); - thisline = tok; - curr_x = x; - } - else - { - thisline += tok; - curr_x += x; - } + while (tk.HasMoreTokens()) { + wxString tok = tk.GetNextToken(); + // FIXME: this causes us to print an extra unnecesary + // space at the end of the line. But it + // is invisible , simplifies the size calculation + // and ensures tokens are separated in the display + tok += _T(" "); + + dc.GetTextExtent(tok, &x, &y); + if (curr_x + x > max_x) { + lines.Add(thisline); + thisline = tok; + curr_x = x; } + else { + thisline += tok; + curr_x += x; + } + } - lines.Add( thisline ); //Add last line + lines.Add(thisline); // Add last line - return lines; + return lines; } -wxSize wxSheetCellAutoWrapStringRendererRefData::GetBestSize(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxSheetCoords& coords) +wxSize wxSheetCellAutoWrapStringRendererRefData::GetBestSize(wxSheet &sheet, + const wxSheetCellAttr &attr, wxDC &dc, + const wxSheetCoords &coords) { - wxCoord x, y, height, width = sheet.GetColWidth(coords.GetCol()) -10; - int count = 250; //Limit iterations.. + wxCoord x, y, height, width = sheet.GetColWidth(coords.GetCol()) - 10; + int count = 250; // Limit iterations.. - wxRect rect(0, 0, width, 10); + wxRect rect(0, 0, width, 10); - // M is a nice large character 'y' gives descender!. - dc.SetFont(attr.GetFont()); - dc.GetTextExtent(wxT("My"), &x, &y); + // M is a nice large character 'y' gives descender!. + dc.SetFont(attr.GetFont()); + dc.GetTextExtent(wxT("My"), &x, &y); - do // Search for a shape no taller than the golden ratio. - { - width += 10; - rect.SetWidth(width); - height = y * GetTextLines(sheet,dc,attr,rect,coords).GetCount(); - count--; - } while (count && (width < (height*1.68)) ); + do // Search for a shape no taller than the golden ratio. + { + width += 10; + rect.SetWidth(width); + height = y * GetTextLines(sheet, dc, attr, rect, coords).GetCount(); + count--; + } while (count && (width < (height * 1.68))); - return wxSize(width, height); + return wxSize(width, height); } // ---------------------------------------------------------------------------- // wxSheetCellNumberRendererRefData // ---------------------------------------------------------------------------- -wxString wxSheetCellNumberRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) +wxString wxSheetCellNumberRendererRefData::GetString(wxSheet &sheet, const wxSheetCoords &coords) { - wxSheetTable *table = sheet.GetTable(); - if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) - return wxString::Format(_T("%ld"), table->GetValueAsLong(coords)); + wxSheetTable *table = sheet.GetTable(); + if (table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER)) { + return wxString::Format(_T("%ld"), table->GetValueAsLong(coords)); + } - return sheet.GetCellValue(coords); + return sheet.GetCellValue(coords); } -void wxSheetCellNumberRendererRefData::Draw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, +void wxSheetCellNumberRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rectCell, const wxSheetCoords &coords, bool isSelected) { - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); - SetTextColoursAndFont(sheet, attr, dc, isSelected); + SetTextColoursAndFont(sheet, attr, dc, isSelected); - // draw the text right aligned by default - int align = attr.GetAlignment(); // | wxALIGN_RIGHT; //FIXME Why forced right? + // draw the text right aligned by default + int align = attr.GetAlignment(); // | wxALIGN_RIGHT; //FIXME Why forced right? - wxRect rect = rectCell; - rect.Inflate(-1); + wxRect rect = rectCell; + rect.Inflate(-1); - sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); + sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } // ---------------------------------------------------------------------------- @@ -551,211 +507,208 @@ void wxSheetCellNumberRendererRefData::Draw(wxSheet& sheet, // ---------------------------------------------------------------------------- bool wxSheetCellFloatRendererRefData::Copy(const wxSheetCellFloatRendererRefData &other) { - SetWidth(other.GetWidth()); - SetPrecision(other.GetPrecision()); - return wxSheetCellStringRendererRefData::Copy(other); + SetWidth(other.GetWidth()); + SetPrecision(other.GetPrecision()); + return wxSheetCellStringRendererRefData::Copy(other); } -wxString wxSheetCellFloatRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) +wxString wxSheetCellFloatRendererRefData::GetString(wxSheet &sheet, const wxSheetCoords &coords) { - wxSheetTable *table = sheet.GetTable(); + wxSheetTable *table = sheet.GetTable(); - bool hasDouble = false; - double val = 0; - wxString text; - if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_FLOAT) ) - { - val = table->GetValueAsDouble(coords); - hasDouble = true; - } - else - { - text = sheet.GetCellValue(coords); - hasDouble = text.ToDouble(&val); - } + bool hasDouble = false; + double val = 0; + wxString text; + if (table && table->CanGetValueAs(coords, wxSHEET_VALUE_FLOAT)) { + val = table->GetValueAsDouble(coords); + hasDouble = true; + } + else { + text = sheet.GetCellValue(coords); + hasDouble = text.ToDouble(&val); + } - if ( hasDouble ) - { - if ( !m_format ) - { - if ( m_width < 0 ) - { - if ( m_precision < 0 ) - m_format = _T("%f"); // default width/precision - else - m_format.Printf(_T("%%.%df"), m_precision); - } - else if ( m_precision < 0 ) - m_format.Printf(_T("%%%d.f"), m_width); // default precision - else - m_format.Printf(_T("%%%d.%df"), m_width, m_precision); + if (hasDouble) { + if (!m_format) { + if (m_width < 0) { + if (m_precision < 0) { + m_format = _T("%f"); // default width/precision } - - text.Printf(m_format, val); + else { + m_format.Printf(_T("%%.%df"), m_precision); + } + } + else if (m_precision < 0) { + m_format.Printf(_T("%%%d.f"), m_width); // default precision + } + else { + m_format.Printf(_T("%%%d.%df"), m_width, m_precision); + } } - return text; + text.Printf(m_format, val); + } + + return text; } -void wxSheetCellFloatRendererRefData::Draw( wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, - bool isSelected ) +void wxSheetCellFloatRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rectCell, const wxSheetCoords &coords, + bool isSelected) { - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); - SetTextColoursAndFont(sheet, attr, dc, isSelected); + SetTextColoursAndFont(sheet, attr, dc, isSelected); - // draw the text right aligned by default -- FIXME ? WHY - int align = attr.GetAlignment(); // | wxALIGN_RIGHT; + // draw the text right aligned by default -- FIXME ? WHY + int align = attr.GetAlignment(); // | wxALIGN_RIGHT; - wxRect rect(rectCell); - rect.Inflate(-1); + wxRect rect(rectCell); + rect.Inflate(-1); - sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); + sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } -void wxSheetCellFloatRendererRefData::SetParameters(const wxString& params) +void wxSheetCellFloatRendererRefData::SetParameters(const wxString ¶ms) { - if ( params.IsEmpty() ) - { - // reset to defaults - SetWidth(-1); - SetPrecision(-1); + if (params.IsEmpty()) { + // reset to defaults + SetWidth(-1); + SetPrecision(-1); + } + else { + wxString tmp = params.BeforeFirst(_T(',')); + if (!tmp.IsEmpty()) { + long width; + if (tmp.ToLong(&width)) { + SetWidth((int)width); + } + else { + wxLogDebug(_T("Invalid wxSheetCellFloatRenderer width parameter string '%s ignored"), + params.c_str()); + } } - else - { - wxString tmp = params.BeforeFirst(_T(',')); - if ( !tmp.IsEmpty() ) - { - long width; - if ( tmp.ToLong(&width) ) - SetWidth((int)width); - else - wxLogDebug(_T("Invalid wxSheetCellFloatRenderer width parameter string '%s ignored"), params.c_str()); - } - tmp = params.AfterFirst(_T(',')); - if ( !tmp.IsEmpty() ) - { - long precision; - if ( tmp.ToLong(&precision) ) - SetPrecision((int)precision); - else - wxLogDebug(_T("Invalid wxSheetCellFloatRenderer precision parameter string '%s ignored"), params.c_str()); - } + tmp = params.AfterFirst(_T(',')); + if (!tmp.IsEmpty()) { + long precision; + if (tmp.ToLong(&precision)) { + SetPrecision((int)precision); + } + else { + wxLogDebug(_T("Invalid wxSheetCellFloatRenderer precision parameter string '%s ignored"), + params.c_str()); + } } + } } // ---------------------------------------------------------------------------- // wxSheetCellBitmapRendererRefData // ---------------------------------------------------------------------------- -wxSize wxSheetCellBitmapRendererRefData::GetBestSize(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxSheetCoords& coords) +wxSize wxSheetCellBitmapRendererRefData::GetBestSize(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxSheetCoords &coords) { - wxSize bmpSize; - if (m_bitmap.Ok()) - bmpSize = wxSize( m_bitmap.GetWidth(), m_bitmap.GetHeight() ); + wxSize bmpSize; + if (m_bitmap.Ok()) { + bmpSize = wxSize(m_bitmap.GetWidth(), m_bitmap.GetHeight()); + } - wxSize strSize = wxSheetCellStringRendererRefData::GetBestSize(sheet, attr, dc, coords); + wxSize strSize = wxSheetCellStringRendererRefData::GetBestSize(sheet, attr, dc, coords); - return wxSize(bmpSize.x + strSize.x + 5, wxMax(bmpSize.y, strSize.y)); + return wxSize(bmpSize.x + strSize.x + 5, wxMax(bmpSize.y, strSize.y)); } #define MARGIN 2 -void wxSheetCellBitmapRendererRefData::Draw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect_, - const wxSheetCoords& coords, +void wxSheetCellBitmapRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect_, const wxSheetCoords &coords, bool isSelected) { - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect_, coords, isSelected); + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect_, coords, isSelected); - int text_align = attr.GetAlignment(); + int text_align = attr.GetAlignment(); - wxRect rect(rect_); + wxRect rect(rect_); - wxSize bmpSize; - if (m_bitmap.Ok()) - { - bmpSize.x = m_bitmap.GetWidth(); - bmpSize.y = m_bitmap.GetHeight(); - } + wxSize bmpSize; + if (m_bitmap.Ok()) { + bmpSize.x = m_bitmap.GetWidth(); + bmpSize.y = m_bitmap.GetHeight(); + } - wxSize txtSize(wxSheetCellStringRendererRefData::GetBestSize(sheet, attr, dc, coords)); + wxSize txtSize(wxSheetCellStringRendererRefData::GetBestSize(sheet, attr, dc, coords)); - wxRect bmpRect(rect); - wxRect txtRect(rect); + wxRect bmpRect(rect); + wxRect txtRect(rect); - if ((txtSize.x == 0) && (bmpSize.x == 0)) - return; + if ((txtSize.x == 0) && (bmpSize.x == 0)) { + return; + } - int margin = 2; + int margin = 2; - if ((txtSize.x == 0) || (bmpSize.x == 0)) - margin = 0; + if ((txtSize.x == 0) || (bmpSize.x == 0)) { + margin = 0; + } - if ((m_align & wxSHEET_BMPREN_BMPRIGHT) != 0) - { - //wxPrintf(wxT("1Printing row %d col %d \n"), coords.m_row, coords.m_col); - bmpRect.x += txtSize.x + margin; - bmpRect.width -= txtSize.x + margin; - if (txtSize.x < rect.width) - txtRect.width = txtSize.x; + if ((m_align & wxSHEET_BMPREN_BMPRIGHT) != 0) { + // wxPrintf(wxT("1Printing row %d col %d \n"), coords.m_row, coords.m_col); + bmpRect.x += txtSize.x + margin; + bmpRect.width -= txtSize.x + margin; + if (txtSize.x < rect.width) { + txtRect.width = txtSize.x; } - else if ((m_align & wxSHEET_BMPREN_BMPABOVE) != 0) - { - //wxPrintf(wxT("2Printing row %d col %d \n"), coords.m_row, coords.m_col); - txtRect.y += bmpSize.y + margin; - txtRect.height -= bmpSize.y + margin; - if (bmpSize.y < rect.height) - bmpRect.height = bmpSize.y; + } + else if ((m_align & wxSHEET_BMPREN_BMPABOVE) != 0) { + // wxPrintf(wxT("2Printing row %d col %d \n"), coords.m_row, coords.m_col); + txtRect.y += bmpSize.y + margin; + txtRect.height -= bmpSize.y + margin; + if (bmpSize.y < rect.height) { + bmpRect.height = bmpSize.y; } - else if ((m_align & wxSHEET_BMPREN_BMPBELOW) != 0) - { - //wxPrintf(wxT("3Printing row %d col %d \n"), coords.m_row, coords.m_col); - bmpRect.y += txtSize.y + margin; - bmpRect.height -= txtSize.y + margin; - if (txtSize.y < rect.height) - txtRect.height = txtSize.y; + } + else if ((m_align & wxSHEET_BMPREN_BMPBELOW) != 0) { + // wxPrintf(wxT("3Printing row %d col %d \n"), coords.m_row, coords.m_col); + bmpRect.y += txtSize.y + margin; + bmpRect.height -= txtSize.y + margin; + if (txtSize.y < rect.height) { + txtRect.height = txtSize.y; } - else //if ((m_align & wxSHEET_BMPREN_BMPLEFT) != 0) - { - //wxPrintf(wxT("4Printing row %d col %d \n"), coords.m_row, coords.m_col); - txtRect.x += bmpSize.x + margin; - txtRect.width -= bmpSize.x + margin; - if (bmpSize.x < rect.width) - bmpRect.width = bmpSize.x; + } + else // if ((m_align & wxSHEET_BMPREN_BMPLEFT) != 0) + { + // wxPrintf(wxT("4Printing row %d col %d \n"), coords.m_row, coords.m_col); + txtRect.x += bmpSize.x + margin; + txtRect.width -= bmpSize.x + margin; + if (bmpSize.x < rect.width) { + bmpRect.width = bmpSize.x; } + } - bmpRect.SetPosition(sheet.AlignInRect(m_align, bmpRect, bmpSize)); - txtRect.SetPosition(sheet.AlignInRect(text_align, txtRect, txtSize)); + bmpRect.SetPosition(sheet.AlignInRect(m_align, bmpRect, bmpSize)); + txtRect.SetPosition(sheet.AlignInRect(text_align, txtRect, txtSize)); - bmpRect.Intersect(rect); - txtRect.Intersect(rect); + bmpRect.Intersect(rect); + txtRect.Intersect(rect); - // text renderer will deflate it by 1 - txtRect.Inflate(1); + // text renderer will deflate it by 1 + txtRect.Inflate(1); - //wxPrintf(wxT("Printing row %d col %d \n"), coords.m_row, coords.m_col); - //PRINT_RECT("orig ", rect); - //PRINT_RECT("bmpRect", bmpRect); - //PRINT_RECT("txtRect", txtRect); + // wxPrintf(wxT("Printing row %d col %d \n"), coords.m_row, coords.m_col); + // PRINT_RECT("orig ", rect); + // PRINT_RECT("bmpRect", bmpRect); + // PRINT_RECT("txtRect", txtRect); - if ((txtRect.width > 0) && (txtRect.height > 0)) - wxSheetCellStringRendererRefData::DoDraw(sheet, attr, dc, txtRect, coords, isSelected); + if ((txtRect.width > 0) && (txtRect.height > 0)) { + wxSheetCellStringRendererRefData::DoDraw(sheet, attr, dc, txtRect, coords, isSelected); + } - if (m_bitmap.Ok() && (bmpRect.width > 0) && (bmpRect.height > 0)) - { - dc.SetClippingRegion(rect); - dc.DrawBitmap(m_bitmap, bmpRect.x, bmpRect.y, true); - dc.DestroyClippingRegion(); - } + if (m_bitmap.Ok() && (bmpRect.width > 0) && (bmpRect.height > 0)) { + dc.SetClippingRegion(rect); + dc.DrawBitmap(m_bitmap, bmpRect.x, bmpRect.y, true); + dc.DestroyClippingRegion(); + } } // ---------------------------------------------------------------------------- @@ -769,94 +722,96 @@ wxSize wxSheetCellBoolRendererRefData::ms_sizeCheckMark; // between checkmark and box #define wxSHEET_CHECKMARK_MARGIN 2 -wxSize wxSheetCellBoolRendererRefData::GetBestSize(wxSheet& sheet, - const wxSheetCellAttr& WXUNUSED(attr), - wxDC& WXUNUSED(dc), - const wxSheetCoords& ) +wxSize wxSheetCellBoolRendererRefData::GetBestSize(wxSheet &sheet, + const wxSheetCellAttr &WXUNUSED(attr), + wxDC &WXUNUSED(dc), const wxSheetCoords &) { - // compute it only once (no locks for MT safeness in GUI thread...) - if ( !ms_sizeCheckMark.x ) - { - // get checkbox size - wxCheckBox *checkbox = new wxCheckBox(&sheet, wxID_ANY, wxEmptyString); - wxSize size = checkbox->GetBestSize(); - wxCoord checkSize = size.y + 2*wxSHEET_CHECKMARK_MARGIN; + // compute it only once (no locks for MT safeness in GUI thread...) + if (!ms_sizeCheckMark.x) { + // get checkbox size + wxCheckBox *checkbox = new wxCheckBox(&sheet, wxID_ANY, wxEmptyString); + wxSize size = checkbox->GetBestSize(); + wxCoord checkSize = size.y + 2 * wxSHEET_CHECKMARK_MARGIN; - // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result + // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result #if defined(__WXGTK__) || defined(__WXMOTIF__) - checkSize -= size.y / 2; + checkSize -= size.y / 2; #endif // defined(__WXGTK__) || defined(__WXMOTIF__) - delete checkbox; - ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize; - } + delete checkbox; + ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize; + } - return ms_sizeCheckMark; + return ms_sizeCheckMark; } -void wxSheetCellBoolRendererRefData::Draw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, const wxRect& rect, - const wxSheetCoords& coords, +void wxSheetCellBoolRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rect, const wxSheetCoords &coords, bool isSelected) { - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect, coords, isSelected); - - // draw a check mark in the centre (ignoring alignment - TODO) - wxSize size = GetBestSize(sheet, attr, dc, coords); - - // don't draw outside the cell - wxCoord minSize = wxMin(rect.width, rect.height); - if ((size.x >= minSize) || (size.y >= minSize)) - size.x = size.y = minSize - 2; // leave (at least) 1 pixel margin - - // draw a border around checkmark - int align = attr.GetAlignment(); - - wxRect rectBorder(rect.GetPosition(), size); - - if ((align & wxALIGN_RIGHT) != 0) - rectBorder.x += rect.width - size.x - 2; - else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) - rectBorder.x += rect.width/2 - size.x/2; - else // wxALIGN_LEFT - rectBorder.x += 2; - - if ((align & wxALIGN_BOTTOM) != 0) - rectBorder.y += rect.height - size.y - 2; - else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) - rectBorder.y += rect.height/2 - size.y/2; - else // wxALIGN_TOP - rectBorder.y += 2; - - bool value; - if ( sheet.GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL) ) - value = sheet.GetTable()->GetValueAsBool(coords); - else - { - wxString strValue( sheet.GetTable()->GetValue(coords) ); - value = !( strValue.IsEmpty() || (strValue == wxT("0")) ); - } - - if ( value ) - { - wxRect rectMark = rectBorder; + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect, coords, isSelected); + + // draw a check mark in the centre (ignoring alignment - TODO) + wxSize size = GetBestSize(sheet, attr, dc, coords); + + // don't draw outside the cell + wxCoord minSize = wxMin(rect.width, rect.height); + if ((size.x >= minSize) || (size.y >= minSize)) { + size.x = size.y = minSize - 2; // leave (at least) 1 pixel margin + } + + // draw a border around checkmark + int align = attr.GetAlignment(); + + wxRect rectBorder(rect.GetPosition(), size); + + if ((align & wxALIGN_RIGHT) != 0) { + rectBorder.x += rect.width - size.x - 2; + } + else if ((align & wxALIGN_CENTRE_HORIZONTAL) != 0) { + rectBorder.x += rect.width / 2 - size.x / 2; + } + else { // wxALIGN_LEFT + rectBorder.x += 2; + } + + if ((align & wxALIGN_BOTTOM) != 0) { + rectBorder.y += rect.height - size.y - 2; + } + else if ((align & wxALIGN_CENTRE_VERTICAL) != 0) { + rectBorder.y += rect.height / 2 - size.y / 2; + } + else { // wxALIGN_TOP + rectBorder.y += 2; + } + + bool value; + if (sheet.GetTable()->CanGetValueAs(coords, wxSHEET_VALUE_BOOL)) { + value = sheet.GetTable()->GetValueAsBool(coords); + } + else { + wxString strValue(sheet.GetTable()->GetValue(coords)); + value = !(strValue.IsEmpty() || (strValue == wxT("0"))); + } + + if (value) { + wxRect rectMark = rectBorder; #ifdef __WXMSW__ - // MSW DrawCheckMark() is weird (and should probably be changed...) - rectMark.Inflate(-wxSHEET_CHECKMARK_MARGIN/2); - rectMark.x++; - rectMark.y++; -#else // !MSW - rectMark.Inflate(-wxSHEET_CHECKMARK_MARGIN); + // MSW DrawCheckMark() is weird (and should probably be changed...) + rectMark.Inflate(-wxSHEET_CHECKMARK_MARGIN / 2); + rectMark.x++; + rectMark.y++; +#else // !MSW + rectMark.Inflate(-wxSHEET_CHECKMARK_MARGIN); #endif // MSW/!MSW - dc.SetTextForeground(attr.GetForegroundColour()); - dc.DrawCheckMark(rectMark); - } + dc.SetTextForeground(attr.GetForegroundColour()); + dc.DrawCheckMark(rectMark); + } - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.SetPen(wxPen(attr.GetForegroundColour(), 1, wxPENSTYLE_SOLID)); - dc.DrawRectangle(rectBorder); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.SetPen(wxPen(attr.GetForegroundColour(), 1, wxPENSTYLE_SOLID)); + dc.DrawRectangle(rectBorder); } // ---------------------------------------------------------------------------- @@ -865,69 +820,65 @@ void wxSheetCellBoolRendererRefData::Draw(wxSheet& sheet, #if wxUSE_DATETIME // Enables a sheet cell to display a formated date and or time -bool wxSheetCellDateTimeRendererRefData::Copy(const wxSheetCellDateTimeRendererRefData& other) +bool wxSheetCellDateTimeRendererRefData::Copy(const wxSheetCellDateTimeRendererRefData &other) { - m_outFormat = other.m_outFormat; - m_inFormat = other.m_inFormat; - m_dateTime = other.m_dateTime; - m_tz = other.m_tz; - return wxSheetCellStringRendererRefData::Copy(other); + m_outFormat = other.m_outFormat; + m_inFormat = other.m_inFormat; + m_dateTime = other.m_dateTime; + m_tz = other.m_tz; + return wxSheetCellStringRendererRefData::Copy(other); } -wxString wxSheetCellDateTimeRendererRefData::GetString(wxSheet& sheet, const wxSheetCoords& coords) +wxString wxSheetCellDateTimeRendererRefData::GetString(wxSheet &sheet, const wxSheetCoords &coords) { - wxSheetTable *table = sheet.GetTable(); + wxSheetTable *table = sheet.GetTable(); - bool hasDatetime = false; - wxDateTime val; - wxString text; - if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_DATETIME) ) - { - void* tempval = table->GetValueAsCustom(coords, wxSHEET_VALUE_DATETIME); + bool hasDatetime = false; + wxDateTime val; + wxString text; + if (table && table->CanGetValueAs(coords, wxSHEET_VALUE_DATETIME)) { + void *tempval = table->GetValueAsCustom(coords, wxSHEET_VALUE_DATETIME); - if (tempval) - { - val = *((wxDateTime *)tempval); - hasDatetime = true; - delete (wxDateTime *)tempval; - } + if (tempval) { + val = *((wxDateTime *)tempval); + hasDatetime = true; + delete (wxDateTime *)tempval; } + } - if ( !hasDatetime ) - { - text = sheet.GetCellValue(coords); - hasDatetime = val.ParseFormat(text, m_inFormat, m_dateTime) != (wxChar *)NULL ; - } - else - text = val.Format( m_outFormat, m_tz ); + if (!hasDatetime) { + text = sheet.GetCellValue(coords); + hasDatetime = val.ParseFormat(text, m_inFormat, m_dateTime) != (wxChar *)NULL; + } + else { + text = val.Format(m_outFormat, m_tz); + } - return text; //If we faild to parse string just show what we where given? + return text; // If we faild to parse string just show what we where given? } -void wxSheetCellDateTimeRendererRefData::Draw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, - bool isSelected) +void wxSheetCellDateTimeRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxRect &rectCell, + const wxSheetCoords &coords, bool isSelected) { - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); - SetTextColoursAndFont(sheet, attr, dc, isSelected); + SetTextColoursAndFont(sheet, attr, dc, isSelected); - // draw the text right aligned by default FIXME why? - int align = attr.GetAlignment(); // | wxRIGHT; + // draw the text right aligned by default FIXME why? + int align = attr.GetAlignment(); // | wxRIGHT; - wxRect rect = rectCell; - rect.Inflate(-1); + wxRect rect = rectCell; + rect.Inflate(-1); - sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); + sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } -void wxSheetCellDateTimeRendererRefData::SetParameters(const wxString& params) +void wxSheetCellDateTimeRendererRefData::SetParameters(const wxString ¶ms) { - if (!params.IsEmpty()) - m_outFormat = params; + if (!params.IsEmpty()) { + m_outFormat = params; + } } #endif // wxUSE_DATETIME @@ -938,111 +889,105 @@ void wxSheetCellDateTimeRendererRefData::SetParameters(const wxString& params) // Renders a number as a textual equivalent. // eg data in cell is 0,1,2 ... n the cell could be rendered as "John","Fred"..."Bob" -wxSheetCellEnumRendererRefData::wxSheetCellEnumRendererRefData(const wxString& choices) +wxSheetCellEnumRendererRefData::wxSheetCellEnumRendererRefData(const wxString &choices) { - if (!choices.IsEmpty()) - SetParameters(choices); + if (!choices.IsEmpty()) { + SetParameters(choices); + } } -bool wxSheetCellEnumRendererRefData::Copy(const wxSheetCellEnumRendererRefData& other) +bool wxSheetCellEnumRendererRefData::Copy(const wxSheetCellEnumRendererRefData &other) { - m_choices = other.m_choices; - return wxSheetCellStringRendererRefData::Copy(other); + m_choices = other.m_choices; + return wxSheetCellStringRendererRefData::Copy(other); } -wxString wxSheetCellEnumRendererRefData::GetString( wxSheet& sheet, - const wxSheetCoords& coords ) +wxString wxSheetCellEnumRendererRefData::GetString(wxSheet &sheet, const wxSheetCoords &coords) { - wxSheetTable *table = sheet.GetTable(); - if ( table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER) ) - { - int choiceno = table->GetValueAsLong(coords); - return m_choices[choiceno]; - } + wxSheetTable *table = sheet.GetTable(); + if (table && table->CanGetValueAs(coords, wxSHEET_VALUE_NUMBER)) { + int choiceno = table->GetValueAsLong(coords); + return m_choices[choiceno]; + } - return sheet.GetCellValue(coords); + return sheet.GetCellValue(coords); } -void wxSheetCellEnumRendererRefData::Draw( wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, - bool isSelected ) +void wxSheetCellEnumRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, wxDC &dc, + const wxRect &rectCell, const wxSheetCoords &coords, + bool isSelected) { - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); - SetTextColoursAndFont(sheet, attr, dc, isSelected); + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rectCell, coords, isSelected); + SetTextColoursAndFont(sheet, attr, dc, isSelected); - // draw the text right aligned by default FIXME why? - int align = attr.GetAlignment(); // | wxRIGHT; + // draw the text right aligned by default FIXME why? + int align = attr.GetAlignment(); // | wxRIGHT; - wxRect rect = rectCell; - rect.Inflate(-1); + wxRect rect = rectCell; + rect.Inflate(-1); - sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); + sheet.DrawTextRectangle(dc, GetString(sheet, coords), rect, align); } -void wxSheetCellEnumRendererRefData::SetParameters(const wxString& params) +void wxSheetCellEnumRendererRefData::SetParameters(const wxString ¶ms) { - if ( params.IsEmpty() ) - return; // what can we do? + if (params.IsEmpty()) { + return; // what can we do? + } - m_choices.Empty(); + m_choices.Empty(); - wxStringTokenizer tk(params, _T(',')); - while ( tk.HasMoreTokens() ) - m_choices.Add(tk.GetNextToken()); + wxStringTokenizer tk(params, _T(',')); + while (tk.HasMoreTokens()) { + m_choices.Add(tk.GetNextToken()); + } } // ---------------------------------------------------------------------------- // wxSheetCellRolColLabelRendererRefData // ---------------------------------------------------------------------------- -void wxSheetCellRolColLabelRendererRefData::Draw(wxSheet& sheet, - const wxSheetCellAttr& attr, - wxDC& dc, - const wxRect& rectCell, - const wxSheetCoords& coords, - bool isSelected) -{ - // erase this cells background - wxRect rect(rectCell); - wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect, coords, isSelected); - - int left = rectCell.x; - int top = rectCell.y; - int right = rectCell.GetRight(); - int bottom = rectCell.GetBottom(); - - //dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) ); - // right side - //dc.DrawLine( right, top, right, bottom ); - // left side - //if (coords.m_col == -1) - // dc.DrawLine( left, top, left, bottom ); - // top side - //if (coords.m_row == -1) - // dc.DrawLine( left, top, right, top ); - // bottom - //dc.DrawLine( left, bottom, right, bottom ); - - dc.SetPen( *wxWHITE_PEN ); - // left highlight - dc.DrawLine( left, top, left, bottom ); - // top highlight - dc.DrawLine( left, top, right, top ); - - SetTextColoursAndFont(sheet, attr, dc, isSelected); - - wxString value = sheet.GetCellValue(coords); - - if (!value.IsEmpty()) - { - int align = attr.GetAlignment(); - int orient = attr.GetOrientation(); - rect.Deflate(2); // want margins - sheet.DrawTextRectangle(dc, value, rect, align, orient); - } +void wxSheetCellRolColLabelRendererRefData::Draw(wxSheet &sheet, const wxSheetCellAttr &attr, + wxDC &dc, const wxRect &rectCell, + const wxSheetCoords &coords, bool isSelected) +{ + // erase this cells background + wxRect rect(rectCell); + wxSheetCellRendererRefData::Draw(sheet, attr, dc, rect, coords, isSelected); + + int left = rectCell.x; + int top = rectCell.y; + int right = rectCell.GetRight(); + int bottom = rectCell.GetBottom(); + + // dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) ); + // right side + // dc.DrawLine( right, top, right, bottom ); + // left side + // if (coords.m_col == -1) + // dc.DrawLine( left, top, left, bottom ); + // top side + // if (coords.m_row == -1) + // dc.DrawLine( left, top, right, top ); + // bottom + // dc.DrawLine( left, bottom, right, bottom ); + + dc.SetPen(*wxWHITE_PEN); + // left highlight + dc.DrawLine(left, top, left, bottom); + // top highlight + dc.DrawLine(left, top, right, top); + + SetTextColoursAndFont(sheet, attr, dc, isSelected); + + wxString value = sheet.GetCellValue(coords); + + if (!value.IsEmpty()) { + int align = attr.GetAlignment(); + int orient = attr.GetOrientation(); + rect.Deflate(2); // want margins + sheet.DrawTextRectangle(dc, value, rect, align, orient); + } #if 0 // test code for sizing, draws corner tick marks diff --git a/src/labenski/src/sheetsel.cpp b/src/labenski/src/sheetsel.cpp index 5e2f547b4..c26f4d35e 100644 --- a/src/labenski/src/sheetsel.cpp +++ b/src/labenski/src/sheetsel.cpp @@ -13,57 +13,61 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/defs.h" - #include "wx/utils.h" // for wxMin and wxMax - #include "wx/gdicmn.h" // for wxRect -#endif // WX_PRECOMP +#include "wx/defs.h" +#include "wx/utils.h" // for wxMin and wxMax +#include "wx/gdicmn.h" // for wxRect +#endif // WX_PRECOMP #include "wx/sheet/sheetsel.h" // if set then -//#define CHECK_BLOCK_OVERLAP 1 -//#define CHECK_BLOCK_SORTING 1 +// #define CHECK_BLOCK_OVERLAP 1 +// #define CHECK_BLOCK_SORTING 1 -#define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), s, b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_BLOCK(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), s, b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArraySheetCoords) WX_DEFINE_OBJARRAY(wxArraySheetBlock) -const wxSheetCoords wxNullSheetCoords( INT_MIN, INT_MIN ); -const wxSheetCoords wxGridCellSheetCoords( 0, 0 ); -const wxSheetCoords wxRowLabelSheetCoords( 0, -1 ); -const wxSheetCoords wxColLabelSheetCoords( -1, 0 ); -const wxSheetCoords wxCornerLabelSheetCoords( -1, -1 ); -const wxSheetBlock wxNullSheetBlock( 0, 0, 0, 0 ); +const wxSheetCoords wxNullSheetCoords(INT_MIN, INT_MIN); +const wxSheetCoords wxGridCellSheetCoords(0, 0); +const wxSheetCoords wxRowLabelSheetCoords(0, -1); +const wxSheetCoords wxColLabelSheetCoords(-1, 0); +const wxSheetCoords wxCornerLabelSheetCoords(-1, -1); +const wxSheetBlock wxNullSheetBlock(0, 0, 0, 0); // ---------------------------------------------------------------------------- // Compare functions for sorting // ---------------------------------------------------------------------------- -static int wxCMPFUNC_CONV wxsheetcellblock_sort_topleft_bottomright( wxSheetBlock **a, wxSheetBlock **b) +static int wxCMPFUNC_CONV wxsheetcellblock_sort_topleft_bottomright(wxSheetBlock **a, + wxSheetBlock **b) { - return (*a)->CmpTopLeft(**b); -/* - int row = ((*a)->m_row - (*b)->m_row); - if (row < 0) return -1; - if (row == 0) return ((*a)->m_col - (*b)->m_col); - return 1; -*/ + return (*a)->CmpTopLeft(**b); + /* + int row = ((*a)->m_row - (*b)->m_row); + if (row < 0) return -1; + if (row == 0) return ((*a)->m_col - (*b)->m_col); + return 1; + */ } -static int wxCMPFUNC_CONV wxsheetcellblock_sort_bottomright_topleft( wxSheetBlock **a, wxSheetBlock **b) +static int wxCMPFUNC_CONV wxsheetcellblock_sort_bottomright_topleft(wxSheetBlock **a, + wxSheetBlock **b) { - return (*b)->CmpRightBottom(**a); -/* - int col = ((*b)->GetRight() - (*a)->GetRight()); - if (col < 0) return -1; - if (col == 0) return ((*b)->GetBottom() - (*a)->GetBottom()); - return 1; -*/ + return (*b)->CmpRightBottom(**a); + /* + int col = ((*b)->GetRight() - (*a)->GetRight()); + if (col < 0) return -1; + if (col == 0) return ((*b)->GetBottom() - (*a)->GetBottom()); + return 1; + */ } // ---------------------------------------------------------------------------- @@ -72,1180 +76,1255 @@ static int wxCMPFUNC_CONV wxsheetcellblock_sort_bottomright_topleft( wxSheetBloc wxSheetCell_Type wxSheetCoords::GetCellCoordsType() const { - if ((m_row >= 0) && (m_col >= 0)) - { - return wxSHEET_CELL_GRID; + if ((m_row >= 0) && (m_col >= 0)) { + return wxSHEET_CELL_GRID; + } + else if (m_row == -1) { + if (m_col == -1) { + return wxSHEET_CELL_CORNERLABEL; } - else if (m_row == -1) - { - if (m_col == -1) - return wxSHEET_CELL_CORNERLABEL; - if (m_col >= 0) - return wxSHEET_CELL_COLLABEL; + if (m_col >= 0) { + return wxSHEET_CELL_COLLABEL; } - else if (m_col == -1) - { - if (m_row >= 0) - return wxSHEET_CELL_ROWLABEL; + } + else if (m_col == -1) { + if (m_row >= 0) { + return wxSHEET_CELL_ROWLABEL; } + } - return wxSHEET_CELL_UNKNOWN; + return wxSHEET_CELL_UNKNOWN; } wxSheetCoords wxSheetCoords::GetCellCoords(wxSheetCell_Type type) const { - switch (type) - { - case wxSHEET_CELL_GRID : break; - case wxSHEET_CELL_ROWLABEL : return wxSheetCoords( m_row, -1-m_col); - case wxSHEET_CELL_COLLABEL : return wxSheetCoords(-1-m_row, m_col); - case wxSHEET_CELL_CORNERLABEL : return wxSheetCoords(-1-m_row, -1-m_col); - default : break; - } - return wxSheetCoords(*this); + switch (type) { + case wxSHEET_CELL_GRID: + break; + case wxSHEET_CELL_ROWLABEL: + return wxSheetCoords(m_row, -1 - m_col); + case wxSHEET_CELL_COLLABEL: + return wxSheetCoords(-1 - m_row, m_col); + case wxSHEET_CELL_CORNERLABEL: + return wxSheetCoords(-1 - m_row, -1 - m_col); + default: + break; + } + return wxSheetCoords(*this); } -wxSheetCoords& wxSheetCoords::SetCellCoords(wxSheetCell_Type type) +wxSheetCoords &wxSheetCoords::SetCellCoords(wxSheetCell_Type type) { - switch (type) - { - case wxSHEET_CELL_GRID : break; - case wxSHEET_CELL_ROWLABEL : m_col = -1-m_col; break; - case wxSHEET_CELL_COLLABEL : m_row = -1-m_row; break; - case wxSHEET_CELL_CORNERLABEL : m_row = -1-m_row; m_col = -1-m_col; break; - default : break; - } - return *this; + switch (type) { + case wxSHEET_CELL_GRID: + break; + case wxSHEET_CELL_ROWLABEL: + m_col = -1 - m_col; + break; + case wxSHEET_CELL_COLLABEL: + m_row = -1 - m_row; + break; + case wxSHEET_CELL_CORNERLABEL: + m_row = -1 - m_row; + m_col = -1 - m_col; + break; + default: + break; + } + return *this; } -bool wxSheetCoords::UpdateRows( size_t row, int numRows ) +bool wxSheetCoords::UpdateRows(size_t row, int numRows) { - if ((numRows == 0) || (m_row < int(row))) return false; - if ((numRows > 0) || (m_row > int(row) - numRows)) - m_row += numRows; - else - m_row = int(row) - 1; // put it at beginning of delete - - return true; + if ((numRows == 0) || (m_row < int(row))) { + return false; + } + if ((numRows > 0) || (m_row > int(row) - numRows)) { + m_row += numRows; + } + else { + m_row = int(row) - 1; // put it at beginning of delete + } + + return true; } -bool wxSheetCoords::UpdateCols( size_t col, int numCols ) +bool wxSheetCoords::UpdateCols(size_t col, int numCols) { - if ((numCols == 0) || (m_col < int(col))) return false; - if ((numCols > 0) || (m_col > int(col) - numCols)) - m_col += numCols; - else - m_col = int(col) - 1; // put it at beginning of delete - - return true; + if ((numCols == 0) || (m_col < int(col))) { + return false; + } + if ((numCols > 0) || (m_col > int(col) - numCols)) { + m_col += numCols; + } + else { + m_col = int(col) - 1; // put it at beginning of delete + } + + return true; } // ---------------------------------------------------------------------------- // wxSheetBlock: a rectangular block of cells // ---------------------------------------------------------------------------- -wxSheetBlock::wxSheetBlock( const wxSheetCoords& coords1, - const wxSheetCoords& coords2, bool make_upright ) +wxSheetBlock::wxSheetBlock(const wxSheetCoords &coords1, const wxSheetCoords &coords2, + bool make_upright) { - m_row = coords1.m_row; - m_col = coords1.m_col; - m_height = coords2.m_row - coords1.m_row; - m_width = coords2.m_col - coords1.m_col; - - // block is upright with coords at corners - if (make_upright) - { - if (m_width < 0) - { - m_width = -m_width; - m_col = coords2.m_col; - } - m_width++; + m_row = coords1.m_row; + m_col = coords1.m_col; + m_height = coords2.m_row - coords1.m_row; + m_width = coords2.m_col - coords1.m_col; + + // block is upright with coords at corners + if (make_upright) { + if (m_width < 0) { + m_width = -m_width; + m_col = coords2.m_col; + } + m_width++; - if (m_height < 0) - { - m_height = -m_height; - m_row = coords2.m_row; - } - m_height++; + if (m_height < 0) { + m_height = -m_height; + m_row = coords2.m_row; } + m_height++; + } } wxArraySheetCoords wxSheetBlock::GetArrayCoords() const { - wxArraySheetCoords arrCoords; - if (IsEmpty()) - return arrCoords; - - arrCoords.Alloc(GetWidth()*GetHeight()); - const int bottom = GetBottom(), right = GetRight(); - wxSheetCoords coords; - - for (coords.m_row = m_row; coords.m_row <= bottom; coords.m_row++) - { - for (coords.m_col = m_col; coords.m_col <= right; coords.m_col++) - arrCoords.Add(coords); + wxArraySheetCoords arrCoords; + if (IsEmpty()) { + return arrCoords; + } + + arrCoords.Alloc(GetWidth() * GetHeight()); + const int bottom = GetBottom(), right = GetRight(); + wxSheetCoords coords; + + for (coords.m_row = m_row; coords.m_row <= bottom; coords.m_row++) { + for (coords.m_col = m_col; coords.m_col <= right; coords.m_col++) { + arrCoords.Add(coords); } + } - return arrCoords; + return arrCoords; } wxSheetBlock wxSheetBlock::GetAligned() const { - return wxSheetBlock( m_height < 0 ? m_row + m_height - 1 : m_row, - m_width < 0 ? m_col + m_width - 1 : m_col, - m_height < 0 ? 2 - m_height : m_height, - m_width < 0 ? 2 - m_width : m_width ); + return wxSheetBlock(m_height < 0 ? m_row + m_height - 1 : m_row, + m_width < 0 ? m_col + m_width - 1 : m_col, + m_height < 0 ? 2 - m_height : m_height, m_width < 0 ? 2 - m_width : m_width); } -wxSheetBlock wxSheetBlock::Intersect( const wxSheetBlock &other ) const +wxSheetBlock wxSheetBlock::Intersect(const wxSheetBlock &other) const { - // no need to check if IsEmpty since wxMin(Right/Bottom) does it - // ugly code, but fastest in gcc - int l = other.GetRight(); - int r = GetRight(); - r = wxMin(r, l); - l = wxMax(m_col, other.m_col); - int w = r-l+1; - if (w < 0) return wxSheetBlock(); - int t = other.GetBottom(); - int b = GetBottom(); - b = wxMin(b, t); - t = wxMax(m_row, other.m_row); - int h = b-t+1; - if (h < 0) return wxSheetBlock(); - return wxSheetBlock(t, l, h, w); - -/* - // simplier code, but slower - //int l = wxMax(m_col, other.m_col); - //int r = wxMin(GetRight(), other.GetRight()); - //int t = wxMax(m_row, other.m_row); - //int b = wxMin(GetBottom(), other.GetBottom()); - //return ((b-t+1 < 0) || (r-l+1 < 0)) ? wxSheetBlock() : - // wxSheetBlock(t, l, b-t+1, r-l+1); -*/ + // no need to check if IsEmpty since wxMin(Right/Bottom) does it + // ugly code, but fastest in gcc + int l = other.GetRight(); + int r = GetRight(); + r = wxMin(r, l); + l = wxMax(m_col, other.m_col); + int w = r - l + 1; + if (w < 0) { + return wxSheetBlock(); + } + int t = other.GetBottom(); + int b = GetBottom(); + b = wxMin(b, t); + t = wxMax(m_row, other.m_row); + int h = b - t + 1; + if (h < 0) { + return wxSheetBlock(); + } + return wxSheetBlock(t, l, h, w); + + /* + // simplier code, but slower + //int l = wxMax(m_col, other.m_col); + //int r = wxMin(GetRight(), other.GetRight()); + //int t = wxMax(m_row, other.m_row); + //int b = wxMin(GetBottom(), other.GetBottom()); + //return ((b-t+1 < 0) || (r-l+1 < 0)) ? wxSheetBlock() : + // wxSheetBlock(t, l, b-t+1, r-l+1); + */ } -wxSheetBlock wxSheetBlock::Union( const wxSheetBlock &other ) const +wxSheetBlock wxSheetBlock::Union(const wxSheetBlock &other) const { - // no need to check if IsEmpty since wxMin(Right/Bottom) does it - // ugly code, but fastest in gcc - int l = other.GetRight(); - int r = GetRight(); - r = wxMax(r, l); - l = wxMin(m_col, other.m_col); - int w = r-l+1; - if (w < 0) return wxSheetBlock(); - int t = other.GetBottom(); - int b = GetBottom(); - b = wxMax(b, t); - t = wxMin(m_row, other.m_row); - int h = b-t+1; - if (h < 0) return wxSheetBlock(); - return wxSheetBlock(t, l, h, w); - -/* - // simplier code, but slower - //int l = wxMin(m_col, other.m_col); - //int r = wxMax(GetRight(), other.GetRight()); - //int t = wxMin(m_row, other.m_row); - //int b = wxMax(GetBottom(), other.GetBottom()); - //return wxSheetBlock(t, l, wxMax(b-t+1, 0), wxMax(r-l+1, 0)); -*/ + // no need to check if IsEmpty since wxMin(Right/Bottom) does it + // ugly code, but fastest in gcc + int l = other.GetRight(); + int r = GetRight(); + r = wxMax(r, l); + l = wxMin(m_col, other.m_col); + int w = r - l + 1; + if (w < 0) { + return wxSheetBlock(); + } + int t = other.GetBottom(); + int b = GetBottom(); + b = wxMax(b, t); + t = wxMin(m_row, other.m_row); + int h = b - t + 1; + if (h < 0) { + return wxSheetBlock(); + } + return wxSheetBlock(t, l, h, w); + + /* + // simplier code, but slower + //int l = wxMin(m_col, other.m_col); + //int r = wxMax(GetRight(), other.GetRight()); + //int t = wxMin(m_row, other.m_row); + //int b = wxMax(GetBottom(), other.GetBottom()); + //return wxSheetBlock(t, l, wxMax(b-t+1, 0), wxMax(r-l+1, 0)); + */ } -wxSheetBlock wxSheetBlock::ExpandUnion( const wxSheetBlock &other ) const +wxSheetBlock wxSheetBlock::ExpandUnion(const wxSheetBlock &other) const { - if (IsEmpty()) return other; // preserve other block - if (other.IsEmpty()) return *this; // preserve this - - // ugly code, but fastest in gcc - int l = other.GetRight(); - int r = GetRight(); - r = wxMax(r, l); - l = wxMin(m_col, other.m_col); - int t = other.GetBottom(); - int b = GetBottom(); - b = wxMax(b, t); - t = wxMin(m_row, other.m_row); - return wxSheetBlock(t, l, b-t+1, r-l+1); - -/* - // simplier code, but slower - //int l = wxMin(m_col, other.m_col); - //int r = wxMax(GetRight(), other.GetRight()); - //int t = wxMin(m_row, other.m_row); - //int b = wxMax(GetBottom(), other.GetBottom()); - //return wxSheetBlock(t, l, b-t+1, r-l+1); -*/ + if (IsEmpty()) { + return other; // preserve other block + } + if (other.IsEmpty()) { + return *this; // preserve this + } + + // ugly code, but fastest in gcc + int l = other.GetRight(); + int r = GetRight(); + r = wxMax(r, l); + l = wxMin(m_col, other.m_col); + int t = other.GetBottom(); + int b = GetBottom(); + b = wxMax(b, t); + t = wxMin(m_row, other.m_row); + return wxSheetBlock(t, l, b - t + 1, r - l + 1); + + /* + // simplier code, but slower + //int l = wxMin(m_col, other.m_col); + //int r = wxMax(GetRight(), other.GetRight()); + //int t = wxMin(m_row, other.m_row); + //int b = wxMax(GetBottom(), other.GetBottom()); + //return wxSheetBlock(t, l, b-t+1, r-l+1); + */ } bool wxSheetBlock::Combine(const wxSheetBlock &block) { - //if (IsEmpty() || block.IsEmpty()) return false; - if (!Touches(block)) return false; - if (Contains(block)) return true; - if (block.Contains(*this)) - { - *this = block; - return true; - } - - // FIXME I forgot why wxSheetBlock::Combine needs this code? Isn't Contains good enough? - const wxSheetBlock uBlock(Union(block)); - if (uBlock.IsEmpty()) return false; - - // ugh this is really ugly, I can't figure a better way though -/* - // at least one of the two blocks has to be at each corner of the union - if (((uBlock.GetLeftTop() == GetLeftTop()) || (uBlock.GetLeftTop() == block.GetLeftTop())) && - ((uBlock.GetRightTop() == GetRightTop()) || (uBlock.GetRightTop() == block.GetRightTop())) && - ((uBlock.GetLeftBottom() == GetLeftBottom()) || (uBlock.GetLeftBottom() == block.GetLeftBottom())) && - ((uBlock.GetRightBottom() == GetRightBottom()) || (uBlock.GetRightBottom() == block.GetRightBottom())) ) - { - *this = uBlock; - return true; - } -*/ - - const int t = GetTop(); - const int b = GetBottom(); - const int l = GetLeft(); - const int r = GetRight(); - - const int b_t = block.GetTop(); - const int b_b = block.GetBottom(); - const int b_l = block.GetLeft(); - const int b_r = block.GetRight(); - - const int ub_t = uBlock.GetTop(); - const int ub_b = uBlock.GetBottom(); - const int ub_l = uBlock.GetLeft(); - const int ub_r = uBlock.GetRight(); - - if ( ( ((ub_t==t)&&(ub_l==l)) || ((ub_t==b_t)&&(ub_l==b_l)) ) && - ( ((ub_t==t)&&(ub_r==r)) || ((ub_t==b_t)&&(ub_r==b_r)) ) && - ( ((ub_b==b)&&(ub_l==l)) || ((ub_b==b_b)&&(ub_l==b_l)) ) && - ( ((ub_b==b)&&(ub_r==r)) || ((ub_b==b_b)&&(ub_r==b_r)) ) ) - { - *this = uBlock; - return true; - } - + // if (IsEmpty() || block.IsEmpty()) return false; + if (!Touches(block)) { return false; + } + if (Contains(block)) { + return true; + } + if (block.Contains(*this)) { + *this = block; + return true; + } - -/* - const int t = GetTop(); - const int b = GetBottom(); - const int l = GetLeft(); - const int r = GetRight(); - if ((t < b) || (l < r)) return false; // this is empty - - const int b_t = block.GetTop(); - const int b_b = block.GetBottom(); - const int b_l = block.GetLeft(); - const int b_r = block.GetRight(); - if ((b_t < b_b) || (b_l < b_r)) return false; // block is empty - - // if this contains other block - if ((t <= b_t) && (l <= b_l) && (b >= b_b) && (r >= b_r)) - return true; - // if block contains this - if ((t >= b_t) && (l >= b_l) && (b <= b_b) && (r <= b_r)) - { - *this = block; - return true; - } - - - const int ub_t = uBlock.GetTop(); - const int ub_b = uBlock.GetBottom(); - const int ub_l = uBlock.GetLeft(); - const int ub_r = uBlock.GetRight(); - - if ( ( ((ub_t==t)&&(ub_l==l)) || ((ub_t==b_t)&&(ub_l==b_l)) ) && - ( ((ub_t==t)&&(ub_r==r)) || ((ub_t==b_t)&&(ub_r==b_r)) ) && - ( ((ub_b==b)&&(ub_l==l)) || ((ub_b==b_b)&&(ub_l==b_l)) ) && - ( ((ub_b==b)&&(ub_r==r)) || ((ub_b==b_b)&&(ub_r==b_r)) ) ) - { - *this = uBlock; - return true; - } - + // FIXME I forgot why wxSheetBlock::Combine needs this code? Isn't Contains good enough? + const wxSheetBlock uBlock(Union(block)); + if (uBlock.IsEmpty()) { return false; -*/ + } + + // ugh this is really ugly, I can't figure a better way though + /* + // at least one of the two blocks has to be at each corner of the union + if (((uBlock.GetLeftTop() == GetLeftTop()) || (uBlock.GetLeftTop() == block.GetLeftTop())) && + ((uBlock.GetRightTop() == GetRightTop()) || (uBlock.GetRightTop() == + block.GetRightTop())) && + ((uBlock.GetLeftBottom() == GetLeftBottom()) || (uBlock.GetLeftBottom() == + block.GetLeftBottom())) && + ((uBlock.GetRightBottom() == GetRightBottom()) || (uBlock.GetRightBottom() == + block.GetRightBottom())) ) + { + *this = uBlock; + return true; + } + */ + + const int t = GetTop(); + const int b = GetBottom(); + const int l = GetLeft(); + const int r = GetRight(); + + const int b_t = block.GetTop(); + const int b_b = block.GetBottom(); + const int b_l = block.GetLeft(); + const int b_r = block.GetRight(); + + const int ub_t = uBlock.GetTop(); + const int ub_b = uBlock.GetBottom(); + const int ub_l = uBlock.GetLeft(); + const int ub_r = uBlock.GetRight(); + + if ((((ub_t == t) && (ub_l == l)) || ((ub_t == b_t) && (ub_l == b_l))) && + (((ub_t == t) && (ub_r == r)) || ((ub_t == b_t) && (ub_r == b_r))) && + (((ub_b == b) && (ub_l == l)) || ((ub_b == b_b) && (ub_l == b_l))) && + (((ub_b == b) && (ub_r == r)) || ((ub_b == b_b) && (ub_r == b_r)))) { + *this = uBlock; + return true; + } + + return false; + + /* + const int t = GetTop(); + const int b = GetBottom(); + const int l = GetLeft(); + const int r = GetRight(); + if ((t < b) || (l < r)) return false; // this is empty + + const int b_t = block.GetTop(); + const int b_b = block.GetBottom(); + const int b_l = block.GetLeft(); + const int b_r = block.GetRight(); + if ((b_t < b_b) || (b_l < b_r)) return false; // block is empty + + // if this contains other block + if ((t <= b_t) && (l <= b_l) && (b >= b_b) && (r >= b_r)) + return true; + // if block contains this + if ((t >= b_t) && (l >= b_l) && (b <= b_b) && (r <= b_r)) + { + *this = block; + return true; + } + + + const int ub_t = uBlock.GetTop(); + const int ub_b = uBlock.GetBottom(); + const int ub_l = uBlock.GetLeft(); + const int ub_r = uBlock.GetRight(); + + if ( ( ((ub_t==t)&&(ub_l==l)) || ((ub_t==b_t)&&(ub_l==b_l)) ) && + ( ((ub_t==t)&&(ub_r==r)) || ((ub_t==b_t)&&(ub_r==b_r)) ) && + ( ((ub_b==b)&&(ub_l==l)) || ((ub_b==b_b)&&(ub_l==b_l)) ) && + ( ((ub_b==b)&&(ub_r==r)) || ((ub_b==b_b)&&(ub_r==b_r)) ) ) + { + *this = uBlock; + return true; + } + + return false; + */ } -int wxSheetBlock::Combine( const wxSheetBlock &block, - wxSheetBlock &top, wxSheetBlock &bottom, - wxSheetBlock &left, wxSheetBlock &right ) const +int wxSheetBlock::Combine(const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, + wxSheetBlock &left, wxSheetBlock &right) const { - wxSheetBlock iBlock(Intersect(block)); - if (iBlock.IsEmpty()) return wxSHEET_BLOCK_NONE; // nothing to combine - if (Contains(block)) return wxSHEET_BLOCK_ALL; // can combine all of block, no leftover - - int combined = wxSHEET_BLOCK_NONE; - - if ( block.GetTop() < GetTop() ) - { - top.SetCoords( block.GetTop(), block.GetLeft(), GetTop()-1, block.GetRight() ); - combined |= wxSHEET_BLOCK_TOP; - } - if ( block.GetBottom() > GetBottom() ) - { - bottom.SetCoords( GetBottom()+1, block.GetLeft(), block.GetBottom(), block.GetRight() ); - combined |= wxSHEET_BLOCK_BOTTOM; - } - if ( block.GetLeft() < GetLeft() ) - { - left.SetCoords(iBlock.GetTop(), block.GetLeft(), iBlock.GetBottom(), GetLeft()-1 ); - combined |= wxSHEET_BLOCK_LEFT; - } - if ( block.GetRight() > GetRight() ) - { - right.SetCoords( iBlock.GetTop(), GetRight()+1, iBlock.GetBottom(), block.GetRight() ); - combined |= wxSHEET_BLOCK_RIGHT; - } - - return combined; + wxSheetBlock iBlock(Intersect(block)); + if (iBlock.IsEmpty()) { + return wxSHEET_BLOCK_NONE; // nothing to combine + } + if (Contains(block)) { + return wxSHEET_BLOCK_ALL; // can combine all of block, no leftover + } + + int combined = wxSHEET_BLOCK_NONE; + + if (block.GetTop() < GetTop()) { + top.SetCoords(block.GetTop(), block.GetLeft(), GetTop() - 1, block.GetRight()); + combined |= wxSHEET_BLOCK_TOP; + } + if (block.GetBottom() > GetBottom()) { + bottom.SetCoords(GetBottom() + 1, block.GetLeft(), block.GetBottom(), block.GetRight()); + combined |= wxSHEET_BLOCK_BOTTOM; + } + if (block.GetLeft() < GetLeft()) { + left.SetCoords(iBlock.GetTop(), block.GetLeft(), iBlock.GetBottom(), GetLeft() - 1); + combined |= wxSHEET_BLOCK_LEFT; + } + if (block.GetRight() > GetRight()) { + right.SetCoords(iBlock.GetTop(), GetRight() + 1, iBlock.GetBottom(), block.GetRight()); + combined |= wxSHEET_BLOCK_RIGHT; + } + + return combined; } -int wxSheetBlock::Delete( const wxSheetBlock &block, - wxSheetBlock &top, wxSheetBlock &bottom, - wxSheetBlock &left, wxSheetBlock &right ) const +int wxSheetBlock::Delete(const wxSheetBlock &block, wxSheetBlock &top, wxSheetBlock &bottom, + wxSheetBlock &left, wxSheetBlock &right) const { - wxSheetBlock iBlock(Intersect(block)); - if (iBlock.IsEmpty()) return wxSHEET_BLOCK_NONE; // nothing to delete - if (block.Contains(*this)) return wxSHEET_BLOCK_ALL; // can delete all of this, no leftover - - int deleted = wxSHEET_BLOCK_NONE; - - if ( GetTop() < iBlock.GetTop() ) - { - top.SetCoords( GetTop(), GetLeft(), iBlock.GetTop()-1, GetRight() ); - deleted |= wxSHEET_BLOCK_TOP; - } - if ( GetBottom() > iBlock.GetBottom() ) - { - bottom.SetCoords( iBlock.GetBottom()+1, GetLeft(), GetBottom(), GetRight() ); - deleted |= wxSHEET_BLOCK_BOTTOM; - } - if ( GetLeft() < iBlock.GetLeft() ) - { - left.SetCoords( iBlock.GetTop(), GetLeft(), iBlock.GetBottom(), iBlock.GetLeft()-1 ); - deleted |= wxSHEET_BLOCK_LEFT; - } - if ( GetRight() > iBlock.GetRight() ) - { - right.SetCoords( iBlock.GetTop(), iBlock.GetRight()+1, iBlock.GetBottom(), GetRight() ); - deleted |= wxSHEET_BLOCK_RIGHT; - } - - return deleted; + wxSheetBlock iBlock(Intersect(block)); + if (iBlock.IsEmpty()) { + return wxSHEET_BLOCK_NONE; // nothing to delete + } + if (block.Contains(*this)) { + return wxSHEET_BLOCK_ALL; // can delete all of this, no leftover + } + + int deleted = wxSHEET_BLOCK_NONE; + + if (GetTop() < iBlock.GetTop()) { + top.SetCoords(GetTop(), GetLeft(), iBlock.GetTop() - 1, GetRight()); + deleted |= wxSHEET_BLOCK_TOP; + } + if (GetBottom() > iBlock.GetBottom()) { + bottom.SetCoords(iBlock.GetBottom() + 1, GetLeft(), GetBottom(), GetRight()); + deleted |= wxSHEET_BLOCK_BOTTOM; + } + if (GetLeft() < iBlock.GetLeft()) { + left.SetCoords(iBlock.GetTop(), GetLeft(), iBlock.GetBottom(), iBlock.GetLeft() - 1); + deleted |= wxSHEET_BLOCK_LEFT; + } + if (GetRight() > iBlock.GetRight()) { + right.SetCoords(iBlock.GetTop(), iBlock.GetRight() + 1, iBlock.GetBottom(), GetRight()); + deleted |= wxSHEET_BLOCK_RIGHT; + } + + return deleted; } -bool wxSheetBlock::UpdateRows( size_t row_, int numRows ) +bool wxSheetBlock::UpdateRows(size_t row_, int numRows) { - int row = row_; - if ((numRows == 0) || (GetBottom() < row)) return false; - bool remove = numRows < 0; - - // this starts above the deleted rows - if (m_row < row) - { - // this ends within deleted rows, trim to row - if (remove && (GetBottom() < row - numRows)) - SetBottom(row-1); - // this straddles the inserted/deleted rows - resize - else - m_height += numRows; - } - // This is fully below it or an insert - shift coord - else if (!remove || (m_row > row + labs(numRows))) - { - m_row += numRows; + int row = row_; + if ((numRows == 0) || (GetBottom() < row)) { + return false; + } + bool remove = numRows < 0; + + // this starts above the deleted rows + if (m_row < row) { + // this ends within deleted rows, trim to row + if (remove && (GetBottom() < row - numRows)) { + SetBottom(row - 1); } - // a remove and this's row is in deleted rows - else - { - m_height += m_row - (row - numRows); - m_row = row; + // this straddles the inserted/deleted rows - resize + else { + m_height += numRows; } - - return true; + } + // This is fully below it or an insert - shift coord + else if (!remove || (m_row > row + labs(numRows))) { + m_row += numRows; + } + // a remove and this's row is in deleted rows + else { + m_height += m_row - (row - numRows); + m_row = row; + } + + return true; } -bool wxSheetBlock::UpdateCols( size_t col_, int numCols ) +bool wxSheetBlock::UpdateCols(size_t col_, int numCols) { - int col = col_; - if ((numCols == 0) || (GetRight() < col)) return false; - bool remove = numCols < 0; - - // this starts above the deleted rows - if (m_col < col) - { - // this ends within deleted rows, trim to row - if (remove && (GetRight() < col - numCols)) - SetRight(col-1); - // this straddles the inserted/deleted rows - resize - else - m_width += numCols; - } - // This is fully below it or an insert - shift coord - else if (!remove || (m_col > col + labs(numCols))) - { - m_col += numCols; + int col = col_; + if ((numCols == 0) || (GetRight() < col)) { + return false; + } + bool remove = numCols < 0; + + // this starts above the deleted rows + if (m_col < col) { + // this ends within deleted rows, trim to row + if (remove && (GetRight() < col - numCols)) { + SetRight(col - 1); } - // a remove and this's row is in deleted rows - else - { - m_width += m_col - (col - numCols); - m_col = col; + // this straddles the inserted/deleted rows - resize + else { + m_width += numCols; } - - return true; + } + // This is fully below it or an insert - shift coord + else if (!remove || (m_col > col + labs(numCols))) { + m_col += numCols; + } + // a remove and this's row is in deleted rows + else { + m_width += m_col - (col - numCols); + m_col = col; + } + + return true; } -int wxSheetBlock::CmpTopLeft(const wxSheetBlock& b) const +int wxSheetBlock::CmpTopLeft(const wxSheetBlock &b) const { - int cmp = m_row - b.m_row; if (cmp != 0) return cmp; - cmp = m_col - b.m_col; if (cmp != 0) return cmp; - cmp = m_height - b.m_height; if (cmp != 0) return cmp; - cmp = m_width - b.m_width; return cmp; + int cmp = m_row - b.m_row; + if (cmp != 0) { + return cmp; + } + cmp = m_col - b.m_col; + if (cmp != 0) { + return cmp; + } + cmp = m_height - b.m_height; + if (cmp != 0) { + return cmp; + } + cmp = m_width - b.m_width; + return cmp; } -int wxSheetBlock::CmpRightBottom(const wxSheetBlock& b) const +int wxSheetBlock::CmpRightBottom(const wxSheetBlock &b) const { - int cmp = GetRight() - b.GetRight(); if (cmp != 0) return cmp; - cmp = GetBottom() - b.GetBottom(); if (cmp != 0) return cmp; - cmp = m_col - b.m_col; if (cmp != 0) return cmp; - cmp = m_row - b.m_row; return cmp; + int cmp = GetRight() - b.GetRight(); + if (cmp != 0) { + return cmp; + } + cmp = GetBottom() - b.GetBottom(); + if (cmp != 0) { + return cmp; + } + cmp = m_col - b.m_col; + if (cmp != 0) { + return cmp; + } + cmp = m_row - b.m_row; + return cmp; } // ---------------------------------------------------------------------------- // wxSheetSelection // ---------------------------------------------------------------------------- -wxSheetSelection::wxSheetSelection(int options) - : m_minimized(true), m_options(options) -{ -} +wxSheetSelection::wxSheetSelection(int options) : m_minimized(true), m_options(options) {} -wxSheetSelection::wxSheetSelection( const wxSheetBlock& block, int options ) - : m_minimized(true), m_options(options) +wxSheetSelection::wxSheetSelection(const wxSheetBlock &block, int options) + : m_minimized(true), m_options(options) { - if (!block.IsEmpty()) - { - m_blocks.Add(block); - m_bounds = block; - } + if (!block.IsEmpty()) { + m_blocks.Add(block); + m_bounds = block; + } } void wxSheetSelection::Copy(const wxSheetSelection &source) { - m_blocks.Clear(); - WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); - m_bounds = source.GetBoundingBlock(); - m_minimized = source.IsMinimzed(); - m_options = source.GetOptions(); + m_blocks.Clear(); + WX_APPEND_ARRAY(m_blocks, source.GetBlockArray()); + m_bounds = source.GetBoundingBlock(); + m_minimized = source.IsMinimzed(); + m_options = source.GetOptions(); } -const wxSheetBlock& wxSheetSelection::GetBlock( size_t index ) const +const wxSheetBlock &wxSheetSelection::GetBlock(size_t index) const { - wxCHECK_MSG(index < m_blocks.GetCount(), wxNullSheetBlock, wxT("Invalid index")); - return m_blocks[index]; + wxCHECK_MSG(index < m_blocks.GetCount(), wxNullSheetBlock, wxT("Invalid index")); + return m_blocks[index]; } -void wxSheetSelection::SetBoundingBlock(const wxSheetBlock& block) +void wxSheetSelection::SetBoundingBlock(const wxSheetBlock &block) { - m_bounds = wxNullSheetBlock; - if (block.IsEmpty()) - { - Clear(); - return; + m_bounds = wxNullSheetBlock; + if (block.IsEmpty()) { + Clear(); + return; + } + + int n, count = m_blocks.GetCount(); + + for (n = 0; n < count; n++) { + m_blocks[n] = block.Intersect(m_blocks[n]); + if (m_blocks[n].IsEmpty()) { + m_blocks.RemoveAt(n); + count--; + n--; } - - int n, count = m_blocks.GetCount(); - - for (n=0; n m_blocks[hi-1]) return hi; - - while ( lo < hi ) - { - n = (lo + hi)/2; - const wxSheetBlock& tmp = m_blocks[n]; - if (tmp == block) return n; - if (tmp > block) hi = n; - else lo = n + 1; + size_t n, lo = 0, hi = m_blocks.GetCount(); + if ((hi == 0) || (block < m_blocks[0])) { + return 0; + } + if (block > m_blocks[hi - 1]) { + return hi; + } + + while (lo < hi) { + n = (lo + hi) / 2; + const wxSheetBlock &tmp = m_blocks[n]; + if (tmp == block) { + return n; } - return lo; + if (tmp > block) { + hi = n; + } + else { + lo = n + 1; + } + } + return lo; } int wxSheetSelection::FindTopRow(int row) const { - size_t n, lo = 0, hi = m_blocks.GetCount(); - if ((hi == 0) || (row >= m_blocks[0].GetTop())) return 0; - if (row < m_blocks[hi-1u].GetTop()) return hi; - - while ( lo < hi ) - { - n = (lo + hi)/2; - const int tmp_row = m_blocks[n].GetTop(); - if (tmp_row > row) hi = n; - else lo = n + 1; + size_t n, lo = 0, hi = m_blocks.GetCount(); + if ((hi == 0) || (row >= m_blocks[0].GetTop())) { + return 0; + } + if (row < m_blocks[hi - 1u].GetTop()) { + return hi; + } + + while (lo < hi) { + n = (lo + hi) / 2; + const int tmp_row = m_blocks[n].GetTop(); + if (tmp_row > row) { + hi = n; + } + else { + lo = n + 1; } - return lo; + } + return lo; } -int wxSheetSelection::IndexIntersects( const wxSheetBlock& block ) const +int wxSheetSelection::IndexIntersects(const wxSheetBlock &block) const { - int n, count = m_blocks.GetCount(); - const int bottom_row = block.GetBottom(); - if ((count == 0) || !m_bounds.Intersects(block)) - return wxNOT_FOUND; - - for (n=FindTopRow(bottom_row); nClear(); - - wxArraySheetBlock extraBlocks; - wxSheetBlock top, bottom, left, right; - // iterate though blocks cutting input block out and adding remainder to end - for (n=FindTopRow(bottom_row); nClear(); + } + + wxArraySheetBlock extraBlocks; + wxSheetBlock top, bottom, left, right; + // iterate though blocks cutting input block out and adding remainder to end + for (n = FindTopRow(bottom_row); n < count; n++) { + if (bottom_row < m_blocks[n].GetTop()) { + break; + } - const int deleted = m_blocks[n].Delete(block, top, bottom, left, right); - if (deleted != wxSHEET_BLOCK_NONE) - { - done = true; - int last_n = n; - - if (deletedBlocks) - deletedBlocks->Add(m_blocks[n].Intersect(block)); - if (m_bounds.SideMatches(m_blocks[n]) != wxSHEET_BLOCK_NONE) - recalc_bounds = true; - - if (m_blocks[n].Contains(block)) - n = count + 100; // all done, but add cutouts back - else - n--; - - m_blocks.RemoveAt(last_n); - count--; - - if (deleted != wxSHEET_BLOCK_ALL) - { - if ((deleted & wxSHEET_BLOCK_TOP) != 0) - extraBlocks.Add(top); - if ((deleted & wxSHEET_BLOCK_BOTTOM) != 0) - extraBlocks.Add(bottom); - if ((deleted & wxSHEET_BLOCK_LEFT) != 0) - extraBlocks.Add(left); - if ((deleted & wxSHEET_BLOCK_RIGHT) != 0) - extraBlocks.Add(right); - } + const int deleted = m_blocks[n].Delete(block, top, bottom, left, right); + if (deleted != wxSHEET_BLOCK_NONE) { + done = true; + int last_n = n; + + if (deletedBlocks) { + deletedBlocks->Add(m_blocks[n].Intersect(block)); + } + if (m_bounds.SideMatches(m_blocks[n]) != wxSHEET_BLOCK_NONE) { + recalc_bounds = true; + } + + if (m_blocks[n].Contains(block)) { + n = count + 100; // all done, but add cutouts back + } + else { + n--; + } + + m_blocks.RemoveAt(last_n); + count--; + + if (deleted != wxSHEET_BLOCK_ALL) { + if ((deleted & wxSHEET_BLOCK_TOP) != 0) { + extraBlocks.Add(top); + } + if ((deleted & wxSHEET_BLOCK_BOTTOM) != 0) { + extraBlocks.Add(bottom); + } + if ((deleted & wxSHEET_BLOCK_LEFT) != 0) { + extraBlocks.Add(left); } + if ((deleted & wxSHEET_BLOCK_RIGHT) != 0) { + extraBlocks.Add(right); + } + } } + } - if (done) - { - m_minimized = false; - const int extra_count = extraBlocks.GetCount(); - for (n=0; nClear(); - } + if (block.IsEmpty()) { + return false; + } + + wxArraySheetBlock extraBlocks; + wxArraySheetBlock *extra = &extraBlocks; + if (addedBlocks) { + extra = addedBlocks; + extra->Clear(); + } + + extra->Add(block); + int extra_count = 1; - extra->Add(block); - int extra_count = 1; - - int n, k, count = m_blocks.GetCount(); - if (((m_options & wxSHEET_SELECTION_MULTIPLE_SEL) == 0) && (count > 0) && - m_bounds.Intersects(block)) - { - const int bottom_row = block.GetBottom(); - wxSheetBlock top, bottom, left, right; - - // interate though blocks breaking up input block if it's already selected - for (n=FindTopRow(bottom_row); nItem(k), top, bottom, left, right); - if (combined != wxSHEET_BLOCK_NONE) - { - extra->RemoveAt(k); - extra_count--; - k--; - - if (combined != wxSHEET_BLOCK_ALL) - { - if ((combined & wxSHEET_BLOCK_TOP) != 0) - { extra->Add(top); extra_count++; } - if ((combined & wxSHEET_BLOCK_BOTTOM) != 0) - { extra->Add(bottom); extra_count++; } - if ((combined & wxSHEET_BLOCK_LEFT) != 0) - { extra->Add(left); extra_count++; } - if ((combined & wxSHEET_BLOCK_RIGHT) != 0) - { extra->Add(right); extra_count++; } - } - - if (extra_count == 0) - { - n = count; - break; - } - } + int n, k, count = m_blocks.GetCount(); + if (((m_options & wxSHEET_SELECTION_MULTIPLE_SEL) == 0) && (count > 0) && + m_bounds.Intersects(block)) { + const int bottom_row = block.GetBottom(); + wxSheetBlock top, bottom, left, right; + + // interate though blocks breaking up input block if it's already selected + for (n = FindTopRow(bottom_row); n < count; n++) { + if (bottom_row < m_blocks[n].GetTop()) { + break; + } + + for (k = 0; k < extra_count; k++) { + const int combined = m_blocks[n].Combine(extra->Item(k), top, bottom, left, right); + if (combined != wxSHEET_BLOCK_NONE) { + extra->RemoveAt(k); + extra_count--; + k--; + + if (combined != wxSHEET_BLOCK_ALL) { + if ((combined & wxSHEET_BLOCK_TOP) != 0) { + extra->Add(top); + extra_count++; + } + if ((combined & wxSHEET_BLOCK_BOTTOM) != 0) { + extra->Add(bottom); + extra_count++; + } + if ((combined & wxSHEET_BLOCK_LEFT) != 0) { + extra->Add(left); + extra_count++; } + if ((combined & wxSHEET_BLOCK_RIGHT) != 0) { + extra->Add(right); + extra_count++; + } + } + + if (extra_count == 0) { + n = count; + break; + } } + } } + } #ifdef CHECK_BLOCK_SORTING - for (int m=1; mItem(n)); - if (combineNow) - Minimize(); - - return true; + if (extra_count != 0) { + m_minimized = false; + for (n = 0; n < extra_count; n++) { + InsertBlock(extra->Item(n)); + } + if (combineNow) { + Minimize(); } - return false; + return true; + } + + return false; } -int wxSheetSelection::InsertBlock(const wxSheetBlock& block) +int wxSheetSelection::InsertBlock(const wxSheetBlock &block) { - const int index = FindInsertIndex(block); - m_blocks.Insert(block, index); - m_bounds = m_bounds.ExpandUnion(block); - return index; + const int index = FindInsertIndex(block); + m_blocks.Insert(block, index); + m_bounds = m_bounds.ExpandUnion(block); + return index; } void wxSheetSelection::CalculateBounds() { - int n, count = m_blocks.GetCount(); - if (count == 0) - { - m_bounds = wxNullSheetBlock; - return; - } + int n, count = m_blocks.GetCount(); + if (count == 0) { + m_bounds = wxNullSheetBlock; + return; + } - m_bounds = m_blocks[0]; + m_bounds = m_blocks[0]; - for (n=1; n 0 ? 1000 : 0; - for (n=0; n 0 ? 1000 : 0; + for (n = 0; n < count; n++) // usually just takes a few + { + if (!DoDoMinimize(blocks)) { + break; } + } - // sanity check - this shouldn't and hasn't happened - wxCHECK_MSG(!count || (n <= count), true, wxT("Unable to minimize wxSheetSelection")); + // sanity check - this shouldn't and hasn't happened + wxCHECK_MSG(!count || (n <= count), true, wxT("Unable to minimize wxSheetSelection")); #ifdef CHECK_BLOCK_OVERLAP - for (size_t a=0; a= int(m_blocks.GetCount()))) - return wxSHEET_SELECTIONITER_GET_END; - - // first time here - if (m_block_index < 0) - { - m_block_index = 0; - coord = m_coords = m_blocks[m_block_index].GetLeftTop(); - return wxSHEET_SELECTIONITER_GET_LEFTTOP; + if ((m_blocks.GetCount() < 1u) || (m_block_index >= int(m_blocks.GetCount()))) { + return wxSHEET_SELECTIONITER_GET_END; + } + + // first time here + if (m_block_index < 0) { + m_block_index = 0; + coord = m_coords = m_blocks[m_block_index].GetLeftTop(); + return wxSHEET_SELECTIONITER_GET_LEFTTOP; + } + + // at end of block swap to new one + if (m_coords == m_blocks[m_block_index].GetRightBottom()) { + ++m_block_index; + if (m_block_index < int(m_blocks.GetCount())) { + coord = m_coords = m_blocks[m_block_index].GetLeftTop(); + return wxSHEET_SELECTIONITER_GET_LEFTTOP; } - - // at end of block swap to new one - if (m_coords == m_blocks[m_block_index].GetRightBottom()) - { - ++m_block_index; - if (m_block_index < int(m_blocks.GetCount())) - { - coord = m_coords = m_blocks[m_block_index].GetLeftTop(); - return wxSHEET_SELECTIONITER_GET_LEFTTOP; - } - else // past end nothing more to check - return wxSHEET_SELECTIONITER_GET_END; - } - // at end of col, down to next row - if (m_coords.GetCol() == m_blocks[m_block_index].GetRight()) - { - m_coords.SetCol(m_blocks[m_block_index].GetLeft()); - m_coords.m_row++; - - coord = m_coords; - return (coord == m_blocks[m_block_index].GetRightBottom()) ? - wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM : wxSHEET_SELECTIONITER_GET_NEXTROW; + else { // past end nothing more to check + return wxSHEET_SELECTIONITER_GET_END; } + } + // at end of col, down to next row + if (m_coords.GetCol() == m_blocks[m_block_index].GetRight()) { + m_coords.SetCol(m_blocks[m_block_index].GetLeft()); + m_coords.m_row++; - // increment the col - m_coords.m_col++; coord = m_coords; + return (coord == m_blocks[m_block_index].GetRightBottom()) + ? wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM + : wxSHEET_SELECTIONITER_GET_NEXTROW; + } + + // increment the col + m_coords.m_col++; + coord = m_coords; - return wxSHEET_SELECTIONITER_GET_NEXTCOL; + return wxSHEET_SELECTIONITER_GET_NEXTCOL; } wxSheetSelectionIterGet_Type wxSheetSelectionIterator::GetNextReverse(wxSheetCoords &coord) { - if ((m_blocks.GetCount() < 1u) || (m_block_index >= int(m_blocks.GetCount()))) - return wxSHEET_SELECTIONITER_GET_END; - - // first time here - if (m_block_index < 0) - { - m_block_index = 0; - coord = m_coords = m_blocks[m_block_index].GetRightBottom(); - return wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM; + if ((m_blocks.GetCount() < 1u) || (m_block_index >= int(m_blocks.GetCount()))) { + return wxSHEET_SELECTIONITER_GET_END; + } + + // first time here + if (m_block_index < 0) { + m_block_index = 0; + coord = m_coords = m_blocks[m_block_index].GetRightBottom(); + return wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM; + } + + // at end of block swap to new one + if (m_coords == m_blocks[m_block_index].GetLeftTop()) { + ++m_block_index; + if (m_block_index < int(m_blocks.GetCount())) { + coord = m_coords = m_blocks[m_block_index].GetRightBottom(); + return wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM; } - - // at end of block swap to new one - if (m_coords == m_blocks[m_block_index].GetLeftTop()) - { - ++m_block_index; - if (m_block_index < int(m_blocks.GetCount())) - { - coord = m_coords = m_blocks[m_block_index].GetRightBottom(); - return wxSHEET_SELECTIONITER_GET_RIGHTBOTTOM; - } - else // past end nothing more to check - return wxSHEET_SELECTIONITER_GET_END; + else { // past end nothing more to check + return wxSHEET_SELECTIONITER_GET_END; } + } - // at left col, up to next row - if (m_coords.GetCol() == m_blocks[m_block_index].GetLeft()) - { - m_coords.SetCol(m_blocks[m_block_index].GetRight()); - m_coords.m_row--; - - coord = m_coords; - return (coord == m_blocks[m_block_index].GetLeftTop()) ? - wxSHEET_SELECTIONITER_GET_LEFTTOP : wxSHEET_SELECTIONITER_GET_NEXTROW; - } - // increment the col - m_coords.m_col--; + // at left col, up to next row + if (m_coords.GetCol() == m_blocks[m_block_index].GetLeft()) { + m_coords.SetCol(m_blocks[m_block_index].GetRight()); + m_coords.m_row--; coord = m_coords; - return wxSHEET_SELECTIONITER_GET_NEXTCOL; + return (coord == m_blocks[m_block_index].GetLeftTop()) ? wxSHEET_SELECTIONITER_GET_LEFTTOP + : wxSHEET_SELECTIONITER_GET_NEXTROW; + } + // increment the col + m_coords.m_col--; + + coord = m_coords; + return wxSHEET_SELECTIONITER_GET_NEXTCOL; } bool wxSheetSelectionIterator::IsInSelection(int row, int col) const { - int n, count = m_blocks.GetCount(); - for (n=0; nDecRef(); } +#if wxCHECK_VERSION(2, 7, 0) + virtual ~wxSheetVariant() { m_data->DecRef(); } #else - virtual ~wxSheetVariant() { delete m_data; } + virtual ~wxSheetVariant() { delete m_data; } #endif - void Copy(const wxSheetVariant& other); - void Copy(const wxVariant& other); - void Copy(const wxVariantData& other); - void Copy(const wxVariantData* other); + void Copy(const wxSheetVariant &other); + void Copy(const wxVariant &other); + void Copy(const wxVariantData &other); + void Copy(const wxVariantData *other); - wxVariant GetwxVariant() const { return wxVariant(m_data); } - wxVariantData* GetData() const { return m_data; } + wxVariant GetwxVariant() const { return wxVariant(m_data); } + wxVariantData *GetData() const { return m_data; } - wxSheetVariant& operator=(const wxSheetVariant& other) { Copy(other); return *this; } - wxSheetVariant& operator=(const wxVariant& other) { Copy(other); return *this; } - wxSheetVariant& operator=(const wxVariantData& other) { Copy(other); return *this; } + wxSheetVariant &operator=(const wxSheetVariant &other) + { + Copy(other); + return *this; + } + wxSheetVariant &operator=(const wxVariant &other) + { + Copy(other); + return *this; + } + wxSheetVariant &operator=(const wxVariantData &other) + { + Copy(other); + return *this; + } - wxVariantData* m_data; + wxVariantData *m_data; }; - -void wxSheetVariant::Copy(const wxSheetVariant& other) +void wxSheetVariant::Copy(const wxSheetVariant &other) { Copy(other.GetData()); } +void wxSheetVariant::Copy(const wxVariant &other) { Copy(other.GetData()); } +void wxSheetVariant::Copy(const wxVariantData &other) { - Copy(other.GetData()); -} -void wxSheetVariant::Copy(const wxVariant& other) -{ - Copy(other.GetData()); -} -void wxSheetVariant::Copy(const wxVariantData& other) -{ -#if wxCHECK_VERSION(2,7,0) - m_data->DecRef(); - m_data = const_cast(&other); - m_data->IncRef(); +#if wxCHECK_VERSION(2, 7, 0) + m_data->DecRef(); + m_data = const_cast(&other); + m_data->IncRef(); #else - delete m_data; - m_data = (wxVariantData*) other.GetClassInfo()->CreateObject(); - m_data->Copy(*(wxVariantData*)&other); + delete m_data; + m_data = (wxVariantData *)other.GetClassInfo()->CreateObject(); + m_data->Copy(*(wxVariantData *)&other); #endif - } -void wxSheetVariant::Copy(const wxVariantData* other) +void wxSheetVariant::Copy(const wxVariantData *other) { -#if wxCHECK_VERSION(2,7,0) - m_data->DecRef(); +#if wxCHECK_VERSION(2, 7, 0) + m_data->DecRef(); #else - delete m_data; + delete m_data; #endif - if (other) - Copy(*other); - else - m_data = NULL; + if (other) { + Copy(*other); + } + else { + m_data = NULL; + } } - WX_DECLARE_OBJARRAY_WITH_DECL(wxSheetVariant, wxArraySheetVariant, class WXDLLIMPEXP_SHEET); #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxArraySheetVariant) -class WXDLLIMPEXP_SHEET wxSheetRowColVariantContainer -{ +class WXDLLIMPEXP_SHEET wxSheetRowColVariantContainer { public: - wxSheetRowColVariantContainer(bool has_data = false); - + wxSheetRowColVariantContainer(bool has_data = false); - - // Update the number of rows/cols. In numRows/Cols > 0 insert them else - // remove them. - bool UpdateRows( size_t row, int numRows ); - bool UpdateCols( size_t col, int numCols ); + // Update the number of rows/cols. In numRows/Cols > 0 insert them else + // remove them. + bool UpdateRows(size_t row, int numRows); + bool UpdateCols(size_t col, int numCols); protected: - wxArraySheetVariant *m_data; + wxArraySheetVariant *m_data; }; wxSheetRowColVariantContainer::wxSheetRowColVariantContainer(bool has_data) : m_data(NULL) { - if (has_data) - m_data = new wxArraySheetVariant; + if (has_data) { + m_data = new wxArraySheetVariant; + } } -bool wxSheetRowColVariantContainer::UpdateRows( size_t row, int numRows ) -{ - return false; -} -bool wxSheetRowColVariantContainer::UpdateCols( size_t col, int numCols ) -{ - return false; -} +bool wxSheetRowColVariantContainer::UpdateRows(size_t row, int numRows) { return false; } +bool wxSheetRowColVariantContainer::UpdateCols(size_t col, int numCols) { return false; } diff --git a/src/labenski/src/sheetspt.cpp b/src/labenski/src/sheetspt.cpp index a2491bdbb..da9d770ae 100644 --- a/src/labenski/src/sheetspt.cpp +++ b/src/labenski/src/sheetspt.cpp @@ -13,34 +13,36 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #include "wx/sheet/sheetspt.h" #ifndef WX_PRECOMP - #include "wx/dcclient.h" - #include "wx/settings.h" - #include "wx/dcscreen.h" +#include "wx/dcclient.h" +#include "wx/settings.h" +#include "wx/dcscreen.h" #endif #include "wx/renderer.h" -#define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), s, b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_RECT(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), s, b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); // ---------------------------------------------------------------------------- // wxSheetSplitter // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( wxSheetSplitter, wxNavigationEnabled ) +IMPLEMENT_DYNAMIC_CLASS(wxSheetSplitter, wxNavigationEnabled) -BEGIN_EVENT_TABLE( wxSheetSplitter, wxNavigationEnabled ) - EVT_PAINT ( wxSheetSplitter::OnPaint ) - EVT_SIZE ( wxSheetSplitter::OnSize ) - EVT_MOUSE_EVENTS ( wxSheetSplitter::OnMouse ) - EVT_SHEET_SPLIT_BEGIN ( wxID_ANY, wxSheetSplitter::OnSplit ) - EVT_SHEET_VIEW_CHANGED ( wxID_ANY, wxSheetSplitter::OnViewChanged ) +BEGIN_EVENT_TABLE(wxSheetSplitter, wxNavigationEnabled) +EVT_PAINT(wxSheetSplitter::OnPaint) +EVT_SIZE(wxSheetSplitter::OnSize) +EVT_MOUSE_EVENTS(wxSheetSplitter::OnMouse) +EVT_SHEET_SPLIT_BEGIN(wxID_ANY, wxSheetSplitter::OnSplit) +EVT_SHEET_VIEW_CHANGED(wxID_ANY, wxSheetSplitter::OnViewChanged) - // WX_EVENT_TABLE_CONTROL_CONTAINER(wxSheetSplitter) +// WX_EVENT_TABLE_CONTROL_CONTAINER(wxSheetSplitter) END_EVENT_TABLE() // Obsolete - use wxNavigationEnabled<> in modern wxWidgets @@ -52,557 +54,586 @@ END_EVENT_TABLE() void wxSheetSplitter::Init() { - m_container.SetContainerWindow(this); + m_container.SetContainerWindow(this); - m_tlSheet = NULL; - m_trSheet = NULL; - m_blSheet = NULL; - m_brSheet = NULL; + m_tlSheet = NULL; + m_trSheet = NULL; + m_blSheet = NULL; + m_brSheet = NULL; - m_splitMode = wxSHEET_SPLIT_NONE; - m_splitCursor = wxSHEET_SPLIT_NONE; - //m_sash_width = 4; + m_splitMode = wxSHEET_SPLIT_NONE; + m_splitCursor = wxSHEET_SPLIT_NONE; + // m_sash_width = 4; - m_enable_split_vert = true; - m_enable_split_horiz = true; + m_enable_split_vert = true; + m_enable_split_horiz = true; } -bool wxSheetSplitter::Create(wxWindow *parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - long style, const wxString& name) +bool wxSheetSplitter::Create(wxWindow *parent, wxWindowID id, const wxPoint &pos, + const wxSize &size, long style, const wxString &name) { - // allow TABbing from one window to the other - style |= wxTAB_TRAVERSAL; + // allow TABbing from one window to the other + style |= wxTAB_TRAVERSAL; - // we draw our border ourselves to blend the sash with it - style &= ~wxBORDER_MASK; - style |= wxBORDER_NONE; + // we draw our border ourselves to blend the sash with it + style &= ~wxBORDER_MASK; + style |= wxBORDER_NONE; - if (!wxWindow::Create(parent, id, pos, size, style|wxCLIP_CHILDREN, name)) - return false; + if (!wxWindow::Create(parent, id, pos, size, style | wxCLIP_CHILDREN, name)) { + return false; + } - //SetForegroundColour(*wxBLACK); + // SetForegroundColour(*wxBLACK); - // don't erase the splitter background, it's pointless as we overwrite it - SetBackgroundStyle(wxBG_STYLE_CUSTOM); + // don't erase the splitter background, it's pointless as we overwrite it + SetBackgroundStyle(wxBG_STYLE_CUSTOM); - return true; + return true; } wxSheetSplitter::~wxSheetSplitter() { - // stop paint events, probably not necessary anymore, doesn't hurt though - if (m_tlSheet) m_tlSheet->GetSheetRefData()->RemoveSheet(m_tlSheet); - if (m_trSheet) m_trSheet->GetSheetRefData()->RemoveSheet(m_trSheet); - if (m_blSheet) m_blSheet->GetSheetRefData()->RemoveSheet(m_blSheet); - if (m_brSheet) m_brSheet->GetSheetRefData()->RemoveSheet(m_brSheet); + // stop paint events, probably not necessary anymore, doesn't hurt though + if (m_tlSheet) { + m_tlSheet->GetSheetRefData()->RemoveSheet(m_tlSheet); + } + if (m_trSheet) { + m_trSheet->GetSheetRefData()->RemoveSheet(m_trSheet); + } + if (m_blSheet) { + m_blSheet->GetSheetRefData()->RemoveSheet(m_blSheet); + } + if (m_brSheet) { + m_brSheet->GetSheetRefData()->RemoveSheet(m_brSheet); + } } bool wxSheetSplitter::Destroy() { - // stop paint events, probably not necessary anymore, doesn't hurt though - if (m_tlSheet) m_tlSheet->GetSheetRefData()->RemoveSheet(m_tlSheet); - if (m_trSheet) m_trSheet->GetSheetRefData()->RemoveSheet(m_trSheet); - if (m_blSheet) m_blSheet->GetSheetRefData()->RemoveSheet(m_blSheet); - if (m_brSheet) m_brSheet->GetSheetRefData()->RemoveSheet(m_brSheet); + // stop paint events, probably not necessary anymore, doesn't hurt though + if (m_tlSheet) { + m_tlSheet->GetSheetRefData()->RemoveSheet(m_tlSheet); + } + if (m_trSheet) { + m_trSheet->GetSheetRefData()->RemoveSheet(m_trSheet); + } + if (m_blSheet) { + m_blSheet->GetSheetRefData()->RemoveSheet(m_blSheet); + } + if (m_brSheet) { + m_brSheet->GetSheetRefData()->RemoveSheet(m_brSheet); + } + + return wxWindow::Destroy(); +} + +void wxSheetSplitter::Initialize(wxSheet *sheet) +{ + wxCHECK_RET(sheet && (sheet->GetParent() == this), wxT("Invalid sheet or parent")); + m_tlSheet = sheet; + // In >= wx25 a window's min size is set when created with a size, breaks splitting + m_tlSheet->SetSizeHints(-1, -1); + ConfigureWindows(); + LayoutWindows(); +} + +wxSheet *wxSheetSplitter::CreateSheet(wxWindowID id) +{ + wxCHECK_MSG(m_tlSheet, NULL, + wxT("Unable to create wxSheet child in splitter, splitter not initialized yet.")); + wxSheetSplitterEvent event(GetId(), wxEVT_SHEET_SPLIT_CREATE_SHEET); + event.SetEventObject(this); + event.SetExtraLong(id); + GetEventHandler()->ProcessEvent(event); + if (event.GetSheet()) { + wxSheet *sheet = event.GetSheet(); + wxCHECK_MSG(sheet->GetParent() == this, sheet, wxT("Invalid parent for wxSheet in splitter")); + return sheet; + } - return wxWindow::Destroy(); + return m_tlSheet->Clone(id); } -void wxSheetSplitter::Initialize(wxSheet* sheet) +wxSheet *wxSheetSplitter::CreateTopRightSheet(wxWindowID id) { - wxCHECK_RET(sheet && (sheet->GetParent() == this), wxT("Invalid sheet or parent")); - m_tlSheet = sheet; - // In >= wx25 a window's min size is set when created with a size, breaks splitting - m_tlSheet->SetSizeHints(-1, -1); - ConfigureWindows(); - LayoutWindows(); + wxSheet *sheet = CreateSheet(id); + wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); + sheet->RefSheet(m_tlSheet); + sheet->GetRowLabelWindow()->Show(false); + sheet->GetCornerLabelWindow()->Show(false); + sheet->EnableSplitHorizontally(false); + sheet->SetGridOrigin(m_tlSheet->GetGridOrigin()); + return sheet; } - -wxSheet* wxSheetSplitter::CreateSheet(wxWindowID id) +wxSheet *wxSheetSplitter::CreateBottomLeftSheet(wxWindowID id) { - wxCHECK_MSG(m_tlSheet, NULL, wxT("Unable to create wxSheet child in splitter, splitter not initialized yet.")); - wxSheetSplitterEvent event(GetId(), wxEVT_SHEET_SPLIT_CREATE_SHEET); - event.SetEventObject(this); - event.SetExtraLong(id); - GetEventHandler()->ProcessEvent(event); - if (event.GetSheet()) - { - wxSheet *sheet = event.GetSheet(); - wxCHECK_MSG(sheet->GetParent() == this, sheet, wxT("Invalid parent for wxSheet in splitter")); - return sheet; - } - - return m_tlSheet->Clone(id); + wxSheet *sheet = CreateSheet(id); + wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); + sheet->RefSheet(m_tlSheet); + sheet->GetColLabelWindow()->Show(false); + sheet->GetCornerLabelWindow()->Show(false); + sheet->EnableSplitVertically(false); + sheet->SetGridOrigin(m_tlSheet->GetGridOrigin()); + return sheet; } - -wxSheet* wxSheetSplitter::CreateTopRightSheet(wxWindowID id) -{ - wxSheet *sheet = CreateSheet(id); - wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); - sheet->RefSheet(m_tlSheet); - sheet->GetRowLabelWindow()->Show(false); - sheet->GetCornerLabelWindow()->Show(false); - sheet->EnableSplitHorizontally(false); - sheet->SetGridOrigin(m_tlSheet->GetGridOrigin()); - return sheet; -} -wxSheet* wxSheetSplitter::CreateBottomLeftSheet(wxWindowID id) +wxSheet *wxSheetSplitter::CreateBottomRightSheet(wxWindowID id) { - wxSheet *sheet = CreateSheet(id); - wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); - sheet->RefSheet(m_tlSheet); - sheet->GetColLabelWindow()->Show(false); - sheet->GetCornerLabelWindow()->Show(false); - sheet->EnableSplitVertically(false); - sheet->SetGridOrigin(m_tlSheet->GetGridOrigin()); - return sheet; -} -wxSheet* wxSheetSplitter::CreateBottomRightSheet(wxWindowID id) -{ - wxSheet *sheet = CreateSheet(id); - wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); - sheet->RefSheet(m_tlSheet); - sheet->GetRowLabelWindow()->Show(false); - sheet->GetColLabelWindow()->Show(false); - sheet->GetCornerLabelWindow()->Show(false); - sheet->EnableSplitVertically(false); - sheet->EnableSplitHorizontally(false); - sheet->SetGridOrigin(m_trSheet->GetGridOrigin()); - return sheet; + wxSheet *sheet = CreateSheet(id); + wxCHECK_MSG(sheet, NULL, wxT("Unable to create wxSheet child in splitter")); + sheet->RefSheet(m_tlSheet); + sheet->GetRowLabelWindow()->Show(false); + sheet->GetColLabelWindow()->Show(false); + sheet->GetCornerLabelWindow()->Show(false); + sheet->EnableSplitVertically(false); + sheet->EnableSplitHorizontally(false); + sheet->SetGridOrigin(m_trSheet->GetGridOrigin()); + return sheet; } void wxSheetSplitter::SplitVertically(int y_pos, bool sendEvt) { - wxCHECK_RET(m_tlSheet, wxT("Unable to split vertically, not initialized yet.")); - wxCHECK_RET(!IsSplitVertically(), wxT("Already vertically split")); - wxCHECK_RET((y_pos >= m_minSize.y) || - (y_pos < GetClientSize().GetHeight() - m_minSize.y), - wxT("Invalid vertical split position")); + wxCHECK_RET(m_tlSheet, wxT("Unable to split vertically, not initialized yet.")); + wxCHECK_RET(!IsSplitVertically(), wxT("Already vertically split")); + wxCHECK_RET((y_pos >= m_minSize.y) || (y_pos < GetClientSize().GetHeight() - m_minSize.y), + wxT("Invalid vertical split position")); - m_blSheet = CreateBottomLeftSheet(); - wxCHECK_RET(m_blSheet, wxT("Unable to create wxSheet child in splitter")); + m_blSheet = CreateBottomLeftSheet(); + wxCHECK_RET(m_blSheet, wxT("Unable to create wxSheet child in splitter")); - if (m_trSheet && !m_brSheet) - { - m_brSheet = CreateBottomRightSheet(); - wxCHECK_RET(m_brSheet, wxT("Unable to create wxSheet child in splitter")); - } + if (m_trSheet && !m_brSheet) { + m_brSheet = CreateBottomRightSheet(); + wxCHECK_RET(m_brSheet, wxT("Unable to create wxSheet child in splitter")); + } - m_splitPos.y = y_pos; - ConfigureWindows(); - LayoutWindows(); - Refresh(false); + m_splitPos.y = y_pos; + ConfigureWindows(); + LayoutWindows(); + Refresh(false); - if (sendEvt) - SendEvent( wxEVT_SHEET_SPLIT_CHANGED, true ); + if (sendEvt) { + SendEvent(wxEVT_SHEET_SPLIT_CHANGED, true); + } } void wxSheetSplitter::SplitHorizontally(int x_pos, bool sendEvt) { - wxCHECK_RET(m_tlSheet, wxT("Unable to split horizontally, not initialized yet.")); - wxCHECK_RET(!IsSplitHorizontally(), wxT("Already horizontally split")); - wxCHECK_RET((x_pos >= m_minSize.x) || - (x_pos < GetClientSize().GetWidth() - m_minSize.x), - wxT("Invalid horizontal split position")); + wxCHECK_RET(m_tlSheet, wxT("Unable to split horizontally, not initialized yet.")); + wxCHECK_RET(!IsSplitHorizontally(), wxT("Already horizontally split")); + wxCHECK_RET((x_pos >= m_minSize.x) || (x_pos < GetClientSize().GetWidth() - m_minSize.x), + wxT("Invalid horizontal split position")); - m_trSheet = CreateTopRightSheet(); - wxCHECK_RET(m_trSheet, wxT("Unable to create wxSheet child in splitter")); + m_trSheet = CreateTopRightSheet(); + wxCHECK_RET(m_trSheet, wxT("Unable to create wxSheet child in splitter")); - if (m_blSheet && !m_brSheet) - { - m_brSheet = CreateBottomRightSheet(); - wxCHECK_RET(m_brSheet, wxT("Unable to create wxSheet child in splitter")); - } + if (m_blSheet && !m_brSheet) { + m_brSheet = CreateBottomRightSheet(); + wxCHECK_RET(m_brSheet, wxT("Unable to create wxSheet child in splitter")); + } - m_splitPos.x = x_pos; - ConfigureWindows(); - LayoutWindows(); - Refresh(false); + m_splitPos.x = x_pos; + ConfigureWindows(); + LayoutWindows(); + Refresh(false); - if (sendEvt) - SendEvent( wxEVT_SHEET_SPLIT_CHANGED, false ); + if (sendEvt) { + SendEvent(wxEVT_SHEET_SPLIT_CHANGED, false); + } } void wxSheetSplitter::UnsplitVertically(bool remove_bottom, bool sendEvt) { - wxCHECK_RET(IsSplitVertically(), wxT("Not vertically split")); + wxCHECK_RET(IsSplitVertically(), wxT("Not vertically split")); - wxPoint blOrigin = m_blSheet->GetGridOrigin(); - m_blSheet->Show(false); - m_blSheet->Destroy(); - m_blSheet = NULL; + wxPoint blOrigin = m_blSheet->GetGridOrigin(); + m_blSheet->Show(false); + m_blSheet->Destroy(); + m_blSheet = NULL; - if (m_brSheet) - { - wxPoint brOrigin = m_brSheet->GetGridOrigin(); - m_brSheet->Show(false); - m_brSheet->Destroy(); - m_brSheet = NULL; + if (m_brSheet) { + wxPoint brOrigin = m_brSheet->GetGridOrigin(); + m_brSheet->Show(false); + m_brSheet->Destroy(); + m_brSheet = NULL; - if (!remove_bottom) - m_trSheet->SetGridOrigin(brOrigin); + if (!remove_bottom) { + m_trSheet->SetGridOrigin(brOrigin); } + } - if (!remove_bottom) - m_tlSheet->SetGridOrigin(blOrigin); + if (!remove_bottom) { + m_tlSheet->SetGridOrigin(blOrigin); + } - m_splitPos.y = 0; - ConfigureWindows(); - LayoutWindows(); - Refresh(false); + m_splitPos.y = 0; + ConfigureWindows(); + LayoutWindows(); + Refresh(false); - if (sendEvt) - SendEvent( wxEVT_SHEET_SPLIT_UNSPLIT, true ); + if (sendEvt) { + SendEvent(wxEVT_SHEET_SPLIT_UNSPLIT, true); + } } void wxSheetSplitter::UnsplitHorizontally(bool remove_right, bool sendEvt) { - wxCHECK_RET(IsSplitHorizontally(), wxT("Not horizontally split")); + wxCHECK_RET(IsSplitHorizontally(), wxT("Not horizontally split")); - wxPoint trOrigin = m_trSheet->GetGridOrigin(); - m_trSheet->Show(false); - m_trSheet->Destroy(); - m_trSheet = NULL; + wxPoint trOrigin = m_trSheet->GetGridOrigin(); + m_trSheet->Show(false); + m_trSheet->Destroy(); + m_trSheet = NULL; - if (m_brSheet) - { - wxPoint brOrigin = m_brSheet->GetGridOrigin(); - m_brSheet->Show(false); - m_brSheet->Destroy(); - m_brSheet = NULL; + if (m_brSheet) { + wxPoint brOrigin = m_brSheet->GetGridOrigin(); + m_brSheet->Show(false); + m_brSheet->Destroy(); + m_brSheet = NULL; - if (!remove_right) - m_blSheet->SetGridOrigin(brOrigin); + if (!remove_right) { + m_blSheet->SetGridOrigin(brOrigin); } + } - if (!remove_right) - m_tlSheet->SetGridOrigin(trOrigin); + if (!remove_right) { + m_tlSheet->SetGridOrigin(trOrigin); + } - m_splitPos.x = 0; - ConfigureWindows(); - LayoutWindows(); - Refresh(false); + m_splitPos.x = 0; + ConfigureWindows(); + LayoutWindows(); + Refresh(false); - if (sendEvt) - SendEvent( wxEVT_SHEET_SPLIT_UNSPLIT, false ); + if (sendEvt) { + SendEvent(wxEVT_SHEET_SPLIT_UNSPLIT, false); + } } void wxSheetSplitter::SetVerticalSplitPosition(int y_pos, bool sendEvt) { - wxCHECK_RET(m_tlSheet, wxT("wxSheetSplitter not initialized")); - y_pos = GetAdjustedVerticalSashPosition(y_pos); - wxSize clientSize(GetClientSize()); - int border_size = GetBorderSize(); + wxCHECK_RET(m_tlSheet, wxT("wxSheetSplitter not initialized")); + y_pos = GetAdjustedVerticalSashPosition(y_pos); + wxSize clientSize(GetClientSize()); + int border_size = GetBorderSize(); - if ((y_pos <= border_size) || (y_pos >= clientSize.y-border_size)) - { - if (IsSplitVertically()) - UnsplitVertically(!(y_pos <= border_size), sendEvt); - } - else if (!IsSplitVertically()) - { - SplitVertically(y_pos, sendEvt); + if ((y_pos <= border_size) || (y_pos >= clientSize.y - border_size)) { + if (IsSplitVertically()) { + UnsplitVertically(!(y_pos <= border_size), sendEvt); } - else if (m_splitPos.y != y_pos) - { - m_splitPos.y = y_pos; - LayoutWindows(); - Refresh(false); + } + else if (!IsSplitVertically()) { + SplitVertically(y_pos, sendEvt); + } + else if (m_splitPos.y != y_pos) { + m_splitPos.y = y_pos; + LayoutWindows(); + Refresh(false); - if (sendEvt) - SendEvent( wxEVT_SHEET_SPLIT_CHANGED, true ); + if (sendEvt) { + SendEvent(wxEVT_SHEET_SPLIT_CHANGED, true); } + } } void wxSheetSplitter::SetHorizontalSplitPosition(int x_pos, bool sendEvt) { - wxCHECK_RET(m_tlSheet, wxT("wxSheetSplitter not horizontally split")); - x_pos = GetAdjustedHorizontalSashPosition(x_pos); - wxSize clientSize(GetClientSize()); - int border_size = GetBorderSize(); + wxCHECK_RET(m_tlSheet, wxT("wxSheetSplitter not horizontally split")); + x_pos = GetAdjustedHorizontalSashPosition(x_pos); + wxSize clientSize(GetClientSize()); + int border_size = GetBorderSize(); - if ((x_pos <= border_size) || (x_pos >= clientSize.x-border_size)) - { - if (IsSplitHorizontally()) - UnsplitHorizontally(!(x_pos <= border_size), sendEvt); - } - else if (!IsSplitHorizontally()) - { - SplitHorizontally(x_pos, sendEvt); + if ((x_pos <= border_size) || (x_pos >= clientSize.x - border_size)) { + if (IsSplitHorizontally()) { + UnsplitHorizontally(!(x_pos <= border_size), sendEvt); } - else if (m_splitPos.x != x_pos) - { - m_splitPos.x = x_pos; - LayoutWindows(); - Refresh(false); + } + else if (!IsSplitHorizontally()) { + SplitHorizontally(x_pos, sendEvt); + } + else if (m_splitPos.x != x_pos) { + m_splitPos.x = x_pos; + LayoutWindows(); + Refresh(false); - if (sendEvt) - SendEvent( wxEVT_SHEET_SPLIT_CHANGED, false ); + if (sendEvt) { + SendEvent(wxEVT_SHEET_SPLIT_CHANGED, false); } + } } int wxSheetSplitter::GetAdjustedVerticalSashPosition(int pos) const { - int width = GetClientSize().GetWidth(); + int width = GetClientSize().GetWidth(); - if (width < m_minSize.x) - pos = width/2; - else if (pos <= m_minSize.x) - pos = m_minSize.x; - else if (pos >= width - m_minSize.x) - pos = width - m_minSize.x; + if (width < m_minSize.x) { + pos = width / 2; + } + else if (pos <= m_minSize.x) { + pos = m_minSize.x; + } + else if (pos >= width - m_minSize.x) { + pos = width - m_minSize.x; + } - return pos; + return pos; } int wxSheetSplitter::GetAdjustedHorizontalSashPosition(int pos) const { - int height = GetClientSize().GetHeight(); + int height = GetClientSize().GetHeight(); - if (height < m_minSize.y) - pos = height/2; - else if (pos <= m_minSize.y) - return m_minSize.y; - else if (pos >= height - m_minSize.y) - return height - m_minSize.y; + if (height < m_minSize.y) { + pos = height / 2; + } + else if (pos <= m_minSize.y) { + return m_minSize.y; + } + else if (pos >= height - m_minSize.y) { + return height - m_minSize.y; + } - return pos; + return pos; } void wxSheetSplitter::ConfigureWindows() { - if (!m_tlSheet) - return; + if (!m_tlSheet) { + return; + } - if (m_tlSheet) - { - int sb_mode = (m_trSheet ? wxSheet::SB_VERT_NEVER : wxSheet::SB_AS_NEEDED) | - (m_blSheet ? wxSheet::SB_HORIZ_NEVER : wxSheet::SB_AS_NEEDED); + if (m_tlSheet) { + int sb_mode = (m_trSheet ? wxSheet::SB_VERT_NEVER : wxSheet::SB_AS_NEEDED) | + (m_blSheet ? wxSheet::SB_HORIZ_NEVER : wxSheet::SB_AS_NEEDED); - m_tlSheet->SetScrollBarMode(sb_mode); - m_tlSheet->EnableSplitVertically(!m_blSheet && m_enable_split_vert); - m_tlSheet->EnableSplitHorizontally(!m_trSheet && m_enable_split_horiz); - } - if (m_trSheet) - { - int sb_mode = (m_brSheet ? wxSheet::SB_HORIZ_NEVER : wxSheet::SB_AS_NEEDED); + m_tlSheet->SetScrollBarMode(sb_mode); + m_tlSheet->EnableSplitVertically(!m_blSheet && m_enable_split_vert); + m_tlSheet->EnableSplitHorizontally(!m_trSheet && m_enable_split_horiz); + } + if (m_trSheet) { + int sb_mode = (m_brSheet ? wxSheet::SB_HORIZ_NEVER : wxSheet::SB_AS_NEEDED); - m_trSheet->SetHorizontalScrollBarMode(sb_mode); - m_trSheet->EnableSplitVertically(!m_brSheet && m_enable_split_vert); - } - if (m_blSheet) - { - int sb_mode = (m_brSheet ? wxSheet::SB_VERT_NEVER : wxSheet::SB_AS_NEEDED); + m_trSheet->SetHorizontalScrollBarMode(sb_mode); + m_trSheet->EnableSplitVertically(!m_brSheet && m_enable_split_vert); + } + if (m_blSheet) { + int sb_mode = (m_brSheet ? wxSheet::SB_VERT_NEVER : wxSheet::SB_AS_NEEDED); - m_blSheet->SetVerticalScrollBarMode(sb_mode); - m_blSheet->EnableSplitHorizontally(!m_brSheet && m_enable_split_horiz); - } + m_blSheet->SetVerticalScrollBarMode(sb_mode); + m_blSheet->EnableSplitHorizontally(!m_brSheet && m_enable_split_horiz); + } } void wxSheetSplitter::LayoutWindows() { - if (!m_tlSheet) - return; + if (!m_tlSheet) { + return; + } - wxSize clientSize(GetClientSize()); + wxSize clientSize(GetClientSize()); - int x = m_splitPos.x; - int y = m_splitPos.y; - int sash_size = GetSashSize(); - int border_size = GetBorderSize(); + int x = m_splitPos.x; + int y = m_splitPos.y; + int sash_size = GetSashSize(); + int border_size = GetBorderSize(); + + if (!m_trSheet) { + x = clientSize.x - 2 * border_size; + } + /* + else if (m_trSheet && (x > clientSize.x - m_minSize.x)) + { + // fix sash position to stay within visible part of window + x = clientSize.x - m_minSize.x; + if (x < sash_size + border_size + 2) + x = clientSize.x/2; - if (!m_trSheet) - x = clientSize.x - 2*border_size; -/* - else if (m_trSheet && (x > clientSize.x - m_minSize.x)) - { - // fix sash position to stay within visible part of window - x = clientSize.x - m_minSize.x; - if (x < sash_size + border_size + 2) - x = clientSize.x/2; + m_splitPos.x = x; + } + */ - m_splitPos.x = x; - } -*/ + if (!m_blSheet) { + y = clientSize.y - 2 * border_size; + } + /* + else if (m_blSheet && (y > clientSize.y - m_minSize.y)) + { + // fix sash position to stay within visible part of window + y = clientSize.y - m_minSize.y; + if (y < sash_size + border_size + 2) + y = clientSize.y/2; - if (!m_blSheet) - y = clientSize.y - 2*border_size; -/* - else if (m_blSheet && (y > clientSize.y - m_minSize.y)) - { - // fix sash position to stay within visible part of window - y = clientSize.y - m_minSize.y; - if (y < sash_size + border_size + 2) - y = clientSize.y/2; - - m_splitPos.y = y; - } -*/ + m_splitPos.y = y; + } + */ - wxRect rect = wxRect(border_size, border_size, x, y); - if (m_tlSheet->GetRect() != rect) - m_tlSheet->SetSize(rect); + wxRect rect = wxRect(border_size, border_size, x, y); + if (m_tlSheet->GetRect() != rect) { + m_tlSheet->SetSize(rect); + } - if (m_trSheet) - { - rect = wxRect(x+sash_size, border_size, clientSize.x-x-sash_size-border_size, y); - if (m_trSheet->GetRect() != rect) - m_trSheet->SetSize(rect); + if (m_trSheet) { + rect = wxRect(x + sash_size, border_size, clientSize.x - x - sash_size - border_size, y); + if (m_trSheet->GetRect() != rect) { + m_trSheet->SetSize(rect); } - if (m_blSheet) - { - rect = wxRect(border_size, y+sash_size, x, clientSize.y-y-sash_size-border_size); - if (m_blSheet->GetRect() != rect) - m_blSheet->SetSize(rect); + } + if (m_blSheet) { + rect = wxRect(border_size, y + sash_size, x, clientSize.y - y - sash_size - border_size); + if (m_blSheet->GetRect() != rect) { + m_blSheet->SetSize(rect); } - if (m_brSheet) - { - rect = wxRect(x+sash_size, y+sash_size, clientSize.x-x-sash_size-border_size, clientSize.y-y-sash_size-border_size); - if (m_brSheet->GetRect() != rect) - m_brSheet->SetSize(rect); + } + if (m_brSheet) { + rect = wxRect(x + sash_size, y + sash_size, clientSize.x - x - sash_size - border_size, + clientSize.y - y - sash_size - border_size); + if (m_brSheet->GetRect() != rect) { + m_brSheet->SetSize(rect); } + } } -void wxSheetSplitter::OnSize( wxSizeEvent& event ) +void wxSheetSplitter::OnSize(wxSizeEvent &event) { - m_splitPos.x = GetAdjustedVerticalSashPosition(m_splitPos.x); - m_splitPos.y = GetAdjustedHorizontalSashPosition(m_splitPos.y); - LayoutWindows(); + m_splitPos.x = GetAdjustedVerticalSashPosition(m_splitPos.x); + m_splitPos.y = GetAdjustedHorizontalSashPosition(m_splitPos.y); + LayoutWindows(); - event.Skip(); + event.Skip(); } -void wxSheetSplitter::OnViewChanged(wxSheetEvent& event) +void wxSheetSplitter::OnViewChanged(wxSheetEvent &event) { - wxSheet *sheet = (wxSheet*)event.GetEventObject(); - wxPoint origin = sheet->GetGridOrigin(); + wxSheet *sheet = (wxSheet *)event.GetEventObject(); + wxPoint origin = sheet->GetGridOrigin(); - if (sheet == m_tlSheet) - { - if (m_trSheet) - m_trSheet->SetGridOrigin(-1, origin.y); - if (m_blSheet) - m_blSheet->SetGridOrigin(origin.x, -1); + if (sheet == m_tlSheet) { + if (m_trSheet) { + m_trSheet->SetGridOrigin(-1, origin.y); } - else if (sheet == m_trSheet) - { - if (m_tlSheet) - m_tlSheet->SetGridOrigin(-1, origin.y); - if (m_brSheet) - m_brSheet->SetGridOrigin(origin.x, -1); + if (m_blSheet) { + m_blSheet->SetGridOrigin(origin.x, -1); } - else if (sheet == m_blSheet) - { - if (m_brSheet) - m_brSheet->SetGridOrigin(-1, origin.y); - if (m_tlSheet) - m_tlSheet->SetGridOrigin(origin.x, -1); + } + else if (sheet == m_trSheet) { + if (m_tlSheet) { + m_tlSheet->SetGridOrigin(-1, origin.y); } - else if (sheet == m_brSheet) - { - if (m_blSheet) - m_blSheet->SetGridOrigin(-1, origin.y); - if (m_trSheet) - m_trSheet->SetGridOrigin(origin.x, -1); + if (m_brSheet) { + m_brSheet->SetGridOrigin(origin.x, -1); + } + } + else if (sheet == m_blSheet) { + if (m_brSheet) { + m_brSheet->SetGridOrigin(-1, origin.y); + } + if (m_tlSheet) { + m_tlSheet->SetGridOrigin(origin.x, -1); + } + } + else if (sheet == m_brSheet) { + if (m_blSheet) { + m_blSheet->SetGridOrigin(-1, origin.y); + } + if (m_trSheet) { + m_trSheet->SetGridOrigin(origin.x, -1); } + } } -void wxSheetSplitter::OnSplit(wxSheetSplitterEvent& event) +void wxSheetSplitter::OnSplit(wxSheetSplitterEvent &event) { - // pass event to parent to see if they want to veto it first - GetParent()->GetEventHandler()->ProcessEvent(event); - if (!event.IsAllowed()) - return; + // pass event to parent to see if they want to veto it first + GetParent()->GetEventHandler()->ProcessEvent(event); + if (!event.IsAllowed()) { + return; + } - if (!HasCapture()) - CaptureMouse(); + if (!HasCapture()) { + CaptureMouse(); + } - m_splitMode = event.IsVerticalSplit() ? wxSHEET_SPLIT_VERTICAL : wxSHEET_SPLIT_HORIZONTAL; - SetMouseCursor(m_splitMode); - // out of bounds, don't draw initial tracker - m_mousePos = wxPoint(-10, -10); + m_splitMode = event.IsVerticalSplit() ? wxSHEET_SPLIT_VERTICAL : wxSHEET_SPLIT_HORIZONTAL; + SetMouseCursor(m_splitMode); + // out of bounds, don't draw initial tracker + m_mousePos = wxPoint(-10, -10); } -void wxSheetSplitter::OnMouse(wxMouseEvent& event) +void wxSheetSplitter::OnMouse(wxMouseEvent &event) { - wxPoint mousePos(event.GetPosition()); + wxPoint mousePos(event.GetPosition()); - if (event.LeftDown()) - { - m_splitMode = SashHitTest(mousePos); - SetMouseCursor(m_splitMode); - if ((m_splitMode != wxSHEET_SPLIT_NONE) && !HasCapture()) - CaptureMouse(); - } - else if (event.Moving()) - { - SetMouseCursor(SashHitTest(mousePos)); + if (event.LeftDown()) { + m_splitMode = SashHitTest(mousePos); + SetMouseCursor(m_splitMode); + if ((m_splitMode != wxSHEET_SPLIT_NONE) && !HasCapture()) { + CaptureMouse(); } - else if (event.Dragging() && HasCapture()) - { - DrawSashTracker(m_mousePos.x, m_mousePos.y); - - bool vert = (m_splitMode == wxSHEET_SPLIT_VERTICAL); - - wxSheetSplitterEvent sEvent(GetId(), wxEVT_SHEET_SPLIT_CHANGING); - sEvent.SetEventObject(this); - sEvent.m_vert_split = vert; - sEvent.SetSashPosition(vert ? m_mousePos.y : m_mousePos.x); - if (DoSendEvent(sEvent)) - { - m_mousePos = mousePos; - if (vert) - m_mousePos.x = sEvent.GetSashPosition(); - else - m_mousePos.y = sEvent.GetSashPosition(); - } - - DrawSashTracker(m_mousePos.x, m_mousePos.y); + } + else if (event.Moving()) { + SetMouseCursor(SashHitTest(mousePos)); + } + else if (event.Dragging() && HasCapture()) { + DrawSashTracker(m_mousePos.x, m_mousePos.y); + + bool vert = (m_splitMode == wxSHEET_SPLIT_VERTICAL); + + wxSheetSplitterEvent sEvent(GetId(), wxEVT_SHEET_SPLIT_CHANGING); + sEvent.SetEventObject(this); + sEvent.m_vert_split = vert; + sEvent.SetSashPosition(vert ? m_mousePos.y : m_mousePos.x); + if (DoSendEvent(sEvent)) { + m_mousePos = mousePos; + if (vert) { + m_mousePos.x = sEvent.GetSashPosition(); + } + else { + m_mousePos.y = sEvent.GetSashPosition(); + } } - else if (event.LeftUp() && HasCapture()) - { - ReleaseMouse(); - DrawSashTracker(m_mousePos.x, m_mousePos.y); - m_mousePos = mousePos; + DrawSashTracker(m_mousePos.x, m_mousePos.y); + } + else if (event.LeftUp() && HasCapture()) { + ReleaseMouse(); - if (m_splitMode == wxSHEET_SPLIT_VERTICAL) - SetVerticalSplitPosition(m_mousePos.y, true); - else if (m_splitMode == wxSHEET_SPLIT_HORIZONTAL) - SetHorizontalSplitPosition(m_mousePos.x, true); + DrawSashTracker(m_mousePos.x, m_mousePos.y); + m_mousePos = mousePos; - m_mousePos = wxPoint(-10, -10); - m_splitMode = wxSHEET_SPLIT_NONE; + if (m_splitMode == wxSHEET_SPLIT_VERTICAL) { + SetVerticalSplitPosition(m_mousePos.y, true); } - else if (event.LeftDClick()) - { - m_splitMode = SashHitTest(mousePos); - - if (SendEvent(wxEVT_SHEET_SPLIT_DOUBLECLICKED, - m_splitMode == wxSHEET_SPLIT_VERTICAL)) - { - if ((m_minSize.y == 0) && (m_splitMode == wxSHEET_SPLIT_VERTICAL)) - UnsplitVertically(true, true); - else if ((m_minSize.x == 0) && (m_splitMode == wxSHEET_SPLIT_HORIZONTAL)) - UnsplitHorizontally(true, true); - } + else if (m_splitMode == wxSHEET_SPLIT_HORIZONTAL) { + SetHorizontalSplitPosition(m_mousePos.x, true); } - else if (event.Leaving() || event.Entering()) - { - SetMouseCursor(wxSHEET_SPLIT_NONE); + + m_mousePos = wxPoint(-10, -10); + m_splitMode = wxSHEET_SPLIT_NONE; + } + else if (event.LeftDClick()) { + m_splitMode = SashHitTest(mousePos); + + if (SendEvent(wxEVT_SHEET_SPLIT_DOUBLECLICKED, m_splitMode == wxSHEET_SPLIT_VERTICAL)) { + if ((m_minSize.y == 0) && (m_splitMode == wxSHEET_SPLIT_VERTICAL)) { + UnsplitVertically(true, true); + } + else if ((m_minSize.x == 0) && (m_splitMode == wxSHEET_SPLIT_HORIZONTAL)) { + UnsplitHorizontally(true, true); + } } + } + else if (event.Leaving() || event.Entering()) { + SetMouseCursor(wxSHEET_SPLIT_NONE); + } } -void wxSheetSplitter::OnPaint( wxPaintEvent& WXUNUSED(event) ) +void wxSheetSplitter::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc(this); - DrawSash(dc); + wxPaintDC dc(this); + DrawSash(dc); } void wxSheetSplitter::DrawSash(wxDC &dc) { - wxSize clientSize(GetClientSize()); - bool draw_horiz = (m_splitPos.x > 0) && (m_splitPos.x < clientSize.x); - bool draw_vert = (m_splitPos.y > 0) && (m_splitPos.y < clientSize.y); + wxSize clientSize(GetClientSize()); + bool draw_horiz = (m_splitPos.x > 0) && (m_splitPos.x < clientSize.x); + bool draw_vert = (m_splitPos.y > 0) && (m_splitPos.y < clientSize.y); #if 0 // old method where we just draw a black line if (draw_horiz || draw_vert) @@ -616,138 +647,145 @@ void wxSheetSplitter::DrawSash(wxDC &dc) dc.DrawLine(0, m_splitPos.y + sash_size/2, clientSize.x, m_splitPos.y + sash_size/2); } #else - wxRendererNative& ren = wxRendererNative::Get(); - - if (HasFlag(wxSP_3DBORDER)) - ren.DrawSplitterBorder(this, dc, GetClientRect()); - - // don't draw sash if we're configured to not show it - if ( HasFlag(wxSP_NOSASH) ) - return; - - if (draw_horiz) - ren.DrawSplitterSash(this, dc, clientSize, m_splitPos.x, wxVERTICAL, - (m_splitCursor == wxSHEET_SPLIT_HORIZONTAL) ? (int)wxCONTROL_CURRENT : 0); - if (draw_vert) - ren.DrawSplitterSash(this, dc, clientSize, m_splitPos.y, wxHORIZONTAL, - (m_splitCursor == wxSHEET_SPLIT_VERTICAL) ? (int)wxCONTROL_CURRENT : 0); + wxRendererNative &ren = wxRendererNative::Get(); + + if (HasFlag(wxSP_3DBORDER)) { + ren.DrawSplitterBorder(this, dc, GetClientRect()); + } + + // don't draw sash if we're configured to not show it + if (HasFlag(wxSP_NOSASH)) { + return; + } + + if (draw_horiz) { + ren.DrawSplitterSash(this, dc, clientSize, m_splitPos.x, wxVERTICAL, + (m_splitCursor == wxSHEET_SPLIT_HORIZONTAL) ? (int)wxCONTROL_CURRENT : 0); + } + if (draw_vert) { + ren.DrawSplitterSash(this, dc, clientSize, m_splitPos.y, wxHORIZONTAL, + (m_splitCursor == wxSHEET_SPLIT_VERTICAL) ? (int)wxCONTROL_CURRENT : 0); + } #endif } void wxSheetSplitter::DrawSashTracker(int x, int y) { - if ((x < 0) && (y < 0)) - return; + if ((x < 0) && (y < 0)) { + return; + } - int w, h; - GetClientSize(&w, &h); + int w, h; + GetClientSize(&w, &h); - int x1, y1; - int x2, y2; + int x1, y1; + int x2, y2; - int sash_size = GetSashSize(); - int border_size = GetBorderSize(); + int sash_size = GetSashSize(); + int border_size = GetBorderSize(); - if ( m_splitMode == wxSHEET_SPLIT_HORIZONTAL ) - { - x1 = x2 = ((x > w) ? w : ((x < 0) ? 0 : x)) + sash_size/2; - y1 = border_size; - y2 = h-border_size; - } - else - { - x1 = border_size; - x2 = w-border_size; - y1 = y2 = ((y > h) ? h : ((y < 0) ? 0 : y)) + sash_size/2; - } + if (m_splitMode == wxSHEET_SPLIT_HORIZONTAL) { + x1 = x2 = ((x > w) ? w : ((x < 0) ? 0 : x)) + sash_size / 2; + y1 = border_size; + y2 = h - border_size; + } + else { + x1 = border_size; + x2 = w - border_size; + y1 = y2 = ((y > h) ? h : ((y < 0) ? 0 : y)) + sash_size / 2; + } - ClientToScreen(&x1, &y1); - ClientToScreen(&x2, &y2); + ClientToScreen(&x1, &y1); + ClientToScreen(&x2, &y2); - wxScreenDC screenDC; - screenDC.SetLogicalFunction(wxINVERT); - screenDC.SetPen(wxPen(GetForegroundColour(), sash_size, wxPENSTYLE_SOLID)); - screenDC.SetBrush(*wxTRANSPARENT_BRUSH); - screenDC.DrawLine(x1, y1, x2, y2); - screenDC.SetLogicalFunction(wxCOPY); + wxScreenDC screenDC; + screenDC.SetLogicalFunction(wxINVERT); + screenDC.SetPen(wxPen(GetForegroundColour(), sash_size, wxPENSTYLE_SOLID)); + screenDC.SetBrush(*wxTRANSPARENT_BRUSH); + screenDC.DrawLine(x1, y1, x2, y2); + screenDC.SetLogicalFunction(wxCOPY); } int wxSheetSplitter::GetSashSize() const { - return wxRendererNative::Get().GetSplitterParams(this).widthSash; + return wxRendererNative::Get().GetSplitterParams(this).widthSash; } int wxSheetSplitter::GetBorderSize() const { - return wxRendererNative::Get().GetSplitterParams(this).border; + return wxRendererNative::Get().GetSplitterParams(this).border; } -int wxSheetSplitter::SashHitTest(const wxPoint& pt) const +int wxSheetSplitter::SashHitTest(const wxPoint &pt) const { - if ((m_splitPos.x <= 0) && (m_splitPos.y <= 0)) - return wxSHEET_SPLIT_NONE; + if ((m_splitPos.x <= 0) && (m_splitPos.y <= 0)) { + return wxSHEET_SPLIT_NONE; + } - wxSize clientSize = GetClientSize(); - int sash_size = GetSashSize(); - int border_size = GetBorderSize(); + wxSize clientSize = GetClientSize(); + int sash_size = GetSashSize(); + int border_size = GetBorderSize(); - if (m_trSheet && (m_splitPos.x > 0)) - { - wxRect rect(m_splitPos.x, border_size, sash_size, clientSize.y-2*border_size); -#if wxCHECK_VERSION(2,7,0) - if (rect.Contains(pt)) + if (m_trSheet && (m_splitPos.x > 0)) { + wxRect rect(m_splitPos.x, border_size, sash_size, clientSize.y - 2 * border_size); +#if wxCHECK_VERSION(2, 7, 0) + if (rect.Contains(pt)) #else - if (rect.Inside(pt)) + if (rect.Inside(pt)) #endif - return wxSHEET_SPLIT_HORIZONTAL; - } + return wxSHEET_SPLIT_HORIZONTAL; + } - if (m_blSheet && (m_splitPos.y > 0)) - { - wxRect rect(border_size, m_splitPos.y, clientSize.x-2*border_size, sash_size); -#if wxCHECK_VERSION(2,7,0) - if (rect.Contains(pt)) + if (m_blSheet && (m_splitPos.y > 0)) { + wxRect rect(border_size, m_splitPos.y, clientSize.x - 2 * border_size, sash_size); +#if wxCHECK_VERSION(2, 7, 0) + if (rect.Contains(pt)) #else - if (rect.Inside(pt)) + if (rect.Inside(pt)) #endif - return wxSHEET_SPLIT_VERTICAL; - } + return wxSHEET_SPLIT_VERTICAL; + } - return wxSHEET_SPLIT_NONE; + return wxSHEET_SPLIT_NONE; } void wxSheetSplitter::SetMouseCursor(int sheet_split_mode) { - if (m_splitCursor == sheet_split_mode) - return; + if (m_splitCursor == sheet_split_mode) { + return; + } - m_splitCursor = sheet_split_mode; - wxClientDC dc(this); - DrawSash(dc); + m_splitCursor = sheet_split_mode; + wxClientDC dc(this); + DrawSash(dc); - switch (sheet_split_mode) - { - case wxSHEET_SPLIT_VERTICAL : SetCursor(wxCURSOR_SIZENS); break; - case wxSHEET_SPLIT_HORIZONTAL : SetCursor(wxCURSOR_SIZEWE); break; - case wxSHEET_SPLIT_NONE : - default : SetCursor(*wxSTANDARD_CURSOR); - } + switch (sheet_split_mode) { + case wxSHEET_SPLIT_VERTICAL: + SetCursor(wxCURSOR_SIZENS); + break; + case wxSHEET_SPLIT_HORIZONTAL: + SetCursor(wxCURSOR_SIZEWE); + break; + case wxSHEET_SPLIT_NONE: + default: + SetCursor(*wxSTANDARD_CURSOR); + } } -bool wxSheetSplitter::SendEvent( wxEventType type, bool vert_split ) +bool wxSheetSplitter::SendEvent(wxEventType type, bool vert_split) { - wxSheetSplitterEvent event(GetId(), type); - event.SetEventObject(this); - event.m_vert_split = vert_split; - event.m_sash_pos = vert_split ? m_splitPos.y : m_splitPos.x; - return DoSendEvent(event); + wxSheetSplitterEvent event(GetId(), type); + event.SetEventObject(this); + event.m_vert_split = vert_split; + event.m_sash_pos = vert_split ? m_splitPos.y : m_splitPos.x; + return DoSendEvent(event); } -bool wxSheetSplitter::DoSendEvent( wxSheetSplitterEvent& event ) +bool wxSheetSplitter::DoSendEvent(wxSheetSplitterEvent &event) { - bool claimed = GetEventHandler()->ProcessEvent(event); - bool vetoed = !event.IsAllowed(); - return !vetoed && !claimed; + bool claimed = GetEventHandler()->ProcessEvent(event); + bool vetoed = !event.IsAllowed(); + return !vetoed && !claimed; } // ---------------------------------------------------------------------------- diff --git a/src/labenski/src/sheettbl.cpp b/src/labenski/src/sheettbl.cpp index 62845550b..59dab0a5f 100644 --- a/src/labenski/src/sheettbl.cpp +++ b/src/labenski/src/sheettbl.cpp @@ -13,18 +13,22 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #include "wx/sheet/sheettbl.h" #include "wx/sheet/sheet.h" -#include // used in GetDefaultColLabelValue +#include // used in GetDefaultColLabelValue #ifndef WX_PRECOMP #endif // WX_PRECOMP -#define PRINT_BLOCK(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); -#define PRINT_RECT(s, b) wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_BLOCK(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); +#define PRINT_RECT(s, b) \ + wxPrintf(wxT("%s %d %d %d %d - w%d h%d\n"), wxT(s), b.GetTop(), b.GetLeft(), b.GetBottom(), \ + b.GetRight(), b.GetWidth(), b.GetHeight()); #define wxStrF wxString::Format @@ -36,1042 +40,1060 @@ DEFINE_PAIRED_INT_DATA_ARRAYS(wxString, wxPairArrayIntSheetString) DEFINE_PAIRED_INT_DATA_ARRAYS(wxPairArrayIntSheetString, wxPairArrayIntPairArraySheetString) #if !wxUSE_GRID - WX_DEFINE_OBJARRAY(wxSheetStringArray) // else use wxGridStringArray -#endif // wxUSE_GRID +WX_DEFINE_OBJARRAY(wxSheetStringArray) // else use wxGridStringArray +#endif // wxUSE_GRID // ---------------------------------------------------------------------------- // wxArrayStringUpdatePos - UpdatePos for wxArrayString // ---------------------------------------------------------------------------- -bool wxArrayStringUpdatePos(wxArrayString& arr, size_t pos, int num, bool no_error) +bool wxArrayStringUpdatePos(wxArrayString &arr, size_t pos, int num, bool no_error) { - if (num == 0) + if (num == 0) { + return false; + } + else if (num > 0) { + // if no_error check if <= GetCount, else let array error out + if (!no_error || (pos <= arr.GetCount())) { + arr.Insert(wxEmptyString, pos, num); + } + } + else // if (num < 0) + { + const int count = arr.GetCount(); + if (no_error && (int(pos) - num > count)) { + num = -(count - int(pos)); + if ((num >= 0) || (count == 0)) { return false; - else if (num > 0) - { - // if no_error check if <= GetCount, else let array error out - if (!no_error || (pos <= arr.GetCount())) - arr.Insert( wxEmptyString, pos, num ); + } + } + else { + wxCHECK_MSG(int(pos) - num <= count, false, + wxStrF(wxT("Called wxArrayStringUpdatePos(pos=%d, N=%d)\nPos value is invalid " + "for present array with %d elements"), + int(pos), num, count)); } - else // if (num < 0) - { - const int count = arr.GetCount(); - if (no_error && (int(pos) - num > count)) - { - num = -(count - int(pos)); - if ((num >= 0) || (count == 0)) return false; - } - else - { - wxCHECK_MSG( int(pos) - num <= count, false, - wxStrF(wxT("Called wxArrayStringUpdatePos(pos=%d, N=%d)\nPos value is invalid for present array with %d elements"), - int(pos), num, count) ); - } - if ((pos == 0u) && (num == count)) - arr.Clear(); - else - arr.RemoveAt( pos, -num ); + if ((pos == 0u) && (num == count)) { + arr.Clear(); + } + else { + arr.RemoveAt(pos, -num); } + } - return true; + return true; } // ---------------------------------------------------------------------------- // wxSheetDataBase // ---------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS( wxSheetValueProviderBase, wxObject ) +IMPLEMENT_ABSTRACT_CLASS(wxSheetValueProviderBase, wxObject) void wxSheetValueProviderBase::Clear() { - const int numRows = GetNumberRows(); - const int numCols = GetNumberCols(); - if (numRows > 0) UpdateRows(0, -numRows); - if (numCols > 0) UpdateCols(0, -numCols); -} - -void wxSheetValueProviderBase::Copy(const wxSheetValueProviderBase& other) -{ - Clear(); - const int numRows = other.GetNumberRows(); - const int numCols = other.GetNumberCols(); - m_options = other.GetOptions(); - UpdateRows(0, numRows); - UpdateCols(0, numCols); - wxSheetCoords c; - - for (c.m_row = 0; c.m_row < numRows; c.m_row++) - { - for (c.m_col = 0; c.m_col < numCols; c.m_col++) - { - wxString val(other.GetValue(c)); - if (!val.IsEmpty()) - SetValue(c, val); - } + const int numRows = GetNumberRows(); + const int numCols = GetNumberCols(); + if (numRows > 0) { + UpdateRows(0, -numRows); + } + if (numCols > 0) { + UpdateCols(0, -numCols); + } +} + +void wxSheetValueProviderBase::Copy(const wxSheetValueProviderBase &other) +{ + Clear(); + const int numRows = other.GetNumberRows(); + const int numCols = other.GetNumberCols(); + m_options = other.GetOptions(); + UpdateRows(0, numRows); + UpdateCols(0, numCols); + wxSheetCoords c; + + for (c.m_row = 0; c.m_row < numRows; c.m_row++) { + for (c.m_col = 0; c.m_col < numCols; c.m_col++) { + wxString val(other.GetValue(c)); + if (!val.IsEmpty()) { + SetValue(c, val); + } } + } } // ---------------------------------------------------------------------------- // wxSheetStringData - base class for a string provider class for the table // ---------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS( wxSheetValueProviderString, wxSheetValueProviderBase ) +IMPLEMENT_ABSTRACT_CLASS(wxSheetValueProviderString, wxSheetValueProviderBase) wxSheetValueProviderString::wxSheetValueProviderString(size_t numRows, size_t numCols, int options) - :wxSheetValueProviderBase(0, 0, options) + : wxSheetValueProviderBase(0, 0, options) { - m_numRows += numRows; - m_numCols += numCols; - DoUpdateRows(0, HasOption(wxSHEET_ValueProviderColPref) ? numRows : numCols); - DoUpdateCols(0, HasOption(wxSHEET_ValueProviderColPref) ? numCols : numRows); + m_numRows += numRows; + m_numCols += numCols; + DoUpdateRows(0, HasOption(wxSHEET_ValueProviderColPref) ? numRows : numCols); + DoUpdateCols(0, HasOption(wxSHEET_ValueProviderColPref) ? numCols : numRows); } -wxString wxSheetValueProviderString::GetValue( const wxSheetCoords& coords_ ) const +wxString wxSheetValueProviderString::GetValue(const wxSheetCoords &coords_) const { - wxCHECK_MSG(ContainsCell(coords_), wxEmptyString, wxT("Invalid coords")); - wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); + wxCHECK_MSG(ContainsCell(coords_), wxEmptyString, wxT("Invalid coords")); + wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); - //wxPrintf(wxT("RC %d %d - NumRC %d %d DataRC %d %d '%s'\n"), coords_.m_row, coords_.m_col, m_numRows, m_numCols, - // m_data.GetCount(), int(m_data.GetCount()) > coords.m_col ? m_data[coords.m_col].GetCount() : 0, - // wxDateTime::Now().FormatISOTime().c_str()); + // wxPrintf(wxT("RC %d %d - NumRC %d %d DataRC %d %d '%s'\n"), coords_.m_row, coords_.m_col, + // m_numRows, m_numCols, + // m_data.GetCount(), int(m_data.GetCount()) > coords.m_col ? m_data[coords.m_col].GetCount() + // : 0, wxDateTime::Now().FormatISOTime().c_str()); - if ((int(m_data.GetCount()) > coords.m_row) && - (int(m_data[coords.m_row].GetCount()) > coords.m_col)) - return m_data[coords.m_row][coords.m_col]; + if ((int(m_data.GetCount()) > coords.m_row) && + (int(m_data[coords.m_row].GetCount()) > coords.m_col)) { + return m_data[coords.m_row][coords.m_col]; + } - return wxEmptyString; + return wxEmptyString; } -void wxSheetValueProviderString::SetValue( const wxSheetCoords& coords_, const wxString& value ) +void wxSheetValueProviderString::SetValue(const wxSheetCoords &coords_, const wxString &value) { - wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); - wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); + wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); + wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); - // add "rows" as necessary to store value - int count = m_data.GetCount(); - if (count <= coords.m_row) - { - wxArrayString sa; - sa.Add( wxEmptyString, 1+coords.m_col ); - m_data.Insert( sa, count, 1+coords.m_row-count ); - } - else // believe it or not - NOT having this else statement is 10% faster in gcc - { - // add "cols" as necessary to store value - count = m_data[coords.m_row].GetCount(); - if (count <= coords.m_col) - { - m_data.Item(coords.m_row).Insert( wxEmptyString, count, 1+coords.m_col-count ); - } + // add "rows" as necessary to store value + int count = m_data.GetCount(); + if (count <= coords.m_row) { + wxArrayString sa; + sa.Add(wxEmptyString, 1 + coords.m_col); + m_data.Insert(sa, count, 1 + coords.m_row - count); + } + else // believe it or not - NOT having this else statement is 10% faster in gcc + { + // add "cols" as necessary to store value + count = m_data[coords.m_row].GetCount(); + if (count <= coords.m_col) { + m_data.Item(coords.m_row).Insert(wxEmptyString, count, 1 + coords.m_col - count); } - m_data[coords.m_row][coords.m_col] = value; + } + m_data[coords.m_row][coords.m_col] = value; } -int wxSheetValueProviderString::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const +int wxSheetValueProviderString::GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) const { - wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); - if (HasOption(wxSHEET_ValueProviderColPref)) - { - if (int(m_data.GetCount()) <= coords.m_row) - return -1; - if (int(m_data[coords.m_row].GetCount()) < coords.m_col) - return m_data[coords.m_row].GetCount() - 1; + wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); + if (HasOption(wxSHEET_ValueProviderColPref)) { + if (int(m_data.GetCount()) <= coords.m_row) { + return -1; + } + if (int(m_data[coords.m_row].GetCount()) < coords.m_col) { + return m_data[coords.m_row].GetCount() - 1; } - // the else case cannot be optimized - just use default - return coords.m_col - 1; + } + // the else case cannot be optimized - just use default + return coords.m_col - 1; } -bool wxSheetValueProviderString::UpdateRows( size_t row, int numRows ) +bool wxSheetValueProviderString::UpdateRows(size_t row, int numRows) { - wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false); - m_numRows += numRows; - return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) : - DoUpdateCols(row, numRows); + wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false); + m_numRows += numRows; + return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) + : DoUpdateCols(row, numRows); } -bool wxSheetValueProviderString::UpdateCols( size_t col, int numCols ) +bool wxSheetValueProviderString::UpdateCols(size_t col, int numCols) { - wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numCols, false); - m_numCols += numCols; - return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) : - DoUpdateRows(col, numCols); + wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numCols, false); + m_numCols += numCols; + return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) + : DoUpdateRows(col, numCols); } -bool wxSheetValueProviderString::DoUpdateRows( size_t row, int numRows ) +bool wxSheetValueProviderString::DoUpdateRows(size_t row, int numRows) { - // get things right before calling this, remember the rows may not be - // filled completely and this won't error out - const int curNumRows = m_data.GetCount(); - //const int curNumCols = curNumRows > 0 ? m_data.Item(0).GetCount() : m_numCols; + // get things right before calling this, remember the rows may not be + // filled completely and this won't error out + const int curNumRows = m_data.GetCount(); + // const int curNumCols = curNumRows > 0 ? m_data.Item(0).GetCount() : m_numCols; - if (numRows == 0) - return false; - else if (numRows > 0) + if (numRows == 0) { + return false; + } + else if (numRows > 0) { + if (curNumRows > int(row)) // only insert, no need to append { - if (curNumRows > int(row)) // only insert, no need to append - { - wxArrayString sa; - m_data.Insert( sa, row, numRows ); - } + wxArrayString sa; + m_data.Insert(sa, row, numRows); } - else // if (numRows < 0) - { - if (curNumRows > int(row)) - { - m_data.RemoveAt( row, wxMin(curNumRows-int(row), -numRows) ); - } + } + else // if (numRows < 0) + { + if (curNumRows > int(row)) { + m_data.RemoveAt(row, wxMin(curNumRows - int(row), -numRows)); } + } - return true; + return true; } -bool wxSheetValueProviderString::DoUpdateCols( size_t col, int numCols ) +bool wxSheetValueProviderString::DoUpdateCols(size_t col, int numCols) { - // only insert or delete cols, no need to append - const int curNumRows = m_data.GetCount(); + // only insert or delete cols, no need to append + const int curNumRows = m_data.GetCount(); - if (numCols == 0) - return false; - else if (numCols > 0) - { - for ( int row = 0; row < curNumRows; row++ ) - { - if (m_data[row].GetCount() > col) - m_data[row].Insert( wxEmptyString, col, numCols ); - } + if (numCols == 0) { + return false; + } + else if (numCols > 0) { + for (int row = 0; row < curNumRows; row++) { + if (m_data[row].GetCount() > col) { + m_data[row].Insert(wxEmptyString, col, numCols); + } } - else // if (numCols < 0) - { - for ( int row = 0; row < curNumRows; row++ ) - { - const int curNumCols = m_data[row].GetCount(); - if (curNumCols > int(col)) - { - m_data[row].RemoveAt( col, wxMin(curNumCols-int(col), -numCols) ); - } - } + } + else // if (numCols < 0) + { + for (int row = 0; row < curNumRows; row++) { + const int curNumCols = m_data[row].GetCount(); + if (curNumCols > int(col)) { + m_data[row].RemoveAt(col, wxMin(curNumCols - int(col), -numCols)); + } } + } - return true; + return true; } void wxSheetValueProviderString::SetOptions(int options) { - if (options == m_options) return; - wxSheetValueProviderString data(0,0,options); - data.Copy(*this); - m_options = options; - Copy(data); + if (options == m_options) { + return; + } + wxSheetValueProviderString data(0, 0, options); + data.Copy(*this); + m_options = options; + Copy(data); } //----------------------------------------------------------------------------- // wxPairArrayIntPairArraySheetString - string data //----------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS( wxSheetValueProviderSparseString, wxSheetValueProviderBase ) +IMPLEMENT_ABSTRACT_CLASS(wxSheetValueProviderSparseString, wxSheetValueProviderBase) -wxSheetValueProviderSparseString::wxSheetValueProviderSparseString(size_t numRows, size_t numCols, int options) - :wxSheetValueProviderBase(0, 0, options) +wxSheetValueProviderSparseString::wxSheetValueProviderSparseString(size_t numRows, size_t numCols, + int options) + : wxSheetValueProviderBase(0, 0, options) { - m_numRows += numRows; - m_numCols += numCols; - DoUpdateRows(0, HasOption(wxSHEET_ValueProviderColPref) ? numRows : numCols); - DoUpdateCols(0, HasOption(wxSHEET_ValueProviderColPref) ? numCols : numRows); + m_numRows += numRows; + m_numCols += numCols; + DoUpdateRows(0, HasOption(wxSHEET_ValueProviderColPref) ? numRows : numCols); + DoUpdateCols(0, HasOption(wxSHEET_ValueProviderColPref) ? numCols : numRows); } -wxString wxSheetValueProviderSparseString::GetValue( const wxSheetCoords& coords_ ) const +wxString wxSheetValueProviderSparseString::GetValue(const wxSheetCoords &coords_) const { - wxCHECK_MSG(ContainsCell(coords_), wxEmptyString, wxT("Invalid coords")); - wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); + wxCHECK_MSG(ContainsCell(coords_), wxEmptyString, wxT("Invalid coords")); + wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); - const int rowPos = m_data.FindIndex(coords.m_row); - if (rowPos != wxNOT_FOUND) - return m_data.GetItemValue(rowPos).GetValue(coords.m_col); + const int rowPos = m_data.FindIndex(coords.m_row); + if (rowPos != wxNOT_FOUND) { + return m_data.GetItemValue(rowPos).GetValue(coords.m_col); + } - return wxEmptyString; + return wxEmptyString; } -void wxSheetValueProviderSparseString::SetValue( const wxSheetCoords& coords_, - const wxString& value ) +void wxSheetValueProviderSparseString::SetValue(const wxSheetCoords &coords_, + const wxString &value) { - wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); - wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); - const int rowPos = m_data.FindIndex(coords.m_row); + wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); + wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); + const int rowPos = m_data.FindIndex(coords.m_row); - if (value.IsEmpty()) - { - // remove the value if empty - if (rowPos != wxNOT_FOUND) - { - m_data.GetItemValue(rowPos).RemoveValue(coords.m_col); - // remove this row if empty - if (m_data.GetItemValue(rowPos).GetCount() == 0) - m_data.RemoveAt(rowPos); - } + if (value.IsEmpty()) { + // remove the value if empty + if (rowPos != wxNOT_FOUND) { + m_data.GetItemValue(rowPos).RemoveValue(coords.m_col); + // remove this row if empty + if (m_data.GetItemValue(rowPos).GetCount() == 0) { + m_data.RemoveAt(rowPos); + } } - else - { - if (rowPos == wxNOT_FOUND) - m_data.GetOrCreateValue(coords.m_row).SetValue(coords.m_col, value); - else - m_data.GetItemValue(rowPos).SetValue(coords.m_col, value); + } + else { + if (rowPos == wxNOT_FOUND) { + m_data.GetOrCreateValue(coords.m_row).SetValue(coords.m_col, value); + } + else { + m_data.GetItemValue(rowPos).SetValue(coords.m_col, value); } + } } -bool wxSheetValueProviderSparseString::HasValue( const wxSheetCoords& coords_ ) const +bool wxSheetValueProviderSparseString::HasValue(const wxSheetCoords &coords_) const { - wxCHECK_MSG(ContainsCell(coords_), false, wxT("Invalid coords")); - wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); - const int rowPos = m_data.FindIndex(coords.m_row); - if (rowPos == wxNOT_FOUND) - return false; + wxCHECK_MSG(ContainsCell(coords_), false, wxT("Invalid coords")); + wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); + const int rowPos = m_data.FindIndex(coords.m_row); + if (rowPos == wxNOT_FOUND) { + return false; + } - return m_data.GetItemValue(rowPos).FindIndex(coords.m_col) != wxNOT_FOUND; + return m_data.GetItemValue(rowPos).FindIndex(coords.m_col) != wxNOT_FOUND; } -int wxSheetValueProviderSparseString::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const +int wxSheetValueProviderSparseString::GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) const { - wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); - if (HasOption(wxSHEET_ValueProviderColPref)) - { - const int rowPos = m_data.FindIndex(coords.m_row); - if (rowPos != wxNOT_FOUND) - { - // pos == 0 meaning nothing to left, == count for col > last filled - const int colPos = m_data.GetItemValue(rowPos).FindInsertIndex(coords.m_col); - if (colPos > 0) - return m_data.GetItemValue(rowPos).GetItemKey(colPos-1); - } - return -1; + wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); + if (HasOption(wxSHEET_ValueProviderColPref)) { + const int rowPos = m_data.FindIndex(coords.m_row); + if (rowPos != wxNOT_FOUND) { + // pos == 0 meaning nothing to left, == count for col > last filled + const int colPos = m_data.GetItemValue(rowPos).FindInsertIndex(coords.m_col); + if (colPos > 0) { + return m_data.GetItemValue(rowPos).GetItemKey(colPos - 1); + } } + return -1; + } - return coords.m_col - 1; + return coords.m_col - 1; } -bool wxSheetValueProviderSparseString::UpdateRows( size_t row, int numRows ) +bool wxSheetValueProviderSparseString::UpdateRows(size_t row, int numRows) { - wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false) - m_numRows += numRows; - return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) : - DoUpdateCols(row, numRows); + wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false) m_numRows += numRows; + return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) + : DoUpdateCols(row, numRows); } -bool wxSheetValueProviderSparseString::UpdateCols( size_t col, int numCols ) +bool wxSheetValueProviderSparseString::UpdateCols(size_t col, int numCols) { - wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numRows, false) - m_numCols += numCols; - return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) : - DoUpdateRows(col, numCols); + wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numRows, false) m_numCols += numCols; + return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) + : DoUpdateRows(col, numCols); } -bool wxSheetValueProviderSparseString::DoUpdateRows( size_t row, int numRows ) +bool wxSheetValueProviderSparseString::DoUpdateRows(size_t row, int numRows) { - return m_data.UpdatePos(row, numRows); + return m_data.UpdatePos(row, numRows); } -bool wxSheetValueProviderSparseString::DoUpdateCols( size_t col, int numCols ) +bool wxSheetValueProviderSparseString::DoUpdateCols(size_t col, int numCols) { - bool done = false; - size_t row, rowCount = m_data.GetCount(); - for (row=0; rowsecond.find(coords.m_col); - if (col_iter != row_iter->second.end()) - return col_iter->second; + wxSheetStringHashStringHash::const_iterator row_iter = m_data.find(coords.m_row); + if (row_iter != m_data.end()) { + wxSheetStringHash::const_iterator col_iter = row_iter->second.find(coords.m_col); + if (col_iter != row_iter->second.end()) { + return col_iter->second; } - return wxEmptyString; + } + return wxEmptyString; } -void wxSheetValueProviderHashString::SetValue( const wxSheetCoords& coords_, - const wxString& value ) +void wxSheetValueProviderHashString::SetValue(const wxSheetCoords &coords_, const wxString &value) { - wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); - wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); + wxCHECK_RET(ContainsCell(coords_), wxT("Invalid coords")); + wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); - wxSheetStringHashStringHash::iterator row_iter = m_data.find(coords.m_row); - if (row_iter == m_data.end()) - { - wxSheetStringHash colHash; - colHash[coords.m_col] = value; - m_data[coords.m_row] = colHash; - return; - } + wxSheetStringHashStringHash::iterator row_iter = m_data.find(coords.m_row); + if (row_iter == m_data.end()) { + wxSheetStringHash colHash; + colHash[coords.m_col] = value; + m_data[coords.m_row] = colHash; + return; + } - row_iter->second[coords.m_col] = value; + row_iter->second[coords.m_col] = value; } -bool wxSheetValueProviderHashString::HasValue( const wxSheetCoords& coords_ ) const +bool wxSheetValueProviderHashString::HasValue(const wxSheetCoords &coords_) const { - wxCHECK_MSG(ContainsCell(coords_), false, wxT("Invalid coords")); - wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); - wxSheetStringHashStringHash::const_iterator row_iter = m_data.find(coords.m_row); - if (row_iter != m_data.end()) - { - wxSheetStringHash::const_iterator col_iter = row_iter->second.find(coords.m_col); - if (col_iter != row_iter->second.end()) - return true; + wxCHECK_MSG(ContainsCell(coords_), false, wxT("Invalid coords")); + wxSheetCoords coords(HasOption(wxSHEET_ValueProviderColPref) ? coords_ : coords_.GetSwapped()); + wxSheetStringHashStringHash::const_iterator row_iter = m_data.find(coords.m_row); + if (row_iter != m_data.end()) { + wxSheetStringHash::const_iterator col_iter = row_iter->second.find(coords.m_col); + if (col_iter != row_iter->second.end()) { + return true; } - return false; + } + return false; } -int wxSheetValueProviderHashString::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) const +int wxSheetValueProviderHashString::GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) const { - wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); - if (HasOption(wxSHEET_ValueProviderColPref)) - { - wxSheetStringHashStringHash::const_iterator row_iter = m_data.find(coords.m_row); - if (row_iter == m_data.end()) - return -1; + wxCHECK_MSG(ContainsCell(coords), coords.m_col - 1, wxT("Invalid coords")); + if (HasOption(wxSHEET_ValueProviderColPref)) { + wxSheetStringHashStringHash::const_iterator row_iter = m_data.find(coords.m_row); + if (row_iter == m_data.end()) { + return -1; } + } - return coords.m_col - 1; + return coords.m_col - 1; } -bool wxSheetValueProviderHashString::UpdateRows( size_t row, int numRows ) +bool wxSheetValueProviderHashString::UpdateRows(size_t row, int numRows) { - wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false) - bool append = (int(row) == m_numRows); - m_numRows += numRows; - if (!m_numCols || !m_numRows) - { - ClearValues(); - return true; - } - - if (!append) - return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) : - DoUpdateCols(row, numRows); + wxSHEET_CHECKUPDATE_MSG(row, numRows, m_numRows, false) bool append = (int(row) == m_numRows); + m_numRows += numRows; + if (!m_numCols || !m_numRows) { + ClearValues(); return true; + } + + if (!append) { + return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateRows(row, numRows) + : DoUpdateCols(row, numRows); + } + return true; } -bool wxSheetValueProviderHashString::UpdateCols( size_t col, int numCols ) +bool wxSheetValueProviderHashString::UpdateCols(size_t col, int numCols) { - wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numRows, false) - bool append = (int(col) == m_numRows); - m_numCols += numCols; - if (!m_numCols || !m_numRows) - { - ClearValues(); - return true; - } - if (!append) - return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) : - DoUpdateRows(col, numCols); + wxSHEET_CHECKUPDATE_MSG(col, numCols, m_numRows, false) bool append = (int(col) == m_numRows); + m_numCols += numCols; + if (!m_numCols || !m_numRows) { + ClearValues(); return true; + } + if (!append) { + return HasOption(wxSHEET_ValueProviderColPref) ? DoUpdateCols(col, numCols) + : DoUpdateRows(col, numCols); + } + return true; } -bool wxSheetValueProviderHashString::DoUpdateRows( size_t row, int numRows ) +bool wxSheetValueProviderHashString::DoUpdateRows(size_t row, int numRows) { - if (numRows == 0) - return false; - else if (numRows > 0) + if (numRows == 0) { + return false; + } + else if (numRows > 0) { + if (!m_data.empty()) // FIXME only insert, already checked append { - if (!m_data.empty()) // FIXME only insert, already checked append - { - wxFAIL_MSG(wxT("Not implemented")); - } + wxFAIL_MSG(wxT("Not implemented")); } - else // if (numRows < 0) - { - const int row_end = row + numRows; - wxSheetStringHashStringHash::iterator row_iter = m_data.begin(); - while (row_iter != m_data.end()) - { - int data_row = row_iter->first; - if ((data_row >= int(row)) && (data_row < row_end)) - { - wxSheetStringHashStringHash::iterator it = row_iter; - row_iter++; - m_data.erase(it); - } - else - row_iter++; - } + } + else // if (numRows < 0) + { + const int row_end = row + numRows; + wxSheetStringHashStringHash::iterator row_iter = m_data.begin(); + while (row_iter != m_data.end()) { + int data_row = row_iter->first; + if ((data_row >= int(row)) && (data_row < row_end)) { + wxSheetStringHashStringHash::iterator it = row_iter; + row_iter++; + m_data.erase(it); + } + else { + row_iter++; + } } + } - return true; + return true; } -bool wxSheetValueProviderHashString::DoUpdateCols( size_t col, int numCols ) +bool wxSheetValueProviderHashString::DoUpdateCols(size_t col, int numCols) { - if (numCols == 0) - return false; - else if (numCols > 0) + if (numCols == 0) { + return false; + } + else if (numCols > 0) { + if (!m_data.empty()) // FIXME only insert, already checked append { - if (!m_data.empty()) // FIXME only insert, already checked append - { - wxFAIL_MSG(wxT("Not implemented")); - } + wxFAIL_MSG(wxT("Not implemented")); } - else // if (numCols < 0) - { - const int col_end = col + numCols; - wxSheetStringHashStringHash::iterator row_iter = m_data.begin(); - while (row_iter != m_data.end()) - { - wxSheetStringHash::iterator col_iter = row_iter->second.begin(); - while (col_iter != row_iter->second.end()) - { - int data_col = col_iter->first; - if ((data_col >= int(col)) && (data_col < col_end)) - { - wxSheetStringHash::iterator it = col_iter; - col_iter++; - row_iter->second.erase(it); - } - else - col_iter++; - } - row_iter++; + } + else // if (numCols < 0) + { + const int col_end = col + numCols; + wxSheetStringHashStringHash::iterator row_iter = m_data.begin(); + while (row_iter != m_data.end()) { + wxSheetStringHash::iterator col_iter = row_iter->second.begin(); + while (col_iter != row_iter->second.end()) { + int data_col = col_iter->first; + if ((data_col >= int(col)) && (data_col < col_end)) { + wxSheetStringHash::iterator it = col_iter; + col_iter++; + row_iter->second.erase(it); + } + else { + col_iter++; } + } + row_iter++; } + } - return true; + return true; } void wxSheetValueProviderHashString::SetOptions(int options) { - if (options == m_options) return; - wxSheetValueProviderHashString data(0,0,options); - data.Copy(*this); - m_options = options; - Copy(data); + if (options == m_options) { + return; + } + wxSheetValueProviderHashString data(0, 0, options); + data.Copy(*this); + m_options = options; + Copy(data); } #endif // wxSHEET_USE_VALUE_PROVIDER_HASH // ---------------------------------------------------------------------------- // wxSheetTable // ---------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS( wxSheetTable, wxObject ) +IMPLEMENT_ABSTRACT_CLASS(wxSheetTable, wxObject) wxSheetTable::wxSheetTable(wxSheet *view) - :wxObject(), m_view(view), - m_attrProvider(NULL), m_own_attr_provider(true), - m_gridCellValues(NULL), m_own_grid_cell_values(true), - m_rowLabelValues(NULL), m_own_row_label_values(true), - m_colLabelValues(NULL), m_own_col_label_values(true), - m_spannedCells(NULL), m_own_spanned_cells(true) + : wxObject(), m_view(view), m_attrProvider(NULL), m_own_attr_provider(true), + m_gridCellValues(NULL), m_own_grid_cell_values(true), m_rowLabelValues(NULL), + m_own_row_label_values(true), m_colLabelValues(NULL), m_own_col_label_values(true), + m_spannedCells(NULL), m_own_spanned_cells(true) { - m_spannedCells = new wxSheetSelection(); + m_spannedCells = new wxSheetSelection(); } wxSheetTable::~wxSheetTable() { - SetAttrProvider(NULL, true); - SetGridCellValueProvider(NULL, true); - SetRowLabelValueProvider(NULL, true); - SetColLabelValueProvider(NULL, true); - SetSpannedBlocks(NULL, true); + SetAttrProvider(NULL, true); + SetGridCellValueProvider(NULL, true); + SetRowLabelValueProvider(NULL, true); + SetColLabelValueProvider(NULL, true); + SetSpannedBlocks(NULL, true); } int wxSheetTable::GetNumberRows() { - wxCHECK_MSG(GetGridCellValueProvider(), 0, wxT("Invalid cell data for the table")); - return GetGridCellValueProvider()->GetNumberRows(); + wxCHECK_MSG(GetGridCellValueProvider(), 0, wxT("Invalid cell data for the table")); + return GetGridCellValueProvider()->GetNumberRows(); } int wxSheetTable::GetNumberCols() { - wxCHECK_MSG(GetGridCellValueProvider(), 0, wxT("Invalid cell data for the table")); - return GetGridCellValueProvider()->GetNumberCols(); + wxCHECK_MSG(GetGridCellValueProvider(), 0, wxT("Invalid cell data for the table")); + return GetGridCellValueProvider()->GetNumberCols(); } -wxString wxSheetTable::GetValue( const wxSheetCoords& coords ) +wxString wxSheetTable::GetValue(const wxSheetCoords &coords) { - switch (wxSheet::GetCellCoordsType(coords)) - { - case wxSHEET_CELL_GRID : - { - // need cell data for values, or override this - wxCHECK_MSG(GetGridCellValueProvider(), wxEmptyString, wxT("Invalid grid cell data for the table")); - return GetGridCellValueProvider()->GetValue(coords); - } - case wxSHEET_CELL_ROWLABEL : - { - // just return default if no row label data - wxSheetCoords rowCoords(coords.SheetToRowLabel()); - if (GetRowLabelValueProvider() && GetRowLabelValueProvider()->HasValue(rowCoords)) - return GetRowLabelValueProvider()->GetValue(rowCoords); - - return GetDefaultRowLabelValue(coords.m_row); - } - case wxSHEET_CELL_COLLABEL : - { - wxSheetCoords colCoords(coords.SheetToColLabel()); - if (GetColLabelValueProvider() && GetColLabelValueProvider()->HasValue(colCoords)) - return GetColLabelValueProvider()->GetValue(colCoords); - - return GetDefaultColLabelValue(coords.m_col); - } - case wxSHEET_CELL_CORNERLABEL : - { - return m_cornerLabelValue; - } - default : - return wxEmptyString; + switch (wxSheet::GetCellCoordsType(coords)) { + case wxSHEET_CELL_GRID: { + // need cell data for values, or override this + wxCHECK_MSG(GetGridCellValueProvider(), wxEmptyString, + wxT("Invalid grid cell data for the table")); + return GetGridCellValueProvider()->GetValue(coords); + } + case wxSHEET_CELL_ROWLABEL: { + // just return default if no row label data + wxSheetCoords rowCoords(coords.SheetToRowLabel()); + if (GetRowLabelValueProvider() && GetRowLabelValueProvider()->HasValue(rowCoords)) { + return GetRowLabelValueProvider()->GetValue(rowCoords); } -} -void wxSheetTable::SetValue( const wxSheetCoords& coords, const wxString& value ) -{ - // You must override this or have set data containers for this to work - switch (wxSheet::GetCellCoordsType(coords)) - { - case wxSHEET_CELL_GRID : - { - wxCHECK_RET(GetGridCellValueProvider(), wxT("Invalid grid cell data for the table")); - GetGridCellValueProvider()->SetValue(coords, value); - break; - } - case wxSHEET_CELL_ROWLABEL : - { - wxCHECK_RET(GetRowLabelValueProvider(), wxT("Invalid row label data for the table")); - GetRowLabelValueProvider()->SetValue(coords.SheetToRowLabel(), value); - break; - } - case wxSHEET_CELL_COLLABEL : - { - wxCHECK_RET(GetColLabelValueProvider(), wxT("Invalid col label data for the table")); - GetColLabelValueProvider()->SetValue(coords.SheetToColLabel(), value); - break; - } - case wxSHEET_CELL_CORNERLABEL : - { - m_cornerLabelValue = value; - break; - } - default : - break; + return GetDefaultRowLabelValue(coords.m_row); + } + case wxSHEET_CELL_COLLABEL: { + wxSheetCoords colCoords(coords.SheetToColLabel()); + if (GetColLabelValueProvider() && GetColLabelValueProvider()->HasValue(colCoords)) { + return GetColLabelValueProvider()->GetValue(colCoords); } -} -bool wxSheetTable::HasValue( const wxSheetCoords& coords ) -{ - switch (wxSheet::GetCellCoordsType(coords)) - { - case wxSHEET_CELL_GRID : - { - if (GetGridCellValueProvider()) - return GetGridCellValueProvider()->HasValue(coords); - break; - } - case wxSHEET_CELL_ROWLABEL : - { - if (GetRowLabelValueProvider()) - return GetRowLabelValueProvider()->HasValue(coords.SheetToRowLabel()); + return GetDefaultColLabelValue(coords.m_col); + } + case wxSHEET_CELL_CORNERLABEL: { + return m_cornerLabelValue; + } + default: + return wxEmptyString; + } +} + +void wxSheetTable::SetValue(const wxSheetCoords &coords, const wxString &value) +{ + // You must override this or have set data containers for this to work + switch (wxSheet::GetCellCoordsType(coords)) { + case wxSHEET_CELL_GRID: { + wxCHECK_RET(GetGridCellValueProvider(), wxT("Invalid grid cell data for the table")); + GetGridCellValueProvider()->SetValue(coords, value); + break; + } + case wxSHEET_CELL_ROWLABEL: { + wxCHECK_RET(GetRowLabelValueProvider(), wxT("Invalid row label data for the table")); + GetRowLabelValueProvider()->SetValue(coords.SheetToRowLabel(), value); + break; + } + case wxSHEET_CELL_COLLABEL: { + wxCHECK_RET(GetColLabelValueProvider(), wxT("Invalid col label data for the table")); + GetColLabelValueProvider()->SetValue(coords.SheetToColLabel(), value); + break; + } + case wxSHEET_CELL_CORNERLABEL: { + m_cornerLabelValue = value; + break; + } + default: + break; + } +} +bool wxSheetTable::HasValue(const wxSheetCoords &coords) +{ + switch (wxSheet::GetCellCoordsType(coords)) { + case wxSHEET_CELL_GRID: { + if (GetGridCellValueProvider()) { + return GetGridCellValueProvider()->HasValue(coords); + } - break; - } - case wxSHEET_CELL_COLLABEL : - { - if (GetColLabelValueProvider()) - return GetColLabelValueProvider()->HasValue(coords.SheetToColLabel()); + break; + } + case wxSHEET_CELL_ROWLABEL: { + if (GetRowLabelValueProvider()) { + return GetRowLabelValueProvider()->HasValue(coords.SheetToRowLabel()); + } - break; - } - case wxSHEET_CELL_CORNERLABEL : - default : break; + break; + } + case wxSHEET_CELL_COLLABEL: { + if (GetColLabelValueProvider()) { + return GetColLabelValueProvider()->HasValue(coords.SheetToColLabel()); } - return !GetValue(coords).IsEmpty(); + break; + } + case wxSHEET_CELL_CORNERLABEL: + default: + break; + } + + return !GetValue(coords).IsEmpty(); } -int wxSheetTable::GetFirstNonEmptyColToLeft( const wxSheetCoords& coords ) +int wxSheetTable::GetFirstNonEmptyColToLeft(const wxSheetCoords &coords) { - switch (wxSheet::GetCellCoordsType(coords)) - { - case wxSHEET_CELL_GRID : - { - if (GetGridCellValueProvider()) - return GetGridCellValueProvider()->GetFirstNonEmptyColToLeft(coords); - - break; - } - case wxSHEET_CELL_ROWLABEL : - { - if (GetRowLabelValueProvider()) - return GetRowLabelValueProvider()->GetFirstNonEmptyColToLeft(coords.SheetToRowLabel()); - - break; - } - case wxSHEET_CELL_COLLABEL : - { - if (GetColLabelValueProvider()) - return GetColLabelValueProvider()->GetFirstNonEmptyColToLeft(coords.SheetToColLabel()); - - break; - } - case wxSHEET_CELL_CORNERLABEL : - default : break; + switch (wxSheet::GetCellCoordsType(coords)) { + case wxSHEET_CELL_GRID: { + if (GetGridCellValueProvider()) { + return GetGridCellValueProvider()->GetFirstNonEmptyColToLeft(coords); } - return coords.m_col-1; -} - -void wxSheetTable::ClearValues(int update) -{ - if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) - GetGridCellValueProvider()->ClearValues(); - if (((update & wxSHEET_UpdateRowLabelValues) != 0) && GetRowLabelValueProvider()) - GetRowLabelValueProvider()->ClearValues(); - if (((update & wxSHEET_UpdateColLabelValues) != 0) && GetColLabelValueProvider()) - GetColLabelValueProvider()->ClearValues(); -/* - FIXME should add clearing attrs here - if (((update & wxSHEET_UpdateGridCellAttrs) != 0) && GetAttrProvider()) - GetAttrProvider()-> - if (((update & wxSHEET_UpdateRowLabelAttrs) != 0) && GetAttrProvider()) - GetAttrProvider()-> - if (((update & wxSHEET_UpdateColLabelAttrs) != 0) && GetAttrProvider()) - GetAttrProvider()-> -*/ -} - -wxString wxSheetTable::GetDefaultRowLabelValue( int row ) const -{ - return wxString::Format(wxT("%d"), row+1); // Starting at zero confuses users -} -wxString wxSheetTable::GetDefaultColLabelValue( int col ) const -{ - // default col labels are: cols [0-25]=[A-Z], cols [26-675]=[AA-ZZ] -/* - wxString s, s2; - unsigned int i, n; - for ( n = 1; ; n++ ) - { - s += wxChar((_T('A')) + (wxChar)( col%26 )); - col = col/26 - 1; - if ( col < 0 ) break; + break; + } + case wxSHEET_CELL_ROWLABEL: { + if (GetRowLabelValueProvider()) { + return GetRowLabelValueProvider()->GetFirstNonEmptyColToLeft(coords.SheetToRowLabel()); } - // reverse the string... - for ( i = n; i > 0; i-- ) s2 += s[i-1]; - //for ( i = 0; i < n; i++ ) s2 += s[n-i-1]; - - return s2; -*/ - - // new method using log function so you don't have to reverse the string - wxCHECK_MSG(col >= 0, wxEmptyString, wxT("Invalid col")); - const size_t chars = (col > 0) ? size_t(log((double) col)/3.2580965380) : 0; // log_26(x) = log(x)/log(26.0) - wxString s(wxT('A'), chars+1); - for ( size_t n = 0; n <= chars; n++ ) - { - s[size_t(chars - n)] = wxChar(_T('A') + (wxChar)(col%26)); - col = col/26 - 1; + + break; + } + case wxSHEET_CELL_COLLABEL: { + if (GetColLabelValueProvider()) { + return GetColLabelValueProvider()->GetFirstNonEmptyColToLeft(coords.SheetToColLabel()); } - return s; -} + break; + } + case wxSHEET_CELL_CORNERLABEL: + default: + break; + } -long wxSheetTable::GetValueAsLong( const wxSheetCoords& coords ) -{ - const wxString val(GetValue(coords)); - long lval = 0; - val.ToLong(&lval); - //wxCHECK_MSG(val.ToLong(&lval), 0, wxT("Unable to get cell ") + CS(coords) + wxT(" value as long.")); - return lval; -} -double wxSheetTable::GetValueAsDouble( const wxSheetCoords& coords ) -{ - const wxString val(GetValue(coords)); - double dval = 0.0; - val.ToDouble(&dval); - // wxCHECK_MSG(val.ToDouble(&dval), 0.0, wxT("Unable to get cell ") + CS(coords) + wxT(" value as double.")); - return dval; + return coords.m_col - 1; } -bool wxSheetTable::GetValueAsBool( const wxSheetCoords& coords ) + +void wxSheetTable::ClearValues(int update) { - const wxString val(GetValue(coords)); - if (val.IsEmpty() || (val == wxT("0")) || - (val.CmpNoCase(wxT("f")) == 0) || (val.CmpNoCase(wxT("false")) == 0)) - return false; + if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) { + GetGridCellValueProvider()->ClearValues(); + } + if (((update & wxSHEET_UpdateRowLabelValues) != 0) && GetRowLabelValueProvider()) { + GetRowLabelValueProvider()->ClearValues(); + } + if (((update & wxSHEET_UpdateColLabelValues) != 0) && GetColLabelValueProvider()) { + GetColLabelValueProvider()->ClearValues(); + } + /* + FIXME should add clearing attrs here + if (((update & wxSHEET_UpdateGridCellAttrs) != 0) && GetAttrProvider()) + GetAttrProvider()-> + if (((update & wxSHEET_UpdateRowLabelAttrs) != 0) && GetAttrProvider()) + GetAttrProvider()-> + if (((update & wxSHEET_UpdateColLabelAttrs) != 0) && GetAttrProvider()) + GetAttrProvider()-> + */ +} + +wxString wxSheetTable::GetDefaultRowLabelValue(int row) const +{ + return wxString::Format(wxT("%d"), row + 1); // Starting at zero confuses users +} +wxString wxSheetTable::GetDefaultColLabelValue(int col) const +{ + // default col labels are: cols [0-25]=[A-Z], cols [26-675]=[AA-ZZ] + /* + wxString s, s2; + unsigned int i, n; + for ( n = 1; ; n++ ) + { + s += wxChar((_T('A')) + (wxChar)( col%26 )); + col = col/26 - 1; + if ( col < 0 ) break; + } + // reverse the string... + for ( i = n; i > 0; i-- ) s2 += s[i-1]; + //for ( i = 0; i < n; i++ ) s2 += s[n-i-1]; + + return s2; + */ + + // new method using log function so you don't have to reverse the string + wxCHECK_MSG(col >= 0, wxEmptyString, wxT("Invalid col")); + const size_t chars = + (col > 0) ? size_t(log((double)col) / 3.2580965380) : 0; // log_26(x) = log(x)/log(26.0) + wxString s(wxT('A'), chars + 1); + for (size_t n = 0; n <= chars; n++) { + s[size_t(chars - n)] = wxChar(_T('A') + (wxChar)(col % 26)); + col = col / 26 - 1; + } + + return s; +} + +long wxSheetTable::GetValueAsLong(const wxSheetCoords &coords) +{ + const wxString val(GetValue(coords)); + long lval = 0; + val.ToLong(&lval); + // wxCHECK_MSG(val.ToLong(&lval), 0, wxT("Unable to get cell ") + CS(coords) + wxT(" value as + // long.")); + return lval; +} +double wxSheetTable::GetValueAsDouble(const wxSheetCoords &coords) +{ + const wxString val(GetValue(coords)); + double dval = 0.0; + val.ToDouble(&dval); + // wxCHECK_MSG(val.ToDouble(&dval), 0.0, wxT("Unable to get cell ") + CS(coords) + wxT(" value as + // double.")); + return dval; +} +bool wxSheetTable::GetValueAsBool(const wxSheetCoords &coords) +{ + const wxString val(GetValue(coords)); + if (val.IsEmpty() || (val == wxT("0")) || (val.CmpNoCase(wxT("f")) == 0) || + (val.CmpNoCase(wxT("false")) == 0)) { + return false; + } - return true; + return true; } -void wxSheetTable::SetValueAsLong( const wxSheetCoords& coords, long value ) +void wxSheetTable::SetValueAsLong(const wxSheetCoords &coords, long value) { - SetValue(coords, wxString::Format(wxT("%ld"), value)); + SetValue(coords, wxString::Format(wxT("%ld"), value)); } -void wxSheetTable::SetValueAsDouble( const wxSheetCoords& coords, double value ) +void wxSheetTable::SetValueAsDouble(const wxSheetCoords &coords, double value) { - SetValue(coords, wxString::Format(wxT("%g"), value)); + SetValue(coords, wxString::Format(wxT("%g"), value)); } -void wxSheetTable::SetValueAsBool( const wxSheetCoords& coords, bool value ) +void wxSheetTable::SetValueAsBool(const wxSheetCoords &coords, bool value) { - SetValue(coords, value ? wxT("1") : wxT("0")); + SetValue(coords, value ? wxT("1") : wxT("0")); } -void* wxSheetTable::GetValueAsCustom( const wxSheetCoords& coords, - const wxString& typeName ) +void *wxSheetTable::GetValueAsCustom(const wxSheetCoords &coords, const wxString &typeName) { - wxFAIL_MSG(wxStrF(wxT("Unable to return wxSheetTable::GetValueAsCustom for cell (%d, %d) and type '%s'"), - coords.m_row, coords.m_col, typeName.c_str())); + wxFAIL_MSG(wxStrF( + wxT("Unable to return wxSheetTable::GetValueAsCustom for cell (%d, %d) and type '%s'"), + coords.m_row, coords.m_col, typeName.c_str())); - return NULL; + return NULL; } -void wxSheetTable::SetValueAsCustom( const wxSheetCoords& coords, - const wxString& typeName, - void* WXUNUSED(value) ) +void wxSheetTable::SetValueAsCustom(const wxSheetCoords &coords, const wxString &typeName, + void *WXUNUSED(value)) { - wxFAIL_MSG(wxStrF(wxT("Unable to set wxSheetTable::SetValueAsCustom for cell (%d, %d) and type '%s'"), - coords.m_row, coords.m_col, typeName.c_str())); + wxFAIL_MSG( + wxStrF(wxT("Unable to set wxSheetTable::SetValueAsCustom for cell (%d, %d) and type '%s'"), + coords.m_row, coords.m_col, typeName.c_str())); } -bool wxSheetTable::CanGetValueAs( const wxSheetCoords& coords, - const wxString& typeName ) +bool wxSheetTable::CanGetValueAs(const wxSheetCoords &coords, const wxString &typeName) { - if ((typeName == wxSHEET_VALUE_NUMBER) || (typeName == wxSHEET_VALUE_CHOICEINT)) - { - const wxString val(GetValue(coords)); - long lval = 0; - return val.ToLong(&lval); - } - else if (typeName == wxSHEET_VALUE_FLOAT) - { - const wxString val(GetValue(coords)); - double dval = 0.0; - return val.ToDouble(&dval); - } - else if (typeName == wxSHEET_VALUE_BOOL) - { - const wxString val(GetValue(coords)); - return val.IsEmpty() || (val == wxT("0")) || (val == wxT("1")) || - (val.CmpNoCase(wxT("f")) == 0) || (val.CmpNoCase(wxT("t")) == 0) || - (val.CmpNoCase(wxT("false")) == 0) || (val.CmpNoCase(wxT("true")) == 0); - } + if ((typeName == wxSHEET_VALUE_NUMBER) || (typeName == wxSHEET_VALUE_CHOICEINT)) { + const wxString val(GetValue(coords)); + long lval = 0; + return val.ToLong(&lval); + } + else if (typeName == wxSHEET_VALUE_FLOAT) { + const wxString val(GetValue(coords)); + double dval = 0.0; + return val.ToDouble(&dval); + } + else if (typeName == wxSHEET_VALUE_BOOL) { + const wxString val(GetValue(coords)); + return val.IsEmpty() || (val == wxT("0")) || (val == wxT("1")) || + (val.CmpNoCase(wxT("f")) == 0) || (val.CmpNoCase(wxT("t")) == 0) || + (val.CmpNoCase(wxT("false")) == 0) || (val.CmpNoCase(wxT("true")) == 0); + } - return typeName == wxSHEET_VALUE_STRING; + return typeName == wxSHEET_VALUE_STRING; } -bool wxSheetTable::CanSetValueAs( const wxSheetCoords& coords, const wxString& typeName ) +bool wxSheetTable::CanSetValueAs(const wxSheetCoords &coords, const wxString &typeName) { - return CanGetValueAs(coords, typeName); + return CanGetValueAs(coords, typeName); } -wxString wxSheetTable::GetTypeName( const wxSheetCoords& ) +wxString wxSheetTable::GetTypeName(const wxSheetCoords &) { - return wxEmptyString; //wxSHEET_VALUE_STRING; + return wxEmptyString; // wxSHEET_VALUE_STRING; } -void wxSheetTable::SetGridCellValueProvider(wxSheetValueProviderBase *gridCellValues, bool is_owner) +void wxSheetTable::SetGridCellValueProvider(wxSheetValueProviderBase *gridCellValues, + bool is_owner) { - if (m_gridCellValues && m_own_grid_cell_values) - delete m_gridCellValues; + if (m_gridCellValues && m_own_grid_cell_values) { + delete m_gridCellValues; + } - m_gridCellValues = gridCellValues; - m_own_grid_cell_values = is_owner; + m_gridCellValues = gridCellValues; + m_own_grid_cell_values = is_owner; } -void wxSheetTable::SetRowLabelValueProvider(wxSheetValueProviderBase *rowLabelValues, bool is_owner) +void wxSheetTable::SetRowLabelValueProvider(wxSheetValueProviderBase *rowLabelValues, + bool is_owner) { - if (m_rowLabelValues && m_own_row_label_values) - delete m_rowLabelValues; + if (m_rowLabelValues && m_own_row_label_values) { + delete m_rowLabelValues; + } - m_rowLabelValues = rowLabelValues; - m_own_row_label_values = is_owner; + m_rowLabelValues = rowLabelValues; + m_own_row_label_values = is_owner; } -void wxSheetTable::SetColLabelValueProvider(wxSheetValueProviderBase *colLabelValues, bool is_owner) +void wxSheetTable::SetColLabelValueProvider(wxSheetValueProviderBase *colLabelValues, + bool is_owner) { - if (m_colLabelValues && m_own_col_label_values) - delete m_colLabelValues; + if (m_colLabelValues && m_own_col_label_values) { + delete m_colLabelValues; + } - m_colLabelValues = colLabelValues; - m_own_col_label_values = is_owner; + m_colLabelValues = colLabelValues; + m_own_col_label_values = is_owner; } -wxSheetCellAttr wxSheetTable::GetAttr( const wxSheetCoords& coords, - wxSheetAttr_Type kind ) +wxSheetCellAttr wxSheetTable::GetAttr(const wxSheetCoords &coords, wxSheetAttr_Type kind) { - // Ok to return nothing - if (GetAttrProvider()) - return GetAttrProvider()->GetAttr(coords, kind); + // Ok to return nothing + if (GetAttrProvider()) { + return GetAttrProvider()->GetAttr(coords, kind); + } - return wxNullSheetCellAttr; + return wxNullSheetCellAttr; } -void wxSheetTable::SetAttr( const wxSheetCoords& coords, - const wxSheetCellAttr& attr, wxSheetAttr_Type kind) +void wxSheetTable::SetAttr(const wxSheetCoords &coords, const wxSheetCellAttr &attr, + wxSheetAttr_Type kind) { - // This is called from the - wxCHECK_RET(GetAttrProvider(), wxT("Invalid attr provider in table")); - GetAttrProvider()->SetAttr(coords, attr, kind); + // This is called from the + wxCHECK_RET(GetAttrProvider(), wxT("Invalid attr provider in table")); + GetAttrProvider()->SetAttr(coords, attr, kind); } void wxSheetTable::SetAttrProvider(wxSheetCellAttrProvider *attrProvider, bool is_owner) { - if (m_attrProvider && m_own_attr_provider) - delete m_attrProvider; + if (m_attrProvider && m_own_attr_provider) { + delete m_attrProvider; + } - m_attrProvider = attrProvider; - m_own_attr_provider = is_owner; + m_attrProvider = attrProvider; + m_own_attr_provider = is_owner; } bool wxSheetTable::HasSpannedCells() { - return GetSpannedBlocks() && (GetSpannedBlocks()->GetCount() != 0u); + return GetSpannedBlocks() && (GetSpannedBlocks()->GetCount() != 0u); } -wxSheetBlock wxSheetTable::GetCellBlock( const wxSheetCoords& coords ) +wxSheetBlock wxSheetTable::GetCellBlock(const wxSheetCoords &coords) { - if (GetSpannedBlocks()) // ok not to have this, just return 1x1 - { - const int n = GetSpannedBlocks()->Index(coords); - if (n != wxNOT_FOUND) - return GetSpannedBlocks()->GetBlock(n); + if (GetSpannedBlocks()) // ok not to have this, just return 1x1 + { + const int n = GetSpannedBlocks()->Index(coords); + if (n != wxNOT_FOUND) { + return GetSpannedBlocks()->GetBlock(n); } - - return wxSheetBlock(coords, 1, 1); -} -void wxSheetTable::SetCellSpan( const wxSheetBlock& block ) -{ - wxCHECK_RET(GetSpannedBlocks(), wxT("Invalid spanned block container")); - wxCHECK_RET(!block.IsEmpty(), wxT("Cannot set cell size smaller than (1,1)")); - wxCHECK_RET((ContainsGridCell(block.GetLeftTop()) && ContainsGridCell(block.GetRightBottom())) || - (ContainsRowLabelCell(block.GetLeftTop()) && ContainsRowLabelCell(block.GetRightBottom())) || - (ContainsColLabelCell(block.GetLeftTop()) && ContainsColLabelCell(block.GetRightBottom())), - wxT("Cannot set cell size for cell out of grid")); - - wxSheetBlock bounds(block); - const wxArraySheetBlock &arrBlock = GetSpannedBlocks()->GetBlockArray(); - int n, index = wxNOT_FOUND, intersections = 0, count = arrBlock.GetCount(); - //int index = wxNOT_FOUND; - - // Check for multiple intersections, one is fine, but topleft corners must match - for (n=0; nGetBlockArray(); + int n, index = wxNOT_FOUND, intersections = 0, count = arrBlock.GetCount(); + // int index = wxNOT_FOUND; + + // Check for multiple intersections, one is fine, but topleft corners must match + for (n = 0; n < count; n++) { + if (arrBlock[n].Intersects(block)) { + intersections++; + index = n; } + } - wxCHECK_RET( (intersections < 2) && - ((intersections == 0) || (arrBlock[index].GetLeftTop() == block.GetLeftTop())), - wxT("Setting cell span for cells already spanned")); + wxCHECK_RET((intersections < 2) && + ((intersections == 0) || (arrBlock[index].GetLeftTop() == block.GetLeftTop())), + wxT("Setting cell span for cells already spanned")); - wxSheetSelection *sel = (wxSheetSelection*)GetSpannedBlocks(); + wxSheetSelection *sel = (wxSheetSelection *)GetSpannedBlocks(); - // delete old block and expand refresh bounds - if (index != wxNOT_FOUND) - { - bounds = bounds.Union(arrBlock[index]); - sel->DeselectBlock(arrBlock[index], false); - } + // delete old block and expand refresh bounds + if (index != wxNOT_FOUND) { + bounds = bounds.Union(arrBlock[index]); + sel->DeselectBlock(arrBlock[index], false); + } - // no need to add a 1x1 block - if ((block.GetWidth() > 1) || (block.GetHeight() > 1)) - { - // don't combine them - sel->SelectBlock(block, false); - } + // no need to add a 1x1 block + if ((block.GetWidth() > 1) || (block.GetHeight() > 1)) { + // don't combine them + sel->SelectBlock(block, false); + } - if (GetView()) GetView()->RefreshGridCellBlock(bounds); + if (GetView()) { + GetView()->RefreshGridCellBlock(bounds); + } } void wxSheetTable::SetSpannedBlocks(wxSheetSelection *spannedCells, bool is_owner) { - if (m_spannedCells && m_own_spanned_cells) - delete m_spannedCells; + if (m_spannedCells && m_own_spanned_cells) { + delete m_spannedCells; + } - m_spannedCells = spannedCells; - m_own_spanned_cells = is_owner; + m_spannedCells = spannedCells; + m_own_spanned_cells = is_owner; } -bool wxSheetTable::UpdateRows( size_t row, int numRows, int update) +bool wxSheetTable::UpdateRows(size_t row, int numRows, int update) { - const int curNumRows = GetNumberRows(); + const int curNumRows = GetNumberRows(); - wxSHEET_CHECKUPDATE_MSG(row, numRows, curNumRows, false); - if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) - GetGridCellValueProvider()->UpdateRows(row, numRows); - if (((update & wxSHEET_UpdateRowLabelValues) != 0) && GetRowLabelValueProvider()) - GetRowLabelValueProvider()->UpdateRows(row, numRows); + wxSHEET_CHECKUPDATE_MSG(row, numRows, curNumRows, false); + if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) { + GetGridCellValueProvider()->UpdateRows(row, numRows); + } + if (((update & wxSHEET_UpdateRowLabelValues) != 0) && GetRowLabelValueProvider()) { + GetRowLabelValueProvider()->UpdateRows(row, numRows); + } - if (((update & wxSHEET_UpdateSpanned) != 0) && GetSpannedBlocks()) - ((wxSheetSelection*)GetSpannedBlocks())->UpdateRows( row, numRows ); - if (((update & wxSHEET_UpdateAttributes) != 0) && GetAttrProvider()) - GetAttrProvider()->UpdateRows( row, numRows, update ); + if (((update & wxSHEET_UpdateSpanned) != 0) && GetSpannedBlocks()) { + ((wxSheetSelection *)GetSpannedBlocks())->UpdateRows(row, numRows); + } + if (((update & wxSHEET_UpdateAttributes) != 0) && GetAttrProvider()) { + GetAttrProvider()->UpdateRows(row, numRows, update); + } - return UpdateSheetRows(row, numRows, update); + return UpdateSheetRows(row, numRows, update); } -bool wxSheetTable::UpdateCols( size_t col, int numCols, int update ) +bool wxSheetTable::UpdateCols(size_t col, int numCols, int update) { - const int curNumCols = GetNumberCols(); + const int curNumCols = GetNumberCols(); - wxSHEET_CHECKUPDATE_MSG(col, numCols, curNumCols, false); - if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) - GetGridCellValueProvider()->UpdateCols(col, numCols); - if (((update & wxSHEET_UpdateColLabelValues) != 0) && GetColLabelValueProvider()) - GetColLabelValueProvider()->UpdateCols(col, numCols); + wxSHEET_CHECKUPDATE_MSG(col, numCols, curNumCols, false); + if (((update & wxSHEET_UpdateGridCellValues) != 0) && GetGridCellValueProvider()) { + GetGridCellValueProvider()->UpdateCols(col, numCols); + } + if (((update & wxSHEET_UpdateColLabelValues) != 0) && GetColLabelValueProvider()) { + GetColLabelValueProvider()->UpdateCols(col, numCols); + } - if (((update & wxSHEET_UpdateSpanned) != 0) && GetSpannedBlocks()) - ((wxSheetSelection*)GetSpannedBlocks())->UpdateCols( col, numCols ); - if (((update & wxSHEET_UpdateAttributes) != 0) && GetAttrProvider()) - GetAttrProvider()->UpdateCols( col, numCols, update ); + if (((update & wxSHEET_UpdateSpanned) != 0) && GetSpannedBlocks()) { + ((wxSheetSelection *)GetSpannedBlocks())->UpdateCols(col, numCols); + } + if (((update & wxSHEET_UpdateAttributes) != 0) && GetAttrProvider()) { + GetAttrProvider()->UpdateCols(col, numCols, update); + } - return UpdateSheetCols(col, numCols, update); + return UpdateSheetCols(col, numCols, update); } -bool wxSheetTable::UpdateSheetRows( size_t row, int numRows, int update ) +bool wxSheetTable::UpdateSheetRows(size_t row, int numRows, int update) { - return GetView() && GetView()->DoUpdateRows(row, numRows, update); + return GetView() && GetView()->DoUpdateRows(row, numRows, update); } -bool wxSheetTable::UpdateSheetCols( size_t col, int numCols, int update ) +bool wxSheetTable::UpdateSheetCols(size_t col, int numCols, int update) { - return GetView() && GetView()->DoUpdateCols(col, numCols, update); + return GetView() && GetView()->DoUpdateCols(col, numCols, update); } bool wxSheetTable::UpdateSheetRowsCols(int update) { - bool done = false; - if (!GetView()) return done; - - const int tableRows = GetNumberRows(); - const int tableCols = GetNumberCols(); - const int sheetRows = GetView()->GetNumberRows(); - const int sheetCols = GetView()->GetNumberCols(); - if (tableRows != sheetRows) - done |= UpdateSheetRows(tableRows < sheetRows ? tableRows : sheetRows, - tableRows - sheetRows, update); - if (tableCols != sheetCols) - done |= UpdateSheetCols(tableCols < sheetCols ? tableCols : sheetCols, - tableCols - sheetCols, update); - + bool done = false; + if (!GetView()) { return done; + } + + const int tableRows = GetNumberRows(); + const int tableCols = GetNumberCols(); + const int sheetRows = GetView()->GetNumberRows(); + const int sheetCols = GetView()->GetNumberCols(); + if (tableRows != sheetRows) { + done |= UpdateSheetRows(tableRows < sheetRows ? tableRows : sheetRows, tableRows - sheetRows, + update); + } + if (tableCols != sheetCols) { + done |= UpdateSheetCols(tableCols < sheetCols ? tableCols : sheetCols, tableCols - sheetCols, + update); + } + + return done; } diff --git a/src/labenski/src/spinctld.cpp b/src/labenski/src/spinctld.cpp index c58d7f743..d8e72d58a 100644 --- a/src/labenski/src/spinctld.cpp +++ b/src/labenski/src/spinctld.cpp @@ -10,38 +10,35 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/valtext.h" // for wxTextValidator - #include "wx/textctrl.h" +#include "wx/valtext.h" // for wxTextValidator +#include "wx/textctrl.h" #endif // WX_PRECOMP #include "wx/wxthings/spinctld.h" #include -#if wxCHECK_VERSION(2,5,0) - #include "wx/math.h" +#if wxCHECK_VERSION(2, 5, 0) +#include "wx/math.h" #else - #if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) - #include - #define wxFinite(x) _finite(x) - #elif defined(__GNUG__)||defined(__GNUWIN32__)||defined(__DJGPP__)|| \ - defined(__SGI_CC__)||defined(__SUNCC__)||defined(__XLC__)|| \ - defined(__HPUX__)||defined(__MWERKS__) - #define wxFinite(x) finite(x) - #else - #define wxFinite(x) ((x) == (x)) - #endif +#if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) +#include +#define wxFinite(x) _finite(x) +#elif defined(__GNUG__) || defined(__GNUWIN32__) || defined(__DJGPP__) || defined(__SGI_CC__) || \ + defined(__SUNCC__) || defined(__XLC__) || defined(__HPUX__) || defined(__MWERKS__) +#define wxFinite(x) finite(x) +#else +#define wxFinite(x) ((x) == (x)) +#endif #endif // wxCHECK_VERSION(2,5,0) #ifdef wxFinite #undef wxFinite #define wxFinite(x) std::isfinite(x) -#endif // wxFinite - - +#endif // wxFinite // NOTES : if the textctrl is focused and the program is ending, a killfocus // event is sent in MSW, this is why m_textCtrl is set to NULL in it's @@ -52,580 +49,626 @@ //---------------------------------------------------------------------------- // the textctrl used for the wxSpinCtrlDbl, needed for keypresses -class wxSpinCtrlDblTextCtrl : public wxTextCtrl -{ +class wxSpinCtrlDblTextCtrl : public wxTextCtrl { public: - wxSpinCtrlDblTextCtrl( wxWindow *parent, wxWindowID id, - const wxString &value = wxEmptyString, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString &name = wxTextCtrlNameStr); - - // MSW sends extra kill focus event - virtual ~wxSpinCtrlDblTextCtrl() - { - if (m_parent) m_parent->m_textCtrl = NULL; - m_parent = NULL; + wxSpinCtrlDblTextCtrl(wxWindow *parent, wxWindowID id, const wxString &value = wxEmptyString, + const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, + long style = 0, const wxValidator &validator = wxDefaultValidator, + const wxString &name = wxTextCtrlNameStr); + + // MSW sends extra kill focus event + virtual ~wxSpinCtrlDblTextCtrl() + { + if (m_parent) { + m_parent->m_textCtrl = NULL; } + m_parent = NULL; + } - wxSpinCtrlDbl *m_parent; + wxSpinCtrlDbl *m_parent; - void OnChar( wxKeyEvent &event ); // pass chars to wxSpinCtrlDbl - void OnKillFocus( wxFocusEvent &event ); // sync the spin to textctrl + void OnChar(wxKeyEvent &event); // pass chars to wxSpinCtrlDbl + void OnKillFocus(wxFocusEvent &event); // sync the spin to textctrl private: - DECLARE_EVENT_TABLE() + DECLARE_EVENT_TABLE() }; -BEGIN_EVENT_TABLE(wxSpinCtrlDblTextCtrl,wxTextCtrl) +BEGIN_EVENT_TABLE(wxSpinCtrlDblTextCtrl, wxTextCtrl) // EVT_TEXT_ENTER( wxID_ANY, wxSpinCtrlDblTextCtrl::OnTextEnter ) // get them from spinctrldbl // EVT_TEXT( wxID_ANY, wxSpinCtrlDblTextCtrl::OnTextUpdate ) // get them from spinctrldbl - EVT_CHAR( wxSpinCtrlDblTextCtrl::OnChar ) - EVT_KILL_FOCUS( wxSpinCtrlDblTextCtrl::OnKillFocus ) +EVT_CHAR(wxSpinCtrlDblTextCtrl::OnChar) +EVT_KILL_FOCUS(wxSpinCtrlDblTextCtrl::OnKillFocus) END_EVENT_TABLE() -wxSpinCtrlDblTextCtrl::wxSpinCtrlDblTextCtrl( wxWindow *parent, wxWindowID id, - const wxString &value, - const wxPoint &pos, const wxSize &size, - long style, - const wxValidator& validator, - const wxString &name) - :wxTextCtrl( parent, id, value, pos, size, style, - validator, name) +wxSpinCtrlDblTextCtrl::wxSpinCtrlDblTextCtrl(wxWindow *parent, wxWindowID id, + const wxString &value, const wxPoint &pos, + const wxSize &size, long style, + const wxValidator &validator, const wxString &name) + : wxTextCtrl(parent, id, value, pos, size, style, validator, name) { - m_parent = (wxSpinCtrlDbl*)parent; + m_parent = (wxSpinCtrlDbl *)parent; } -void wxSpinCtrlDblTextCtrl::OnChar( wxKeyEvent &event ) +void wxSpinCtrlDblTextCtrl::OnChar(wxKeyEvent &event) { - if (m_parent) m_parent->OnChar( event ); + if (m_parent) { + m_parent->OnChar(event); + } } -void wxSpinCtrlDblTextCtrl::OnKillFocus( wxFocusEvent &event ) +void wxSpinCtrlDblTextCtrl::OnKillFocus(wxFocusEvent &event) { - if (m_parent) m_parent->SyncSpinToText(true); - event.Skip(); + if (m_parent) { + m_parent->SyncSpinToText(true); + } + event.Skip(); } //---------------------------------------------------------------------------- // wxSpinCtrlDbl //---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS( wxSpinCtrlDbl, wxControl ) +IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrlDbl, wxControl) -BEGIN_EVENT_TABLE(wxSpinCtrlDbl,wxControl) - EVT_SPIN_UP ( wxID_ANY, wxSpinCtrlDbl::OnSpinUp ) - EVT_SPIN_DOWN ( wxID_ANY, wxSpinCtrlDbl::OnSpinDown ) - EVT_TEXT_ENTER( wxID_ANY, wxSpinCtrlDbl::OnTextEnter ) - //EVT_TEXT ( wxID_ANY, wxSpinCtrlDbl::OnText ) - EVT_SET_FOCUS ( wxSpinCtrlDbl::OnFocus ) - EVT_KILL_FOCUS( wxSpinCtrlDbl::OnKillFocus ) +BEGIN_EVENT_TABLE(wxSpinCtrlDbl, wxControl) +EVT_SPIN_UP(wxID_ANY, wxSpinCtrlDbl::OnSpinUp) +EVT_SPIN_DOWN(wxID_ANY, wxSpinCtrlDbl::OnSpinDown) +EVT_TEXT_ENTER(wxID_ANY, wxSpinCtrlDbl::OnTextEnter) +// EVT_TEXT ( wxID_ANY, wxSpinCtrlDbl::OnText ) +EVT_SET_FOCUS(wxSpinCtrlDbl::OnFocus) +EVT_KILL_FOCUS(wxSpinCtrlDbl::OnKillFocus) END_EVENT_TABLE() void wxSpinCtrlDbl::Init() { - m_min = 0; - m_max = 100; - m_value = 0; - m_default_value = 0; - m_increment = 1; - m_digits = wxSPINCTRLDBL_AUTODIGITS; - m_snap_ticks = false; - m_spinButton = NULL; - m_textCtrl = NULL; + m_min = 0; + m_max = 100; + m_value = 0; + m_default_value = 0; + m_increment = 1; + m_digits = wxSPINCTRLDBL_AUTODIGITS; + m_snap_ticks = false; + m_spinButton = NULL; + m_textCtrl = NULL; } -bool wxSpinCtrlDbl::Create( wxWindow *parent, wxWindowID id, - const wxString& value, - const wxPoint& pos, const wxSize& size, - long style, - double min, double max, - double initial, - double increment, int digits, - const wxString& name) +bool wxSpinCtrlDbl::Create(wxWindow *parent, wxWindowID id, const wxString &value, + const wxPoint &pos, const wxSize &size, long style, double min, + double max, double initial, double increment, int digits, + const wxString &name) { - if (!wxControl::Create(parent, id, pos, size, style|wxNO_BORDER, - wxDefaultValidator, name)) - return false; + if (!wxControl::Create(parent, id, pos, size, style | wxNO_BORDER, wxDefaultValidator, name)) { + return false; + } - wxControl::SetLabel(name); - wxControl::SetBackgroundColour(parent->GetBackgroundColour()); - wxControl::SetForegroundColour(parent->GetForegroundColour()); + wxControl::SetLabel(name); + wxControl::SetBackgroundColour(parent->GetBackgroundColour()); + wxControl::SetForegroundColour(parent->GetForegroundColour()); - int width = size.GetWidth(), height = size.GetHeight(); + int width = size.GetWidth(), height = size.GetHeight(); - wxSize best_size( DoGetBestSize() ); - if (width == -1) width = best_size.GetWidth(); - if (height == -1) height = best_size.GetHeight(); + wxSize best_size(DoGetBestSize()); + if (width == -1) { + width = best_size.GetWidth(); + } + if (height == -1) { + height = best_size.GetHeight(); + } - // Create a validator for numbers, +-, and eE for exponential - wxTextValidator validator(wxFILTER_INCLUDE_CHAR_LIST); + // Create a validator for numbers, +-, and eE for exponential + wxTextValidator validator(wxFILTER_INCLUDE_CHAR_LIST); #if wxCHECK_VERSION(2, 5, 4) - wxArrayString list; + wxArrayString list; - wxString valid_chars(wxT(" 0123456789+-.eE")); - size_t len = valid_chars.Length(); - for (size_t i=0; iGetSize().GetWidth(), height), - wxTE_NOHIDESEL|wxTE_PROCESS_ENTER, validator); + m_spinButton = new wxSpinButton(this, id, wxPoint(0, 0), wxSize(-1, height), + wxSP_ARROW_KEYS | wxSP_VERTICAL | wxSP_WRAP); + m_textCtrl = new wxSpinCtrlDblTextCtrl( + this, id, value, wxPoint(0, 0), wxSize(width - m_spinButton->GetSize().GetWidth(), height), + wxTE_NOHIDESEL | wxTE_PROCESS_ENTER, validator); - DoSetSize( pos.x, pos.y, width, height ); -#if wxCHECK_VERSION(2,7,0) - SetInitialSize(wxSize(width, height)); + DoSetSize(pos.x, pos.y, width, height); +#if wxCHECK_VERSION(2, 7, 0) + SetInitialSize(wxSize(width, height)); #else - SetBestSize(wxSize(width, height)); + SetBestSize(wxSize(width, height)); #endif - m_min = min; - m_max = max; - m_value = initial; - m_default_value = initial; - m_increment = increment; - SetDigits( digits ); - - // set the value here without generating an event - if (!value.IsEmpty()) - m_textCtrl->SetValue(value); - else - m_textCtrl->SetValue(wxString::Format(m_textFormat.c_str(), initial)); - - return true; + m_min = min; + m_max = max; + m_value = initial; + m_default_value = initial; + m_increment = increment; + SetDigits(digits); + + // set the value here without generating an event + if (!value.IsEmpty()) { + m_textCtrl->SetValue(value); + } + else { + m_textCtrl->SetValue(wxString::Format(m_textFormat.c_str(), initial)); + } + + return true; } wxSpinCtrlDbl::~wxSpinCtrlDbl() { - if (m_textCtrl) // null this since MSW sends KILL_FOCUS on deletion - { - m_textCtrl->m_parent = NULL; + if (m_textCtrl) // null this since MSW sends KILL_FOCUS on deletion + { + m_textCtrl->m_parent = NULL; - wxSpinCtrlDblTextCtrl *text = m_textCtrl; - m_textCtrl = NULL; - delete text; - } + wxSpinCtrlDblTextCtrl *text = m_textCtrl; + m_textCtrl = NULL; + delete text; + } - delete m_spinButton; - m_spinButton = NULL; + delete m_spinButton; + m_spinButton = NULL; } -#define wxSPINCTRLDBL_SPIN_WIDTH 15 +#define wxSPINCTRLDBL_SPIN_WIDTH 15 #define wxSPINCTRLDBL_SPIN_HEIGHT 22 void wxSpinCtrlDbl::DoSetSize(int x, int y, int width, int height, int sizeFlags) { - //wxPrintf(wxT("DoSetSize %d, %d %d %d %d %d\n"), GetId(), x, y, width, height, sizeFlags); - - wxSize bestSize( DoGetBestSize() ); - if (width < 0) width = bestSize.GetWidth(); - if (height < 0) height = bestSize.GetHeight(); - - wxWindow::DoSetSize(x, y, width, height, sizeFlags); - - int spinwidth = wxSPINCTRLDBL_SPIN_WIDTH; - int spinheight = wxSPINCTRLDBL_SPIN_HEIGHT; - if (m_spinButton) - m_spinButton->GetSize( &spinwidth, &spinheight ); - -#ifdef __WIN95__ // humm... these used to be different - if (m_textCtrl) m_textCtrl->SetSize( 0, 0, width - spinwidth, height ); - if (m_spinButton) m_spinButton->SetSize( width-spinwidth-2, 0, -1, height ); - //m_textCtrl->SetSize( -3, -3, width - spinwidth, height ); // old wxWin < 2.3.2 - //m_spinButton->SetSize( width-spinwidth-4, -3, -1, height-1 ); + // wxPrintf(wxT("DoSetSize %d, %d %d %d %d %d\n"), GetId(), x, y, width, height, sizeFlags); + + wxSize bestSize(DoGetBestSize()); + if (width < 0) { + width = bestSize.GetWidth(); + } + if (height < 0) { + height = bestSize.GetHeight(); + } + + wxWindow::DoSetSize(x, y, width, height, sizeFlags); + + int spinwidth = wxSPINCTRLDBL_SPIN_WIDTH; + int spinheight = wxSPINCTRLDBL_SPIN_HEIGHT; + if (m_spinButton) { + m_spinButton->GetSize(&spinwidth, &spinheight); + } + +#ifdef __WIN95__ // humm... these used to be different + if (m_textCtrl) { + m_textCtrl->SetSize(0, 0, width - spinwidth, height); + } + if (m_spinButton) { + m_spinButton->SetSize(width - spinwidth - 2, 0, -1, height); + } + // m_textCtrl->SetSize( -3, -3, width - spinwidth, height ); // old wxWin < 2.3.2 + // m_spinButton->SetSize( width-spinwidth-4, -3, -1, height-1 ); #else - if (m_textCtrl) m_textCtrl->SetSize( 0, 0, width - spinwidth, height ); - if (m_spinButton) m_spinButton->SetSize( width-spinwidth, 0, -1, height ); + if (m_textCtrl) { + m_textCtrl->SetSize(0, 0, width - spinwidth, height); + } + if (m_spinButton) { + m_spinButton->SetSize(width - spinwidth, 0, -1, height); + } #endif } -static wxSize s_spinctrl_bestSize(-999,-999); +static wxSize s_spinctrl_bestSize(-999, -999); wxSize wxSpinCtrlDbl::DoGetBestSize() const { - //wxPrintf(wxT("GetBestSize %d\n"), GetId()); - if (s_spinctrl_bestSize.x == -999) - { - wxSpinCtrl spin((wxWindow*)this, wxID_ANY); - s_spinctrl_bestSize = spin.GetBestSize(); - // oops something went wrong, set to reasonable value - if (s_spinctrl_bestSize.GetWidth() < 20) - s_spinctrl_bestSize.SetWidth(95); - if (s_spinctrl_bestSize.GetHeight() < 10) - s_spinctrl_bestSize.SetHeight(wxSPINCTRLDBL_SPIN_HEIGHT); + // wxPrintf(wxT("GetBestSize %d\n"), GetId()); + if (s_spinctrl_bestSize.x == -999) { + wxSpinCtrl spin((wxWindow *)this, wxID_ANY); + s_spinctrl_bestSize = spin.GetBestSize(); + // oops something went wrong, set to reasonable value + if (s_spinctrl_bestSize.GetWidth() < 20) { + s_spinctrl_bestSize.SetWidth(95); } + if (s_spinctrl_bestSize.GetHeight() < 10) { + s_spinctrl_bestSize.SetHeight(wxSPINCTRLDBL_SPIN_HEIGHT); + } + } - return s_spinctrl_bestSize; + return s_spinctrl_bestSize; } void wxSpinCtrlDbl::DoSendEvent() { - wxCommandEvent event( wxEVT_COMMAND_SPINCTRL_UPDATED, GetId() ); - event.SetEventObject( this ); - event.SetInt( (int)(m_value+0.5) ); - if (m_textCtrl) event.SetString( m_textCtrl->GetValue() ); - GetEventHandler()->ProcessEvent( event ); + wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId()); + event.SetEventObject(this); + event.SetInt((int)(m_value + 0.5)); + if (m_textCtrl) { + event.SetString(m_textCtrl->GetValue()); + } + GetEventHandler()->ProcessEvent(event); } -void wxSpinCtrlDbl::OnSpinUp( wxSpinEvent &WXUNUSED(event) ) +void wxSpinCtrlDbl::OnSpinUp(wxSpinEvent &WXUNUSED(event)) { - if (m_textCtrl && m_textCtrl->IsModified() ) - SyncSpinToText(false); + if (m_textCtrl && m_textCtrl->IsModified()) { + SyncSpinToText(false); + } - if ( InRange(m_value + m_increment) ) - { - m_value += m_increment; - SetValue( m_value ); - DoSendEvent(); - } + if (InRange(m_value + m_increment)) { + m_value += m_increment; + SetValue(m_value); + DoSendEvent(); + } } -void wxSpinCtrlDbl::OnSpinDown( wxSpinEvent &WXUNUSED(event) ) +void wxSpinCtrlDbl::OnSpinDown(wxSpinEvent &WXUNUSED(event)) { - if (m_textCtrl && m_textCtrl->IsModified() ) - SyncSpinToText(false); + if (m_textCtrl && m_textCtrl->IsModified()) { + SyncSpinToText(false); + } - if ( InRange(m_value - m_increment) ) - { - m_value -= m_increment; - SetValue( m_value ); - DoSendEvent(); - } + if (InRange(m_value - m_increment)) { + m_value -= m_increment; + SetValue(m_value); + DoSendEvent(); + } } -void wxSpinCtrlDbl::OnTextEnter( wxCommandEvent &event ) +void wxSpinCtrlDbl::OnTextEnter(wxCommandEvent &event) { - SyncSpinToText(true); - event.Skip(); + SyncSpinToText(true); + event.Skip(); } -void wxSpinCtrlDbl::OnText( wxCommandEvent &event ) +void wxSpinCtrlDbl::OnText(wxCommandEvent &event) { - //wxPrintf(wxT("Text '%s'\n"), event.GetString()); fflush(stdout); - event.Skip(); + // wxPrintf(wxT("Text '%s'\n"), event.GetString()); fflush(stdout); + event.Skip(); } -void wxSpinCtrlDbl::OnChar( wxKeyEvent &event ) -{ - double modifier = 1.0; - if ( event.m_shiftDown ) modifier = 2.0; - if ( event.m_controlDown ) modifier *= 10.0; - if ( event.m_altDown ) modifier *= 100.0; - - switch ( event.GetKeyCode() ) - { - case WXK_UP : - { - if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); - SetValue( m_value + m_increment * modifier ); - DoSendEvent(); - break; - } - case WXK_DOWN : - { - if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); - SetValue( m_value - m_increment * modifier ); - DoSendEvent(); - break; - } - case WXK_PAGEUP : - { - if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); - SetValue( m_value + m_increment * 10.0 * modifier ); - DoSendEvent(); - break; - } - case WXK_PAGEDOWN : - { - if (m_textCtrl && m_textCtrl->IsModified()) SyncSpinToText(false); - SetValue( m_value - m_increment * 10.0 * modifier ); - DoSendEvent(); - break; - } - case WXK_SPACE : - { - SetValue(m_value); - event.Skip(false); - break; - } - case WXK_ESCAPE : - { - SetDefaultValue(); - DoSendEvent(); - break; - } - case WXK_TAB : - { - wxNavigationKeyEvent new_event; - new_event.SetEventObject( GetParent() ); - new_event.SetDirection( !event.ShiftDown() ); - // CTRL-TAB changes the (parent) window, i.e. switch notebook page - new_event.SetWindowChange( event.ControlDown() ); - new_event.SetCurrentFocus( this ); - GetParent()->GetEventHandler()->ProcessEvent( new_event ); - break; - } - default : event.Skip(); break; +void wxSpinCtrlDbl::OnChar(wxKeyEvent &event) +{ + double modifier = 1.0; + if (event.m_shiftDown) { + modifier = 2.0; + } + if (event.m_controlDown) { + modifier *= 10.0; + } + if (event.m_altDown) { + modifier *= 100.0; + } + + switch (event.GetKeyCode()) { + case WXK_UP: { + if (m_textCtrl && m_textCtrl->IsModified()) { + SyncSpinToText(false); + } + SetValue(m_value + m_increment * modifier); + DoSendEvent(); + break; + } + case WXK_DOWN: { + if (m_textCtrl && m_textCtrl->IsModified()) { + SyncSpinToText(false); + } + SetValue(m_value - m_increment * modifier); + DoSendEvent(); + break; + } + case WXK_PAGEUP: { + if (m_textCtrl && m_textCtrl->IsModified()) { + SyncSpinToText(false); + } + SetValue(m_value + m_increment * 10.0 * modifier); + DoSendEvent(); + break; + } + case WXK_PAGEDOWN: { + if (m_textCtrl && m_textCtrl->IsModified()) { + SyncSpinToText(false); } + SetValue(m_value - m_increment * 10.0 * modifier); + DoSendEvent(); + break; + } + case WXK_SPACE: { + SetValue(m_value); + event.Skip(false); + break; + } + case WXK_ESCAPE: { + SetDefaultValue(); + DoSendEvent(); + break; + } + case WXK_TAB: { + wxNavigationKeyEvent new_event; + new_event.SetEventObject(GetParent()); + new_event.SetDirection(!event.ShiftDown()); + // CTRL-TAB changes the (parent) window, i.e. switch notebook page + new_event.SetWindowChange(event.ControlDown()); + new_event.SetCurrentFocus(this); + GetParent()->GetEventHandler()->ProcessEvent(new_event); + break; + } + default: + event.Skip(); + break; + } } -void wxSpinCtrlDbl::SetValue( double value ) +void wxSpinCtrlDbl::SetValue(double value) { - if (!m_textCtrl || !InRange(value)) - return; + if (!m_textCtrl || !InRange(value)) { + return; + } - if ( m_snap_ticks && (m_increment != 0) ) + if (m_snap_ticks && (m_increment != 0)) { + double snap_value = (value - m_default_value) / m_increment; + + if (wxFinite(snap_value)) // FIXME what to do about a failure? { - double snap_value = (value - m_default_value) / m_increment; - - if (wxFinite(snap_value)) // FIXME what to do about a failure? - { - if (snap_value - floor(snap_value) < ceil(snap_value) - snap_value) - value = m_default_value + floor(snap_value) * m_increment; - else - value = m_default_value + ceil(snap_value) * m_increment; - } + if (snap_value - floor(snap_value) < ceil(snap_value) - snap_value) { + value = m_default_value + floor(snap_value) * m_increment; + } + else { + value = m_default_value + ceil(snap_value) * m_increment; + } } + } - wxString str(wxString::Format(m_textFormat.c_str(), value)); + wxString str(wxString::Format(m_textFormat.c_str(), value)); - if ((value != m_value) || (str != m_textCtrl->GetValue())) - { - m_textCtrl->SetValue( str ); - m_textCtrl->DiscardEdits(); - m_value = value; - str.ToDouble( &m_value ); // wysiwyg for textctrl - } + if ((value != m_value) || (str != m_textCtrl->GetValue())) { + m_textCtrl->SetValue(str); + m_textCtrl->DiscardEdits(); + m_value = value; + str.ToDouble(&m_value); // wysiwyg for textctrl + } } -void wxSpinCtrlDbl::SetValue( const wxString& text, bool force ) +void wxSpinCtrlDbl::SetValue(const wxString &text, bool force) { - if (!m_textCtrl) return; + if (!m_textCtrl) { + return; + } - double value; - if ( text.ToDouble(&value) ) - SetValue( value ); - else if (force) - { - m_textCtrl->SetValue( text ); - m_textCtrl->DiscardEdits(); - } + double value; + if (text.ToDouble(&value)) { + SetValue(value); + } + else if (force) { + m_textCtrl->SetValue(text); + m_textCtrl->DiscardEdits(); + } } -void wxSpinCtrlDbl::SetRange( double min_val, double max_val ) +void wxSpinCtrlDbl::SetRange(double min_val, double max_val) { - //wxCHECK_RET(max_val > min_val, wxT("invalid spinctrl range")); - m_min = min_val; - m_max = max_val; + // wxCHECK_RET(max_val > min_val, wxT("invalid spinctrl range")); + m_min = min_val; + m_max = max_val; - if (HasRange()) - { - if (m_value > m_max) - SetValue(m_max); - else if (m_value < m_min) - SetValue(m_min); + if (HasRange()) { + if (m_value > m_max) { + SetValue(m_max); } + else if (m_value < m_min) { + SetValue(m_min); + } + } } -void wxSpinCtrlDbl::SetIncrement( double increment ) +void wxSpinCtrlDbl::SetIncrement(double increment) { - m_increment = increment; - SetValue(m_value); + m_increment = increment; + SetValue(m_value); } -void wxSpinCtrlDbl::SetDigits( int digits, formatType fmt ) +void wxSpinCtrlDbl::SetDigits(int digits, formatType fmt) { - wxCHECK_RET(digits >= -1, wxT("invalid spinctrl format")); + wxCHECK_RET(digits >= -1, wxT("invalid spinctrl format")); - if ((digits == wxSPINCTRLDBL_AUTODIGITS) && (fmt != lg_fmt)) - { - wxString wxstr; - int lastplace = -1, extra_digits = 0; - if (fmt == le_fmt) - { - wxstr.Printf(wxT("%le"), m_increment ); - wxstr.LowerCase(); - lastplace = wxstr.Find(wxT('e')) - 2; - long places; - if (wxstr.AfterFirst(wxT('e')).ToLong(&places)) - extra_digits = int(labs(places)); - } - else if (fmt == lf_fmt) - { - wxstr.Printf(wxT("%lf"), m_increment ); - lastplace = wxstr.Len()-1; - } + if ((digits == wxSPINCTRLDBL_AUTODIGITS) && (fmt != lg_fmt)) { + wxString wxstr; + int lastplace = -1, extra_digits = 0; + if (fmt == le_fmt) { + wxstr.Printf(wxT("%le"), m_increment); + wxstr.LowerCase(); + lastplace = wxstr.Find(wxT('e')) - 2; + long places; + if (wxstr.AfterFirst(wxT('e')).ToLong(&places)) { + extra_digits = int(labs(places)); + } + } + else if (fmt == lf_fmt) { + wxstr.Printf(wxT("%lf"), m_increment); + lastplace = wxstr.Len() - 1; + } - int decimalplace = wxstr.Find(wxT('.')); - - int i = 0; - - for ( i=lastplace; i>decimalplace; i-- ) - { - if ( wxstr.GetChar(i) != wxT('0') ) - { - m_digits = extra_digits + i-decimalplace; - switch (fmt) - { - case le_fmt : m_textFormat.Printf(wxT("%%.%dle"), m_digits ); break; - case lf_fmt : - default : m_textFormat.Printf(wxT("%%.%dlg"), m_digits ); break; - } - - SetValue(m_value); - return; - } + int decimalplace = wxstr.Find(wxT('.')); + + int i = 0; + + for (i = lastplace; i > decimalplace; i--) { + if (wxstr.GetChar(i) != wxT('0')) { + m_digits = extra_digits + i - decimalplace; + switch (fmt) { + case le_fmt: + m_textFormat.Printf(wxT("%%.%dle"), m_digits); + break; + case lf_fmt: + default: + m_textFormat.Printf(wxT("%%.%dlg"), m_digits); + break; } - m_digits = 0; // no digits, I guess + SetValue(m_value); + return; + } } - else - m_digits = digits; - switch (fmt) - { - case le_fmt : m_textFormat.Printf(wxT("%%.%dle"), m_digits ); break; - case lg_fmt : - { - if (m_digits == -1) - m_textFormat.Printf(wxT("%%lg") ); - else - m_textFormat.Printf(wxT("%%.%dlg"), m_digits ); - break; - } - case lf_fmt : - default : m_textFormat.Printf(wxT("%%.%dlf"), m_digits ); break; + m_digits = 0; // no digits, I guess + } + else { + m_digits = digits; + } + + switch (fmt) { + case le_fmt: + m_textFormat.Printf(wxT("%%.%dle"), m_digits); + break; + case lg_fmt: { + if (m_digits == -1) { + m_textFormat.Printf(wxT("%%lg")); } - - SetValue(m_value); + else { + m_textFormat.Printf(wxT("%%.%dlg"), m_digits); + } + break; + } + case lf_fmt: + default: + m_textFormat.Printf(wxT("%%.%dlf"), m_digits); + break; + } + + SetValue(m_value); } -void wxSpinCtrlDbl::SetFormat( const wxString& format ) +void wxSpinCtrlDbl::SetFormat(const wxString &format) { - wxString wxstr; - if ( wxstr.Printf(format.c_str(), 123456.123456) > 0 ) - m_textFormat = format; + wxString wxstr; + if (wxstr.Printf(format.c_str(), 123456.123456) > 0) { + m_textFormat = format; + } - SetValue(m_value); + SetValue(m_value); } -void wxSpinCtrlDbl::SetDefaultValue( double default_value ) +void wxSpinCtrlDbl::SetDefaultValue(double default_value) { - if ( InRange(default_value) ) - { - m_default_value = default_value; - SetDefaultValue(); - } + if (InRange(default_value)) { + m_default_value = default_value; + SetDefaultValue(); + } } void wxSpinCtrlDbl::SetSnapToTicks(bool forceTicks) { - if (m_snap_ticks != forceTicks) - { - m_snap_ticks = forceTicks; - SetValue( m_value ); - } + if (m_snap_ticks != forceTicks) { + m_snap_ticks = forceTicks; + SetValue(m_value); + } } -void wxSpinCtrlDbl::OnFocus( wxFocusEvent &event ) +void wxSpinCtrlDbl::OnFocus(wxFocusEvent &event) { - if (m_textCtrl) - m_textCtrl->SetFocus(); // this is to pass TAB navigation + if (m_textCtrl) { + m_textCtrl->SetFocus(); // this is to pass TAB navigation + } - event.Skip(); + event.Skip(); } -void wxSpinCtrlDbl::OnKillFocus( wxFocusEvent &event ) +void wxSpinCtrlDbl::OnKillFocus(wxFocusEvent &event) { - SyncSpinToText(true); - event.Skip(); + SyncSpinToText(true); + event.Skip(); } void wxSpinCtrlDbl::SyncSpinToText(bool send_event, bool force_valid) { - if (!m_textCtrl) - return; + if (!m_textCtrl) { + return; + } - double txt_value; - if ( m_textCtrl->GetValue().ToDouble( &txt_value ) ) - { - if ( force_valid || !HasRange() || InRange(txt_value) ) - { - if (force_valid && HasRange()) - { - if (txt_value > GetMax()) - txt_value = GetMax(); - else if (txt_value < GetMin()) - txt_value = GetMin(); - } - - if (m_value != txt_value) - { - SetValue( txt_value ); - if (send_event) DoSendEvent(); - } + double txt_value; + if (m_textCtrl->GetValue().ToDouble(&txt_value)) { + if (force_valid || !HasRange() || InRange(txt_value)) { + if (force_valid && HasRange()) { + if (txt_value > GetMax()) { + txt_value = GetMax(); } + else if (txt_value < GetMin()) { + txt_value = GetMin(); + } + } + + if (m_value != txt_value) { + SetValue(txt_value); + if (send_event) { + DoSendEvent(); + } + } } - else if (force_valid) - { - // textctrl is out of sync, discard and reset - SetValue(GetValue()); - } + } + else if (force_valid) { + // textctrl is out of sync, discard and reset + SetValue(GetValue()); + } } -bool wxSpinCtrlDbl::SetFont( const wxFont &font ) +bool wxSpinCtrlDbl::SetFont(const wxFont &font) { - if (!m_textCtrl) return false; - return m_textCtrl->SetFont( font ); + if (!m_textCtrl) { + return false; + } + return m_textCtrl->SetFont(font); } wxFont wxSpinCtrlDbl::GetFont() const { - if (!m_textCtrl) return GetFont(); - return m_textCtrl->GetFont(); + if (!m_textCtrl) { + return GetFont(); + } + return m_textCtrl->GetFont(); } -bool wxSpinCtrlDbl::SetBackgroundColour(const wxColour& colour) +bool wxSpinCtrlDbl::SetBackgroundColour(const wxColour &colour) { - if (!m_textCtrl) return wxControl::SetBackgroundColour(colour); - bool ret = false; - ret = m_textCtrl->SetBackgroundColour(colour); - m_textCtrl->Refresh(); // FIXME is this necessary in GTK/OSX - return ret; + if (!m_textCtrl) { + return wxControl::SetBackgroundColour(colour); + } + bool ret = false; + ret = m_textCtrl->SetBackgroundColour(colour); + m_textCtrl->Refresh(); // FIXME is this necessary in GTK/OSX + return ret; } wxColour wxSpinCtrlDbl::GetBackgroundColour() const { - if (!m_textCtrl) return wxControl::GetBackgroundColour(); - return m_textCtrl->GetBackgroundColour(); + if (!m_textCtrl) { + return wxControl::GetBackgroundColour(); + } + return m_textCtrl->GetBackgroundColour(); } -bool wxSpinCtrlDbl::SetForegroundColour(const wxColour& colour) +bool wxSpinCtrlDbl::SetForegroundColour(const wxColour &colour) { - if (!m_textCtrl) return wxControl::SetForegroundColour(colour); - bool ret = false; - ret = m_textCtrl->SetForegroundColour(colour); - m_textCtrl->Refresh(); - return ret; + if (!m_textCtrl) { + return wxControl::SetForegroundColour(colour); + } + bool ret = false; + ret = m_textCtrl->SetForegroundColour(colour); + m_textCtrl->Refresh(); + return ret; } wxColour wxSpinCtrlDbl::GetForegroundColour() const { - if (!m_textCtrl) return wxControl::GetForegroundColour(); - return m_textCtrl->GetForegroundColour(); + if (!m_textCtrl) { + return wxControl::GetForegroundColour(); + } + return m_textCtrl->GetForegroundColour(); } diff --git a/src/labenski/src/toggle.cpp b/src/labenski/src/toggle.cpp index dace2c2fa..4c0ca32ac 100644 --- a/src/labenski/src/toggle.cpp +++ b/src/labenski/src/toggle.cpp @@ -13,16 +13,16 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/control.h" - #include "wx/settings.h" - #include "wx/bitmap.h" - #include "wx/timer.h" - #include "wx/dc.h" - #include "wx/dcclient.h" +#include "wx/control.h" +#include "wx/settings.h" +#include "wx/bitmap.h" +#include "wx/timer.h" +#include "wx/dc.h" +#include "wx/dcclient.h" #endif // WX_PRECOMP #include "wx/tglbtn.h" @@ -32,554 +32,590 @@ // ========================================================================== // wxCustomButton // ========================================================================== -IMPLEMENT_DYNAMIC_CLASS( wxCustomButton, wxControl ) +IMPLEMENT_DYNAMIC_CLASS(wxCustomButton, wxControl) -BEGIN_EVENT_TABLE(wxCustomButton,wxControl) - EVT_MOUSE_EVENTS ( wxCustomButton::OnMouseEvents ) - EVT_PAINT ( wxCustomButton::OnPaint ) - EVT_TIMER ( wxID_ANY, wxCustomButton::OnTimer) - EVT_SIZE ( wxCustomButton::OnSize ) +BEGIN_EVENT_TABLE(wxCustomButton, wxControl) +EVT_MOUSE_EVENTS(wxCustomButton::OnMouseEvents) +EVT_PAINT(wxCustomButton::OnPaint) +EVT_TIMER(wxID_ANY, wxCustomButton::OnTimer) +EVT_SIZE(wxCustomButton::OnSize) END_EVENT_TABLE() wxCustomButton::~wxCustomButton() { - if (HasCapture()) ReleaseMouse(); - if (m_timer) delete m_timer; + if (HasCapture()) { + ReleaseMouse(); + } + if (m_timer) { + delete m_timer; + } } void wxCustomButton::Init() { - m_focused = false; - m_labelMargin = wxSize(4,4); - m_bitmapMargin = wxSize(2,2); - m_down = 0; - m_timer = NULL; - m_eventType = 0; - m_button_style = wxCUSTBUT_TOGGLE|wxCUSTBUT_BOTTOM; + m_focused = false; + m_labelMargin = wxSize(4, 4); + m_bitmapMargin = wxSize(2, 2); + m_down = 0; + m_timer = NULL; + m_eventType = 0; + m_button_style = wxCUSTBUT_TOGGLE | wxCUSTBUT_BOTTOM; } -bool wxCustomButton::Create(wxWindow* parent, wxWindowID id, - const wxString& label, const wxBitmap &bitmap, - const wxPoint& pos, const wxSize& size, - long style, const wxValidator& val, - const wxString& name) +bool wxCustomButton::Create(wxWindow *parent, wxWindowID id, const wxString &label, + const wxBitmap &bitmap, const wxPoint &pos, const wxSize &size, + long style, const wxValidator &val, const wxString &name) { - if (!wxControl::Create(parent,id,pos,size,wxNO_BORDER|wxCLIP_CHILDREN,val,name)) - return false; + if (!wxControl::Create(parent, id, pos, size, wxNO_BORDER | wxCLIP_CHILDREN, val, name)) { + return false; + } - wxControl::SetLabel(label); - wxControl::SetBackgroundColour(parent->GetBackgroundColour()); - wxControl::SetForegroundColour(parent->GetForegroundColour()); - wxControl::SetFont(parent->GetFont()); + wxControl::SetLabel(label); + wxControl::SetBackgroundColour(parent->GetBackgroundColour()); + wxControl::SetForegroundColour(parent->GetForegroundColour()); + wxControl::SetFont(parent->GetFont()); - if (bitmap.Ok()) m_bmpLabel = bitmap; + if (bitmap.Ok()) { + m_bmpLabel = bitmap; + } - if (!SetButtonStyle(style)) return false; + if (!SetButtonStyle(style)) { + return false; + } - wxSize bestSize = DoGetBestSize(); - SetSize(wxSize(size.x<0 ? bestSize.x:size.x, size.y<0 ? bestSize.y:size.y)); -#if wxCHECK_VERSION(2,7,0) - SetInitialSize(GetSize()); + wxSize bestSize = DoGetBestSize(); + SetSize(wxSize(size.x < 0 ? bestSize.x : size.x, size.y < 0 ? bestSize.y : size.y)); +#if wxCHECK_VERSION(2, 7, 0) + SetInitialSize(GetSize()); #else - SetBestSize(GetSize()); + SetBestSize(GetSize()); #endif - CalcLayout(true); - return true; + CalcLayout(true); + return true; } void wxCustomButton::SetValue(bool depressed) { wxCHECK_RET(!(m_button_style & wxCUSTBUT_NOTOGGLE), wxT("can't set button state")); - m_down = depressed ? 1 : 0; - Refresh(false); + m_down = depressed ? 1 : 0; + Refresh(false); } bool wxCustomButton::SetButtonStyle(long style) { - int n_styles = 0; - if ((style & wxCUSTBUT_LEFT) != 0) n_styles++; - if ((style & wxCUSTBUT_RIGHT) != 0) n_styles++; - if ((style & wxCUSTBUT_TOP) != 0) n_styles++; - if ((style & wxCUSTBUT_BOTTOM) != 0) n_styles++; - wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton label position allowed")); - - n_styles = 0; - if ((style & wxCUSTBUT_NOTOGGLE) != 0) n_styles++; - if ((style & wxCUSTBUT_BUTTON) != 0) n_styles++; - if ((style & wxCUSTBUT_TOGGLE) != 0) n_styles++; - if ((style & wxCUSTBUT_BUT_DCLICK_TOG) != 0) n_styles++; - if ((style & wxCUSTBUT_TOG_DCLICK_BUT) != 0) n_styles++; - wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton style allowed")); - - m_button_style = style; - - if ((m_button_style & wxCUSTBUT_BUTTON) != 0) - m_down = 0; + int n_styles = 0; + if ((style & wxCUSTBUT_LEFT) != 0) { + n_styles++; + } + if ((style & wxCUSTBUT_RIGHT) != 0) { + n_styles++; + } + if ((style & wxCUSTBUT_TOP) != 0) { + n_styles++; + } + if ((style & wxCUSTBUT_BOTTOM) != 0) { + n_styles++; + } + wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton label position allowed")); + + n_styles = 0; + if ((style & wxCUSTBUT_NOTOGGLE) != 0) { + n_styles++; + } + if ((style & wxCUSTBUT_BUTTON) != 0) { + n_styles++; + } + if ((style & wxCUSTBUT_TOGGLE) != 0) { + n_styles++; + } + if ((style & wxCUSTBUT_BUT_DCLICK_TOG) != 0) { + n_styles++; + } + if ((style & wxCUSTBUT_TOG_DCLICK_BUT) != 0) { + n_styles++; + } + wxCHECK_MSG(n_styles < 2, false, wxT("Only one wxCustomButton style allowed")); + + m_button_style = style; + + if ((m_button_style & wxCUSTBUT_BUTTON) != 0) { + m_down = 0; + } - CalcLayout(true); - return true; + CalcLayout(true); + return true; } -void wxCustomButton::SetLabel( const wxString &label ) +void wxCustomButton::SetLabel(const wxString &label) { - wxControl::SetLabel(label); - CalcLayout(true); + wxControl::SetLabel(label); + CalcLayout(true); } // sequence of events in GTK is up, dclick, up. -void wxCustomButton::OnMouseEvents(wxMouseEvent& event) +void wxCustomButton::OnMouseEvents(wxMouseEvent &event) { - if (m_button_style & wxCUSTBUT_NOTOGGLE) return; + if (m_button_style & wxCUSTBUT_NOTOGGLE) { + return; + } - if (event.LeftDown() || event.RightDown()) - { - if (!HasCapture()) - CaptureMouse(); // keep depressed until up - - m_down++; - Redraw(); + if (event.LeftDown() || event.RightDown()) { + if (!HasCapture()) { + CaptureMouse(); // keep depressed until up } - else if (event.LeftDClick() || event.RightDClick()) - { - m_down++; // GTK eats second down event - Redraw(); + + m_down++; + Redraw(); + } + else if (event.LeftDClick() || event.RightDClick()) { + m_down++; // GTK eats second down event + Redraw(); + } + else if (event.LeftUp()) { + if (HasCapture()) { + ReleaseMouse(); } - else if (event.LeftUp()) - { - if (HasCapture()) - ReleaseMouse(); - m_eventType = wxEVT_LEFT_UP; + m_eventType = wxEVT_LEFT_UP; -#if wxCHECK_VERSION(2,7,0) - if (wxRect(wxPoint(0,0), GetSize()).Contains(event.GetPosition())) +#if wxCHECK_VERSION(2, 7, 0) + if (wxRect(wxPoint(0, 0), GetSize()).Contains(event.GetPosition())) #else - if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition())) + if (wxRect(wxPoint(0, 0), GetSize()).Inside(event.GetPosition())) #endif - { - if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) - { - m_down = 0; - Redraw(); - SendEvent(); - return; - } - else - { - if (!m_timer) - { - m_timer = new wxTimer(this, m_down+1); - m_timer->Start(200, true); - } - else - { - m_eventType = wxEVT_LEFT_DCLICK; - } - - if ((m_button_style & wxCUSTBUT_TOGGLE) && - (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT)) m_down++; - } + { + if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) { + m_down = 0; + Redraw(); + SendEvent(); + return; + } + else { + if (!m_timer) { + m_timer = new wxTimer(this, m_down + 1); + m_timer->Start(200, true); + } + else { + m_eventType = wxEVT_LEFT_DCLICK; } - Redraw(); + if ((m_button_style & wxCUSTBUT_TOGGLE) && (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT)) { + m_down++; + } + } + } + + Redraw(); + } + else if (event.RightUp()) { + if (HasCapture()) { + ReleaseMouse(); } - else if (event.RightUp()) - { - if (HasCapture()) - ReleaseMouse(); - m_eventType = wxEVT_RIGHT_UP; + m_eventType = wxEVT_RIGHT_UP; -#if wxCHECK_VERSION(2,7,0) - if (wxRect(wxPoint(0,0), GetSize()).Contains(event.GetPosition())) +#if wxCHECK_VERSION(2, 7, 0) + if (wxRect(wxPoint(0, 0), GetSize()).Contains(event.GetPosition())) #else - if (wxRect(wxPoint(0,0), GetSize()).Inside(event.GetPosition())) + if (wxRect(wxPoint(0, 0), GetSize()).Inside(event.GetPosition())) #endif - { - if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) - { - m_down = 0; - Redraw(); - SendEvent(); - return; - } - else - { - m_down++; - - if (!m_timer) - { - m_timer = new wxTimer(this, m_down); - m_timer->Start(250, true); - } - else - { - m_eventType = wxEVT_RIGHT_DCLICK; - } - } - } - + { + if ((m_button_style & wxCUSTBUT_BUTTON) && (m_down > 0)) { + m_down = 0; Redraw(); + SendEvent(); + return; + } + else { + m_down++; + + if (!m_timer) { + m_timer = new wxTimer(this, m_down); + m_timer->Start(250, true); + } + else { + m_eventType = wxEVT_RIGHT_DCLICK; + } + } } - else if (event.Entering()) - { - m_focused = true; - if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) - m_down++; - Redraw(); + Redraw(); + } + else if (event.Entering()) { + m_focused = true; + if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) { + m_down++; } - else if (event.Leaving()) - { - m_focused = false; - if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) - m_down--; - Redraw(); + Redraw(); + } + else if (event.Leaving()) { + m_focused = false; + if ((event.LeftIsDown() || event.RightIsDown()) && HasCapture()) { + m_down--; } + + Redraw(); + } } -void wxCustomButton::OnTimer( wxTimerEvent &event ) +void wxCustomButton::OnTimer(wxTimerEvent &event) { - m_timer->Stop(); - delete m_timer; - m_timer = NULL; + m_timer->Stop(); + delete m_timer; + m_timer = NULL; - // Clean up the button presses - // FIXME - GTK eats second left down for a DClick, who know about the others? - if (m_button_style & wxCUSTBUT_BUTTON) - { - m_down = 0; + // Clean up the button presses + // FIXME - GTK eats second left down for a DClick, who know about the others? + if (m_button_style & wxCUSTBUT_BUTTON) { + m_down = 0; + } + else if (m_button_style & wxCUSTBUT_TOGGLE) { + if (m_eventType == wxEVT_LEFT_UP) { + m_down = event.GetId() % 2 ? 0 : 1; } - else if (m_button_style & wxCUSTBUT_TOGGLE) - { - if (m_eventType == wxEVT_LEFT_UP) - m_down = event.GetId()%2 ? 0 : 1; - else - m_down = event.GetId()%2 ? 1 : 0; + else { + m_down = event.GetId() % 2 ? 1 : 0; } - else if (m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) - { - if (m_eventType == wxEVT_LEFT_DCLICK) - m_down = event.GetId()%2 ? 0 : 1; - else - m_down = event.GetId()%2 ? 1 : 0; + } + else if (m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) { + if (m_eventType == wxEVT_LEFT_DCLICK) { + m_down = event.GetId() % 2 ? 0 : 1; } - else if (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) - { - if (m_eventType == wxEVT_LEFT_UP) - m_down = event.GetId()%2 ? 0 : 1; - else - m_down = event.GetId()%2 ? 1 : 0; + else { + m_down = event.GetId() % 2 ? 1 : 0; } + } + else if (m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) { + if (m_eventType == wxEVT_LEFT_UP) { + m_down = event.GetId() % 2 ? 0 : 1; + } + else { + m_down = event.GetId() % 2 ? 1 : 0; + } + } - Refresh(false); - SendEvent(); + Refresh(false); + SendEvent(); } void wxCustomButton::SendEvent() { - if (((m_button_style & wxCUSTBUT_TOGGLE) && (m_eventType == wxEVT_LEFT_UP)) || - ((m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) && (m_eventType == wxEVT_LEFT_DCLICK)) || - ((m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) && (m_eventType == wxEVT_LEFT_UP))) - { - wxCommandEvent eventOut(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, GetId()); - eventOut.SetInt(m_down%2 ? 1 : 0); - eventOut.SetExtraLong(m_eventType); - eventOut.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventOut); - } - else - { - wxCommandEvent eventOut(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); - eventOut.SetInt(0); - eventOut.SetExtraLong(m_eventType); - eventOut.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventOut); - } + if (((m_button_style & wxCUSTBUT_TOGGLE) && (m_eventType == wxEVT_LEFT_UP)) || + ((m_button_style & wxCUSTBUT_BUT_DCLICK_TOG) && (m_eventType == wxEVT_LEFT_DCLICK)) || + ((m_button_style & wxCUSTBUT_TOG_DCLICK_BUT) && (m_eventType == wxEVT_LEFT_UP))) { + wxCommandEvent eventOut(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, GetId()); + eventOut.SetInt(m_down % 2 ? 1 : 0); + eventOut.SetExtraLong(m_eventType); + eventOut.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventOut); + } + else { + wxCommandEvent eventOut(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); + eventOut.SetInt(0); + eventOut.SetExtraLong(m_eventType); + eventOut.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventOut); + } } wxBitmap wxCustomButton::CreateBitmapDisabled(const wxBitmap &bitmap) const { - wxCHECK_MSG(bitmap.Ok(), wxNullBitmap, wxT("invalid bitmap")); - - unsigned char br = GetBackgroundColour().Red(); - unsigned char bg = GetBackgroundColour().Green(); - unsigned char bb = GetBackgroundColour().Blue(); - - wxImage image = bitmap.ConvertToImage(); - int pos, width = image.GetWidth(), height = image.GetHeight(); - unsigned char *img_data = image.GetData(); - - for (int j=0; j lh ? bh : lh; + if (has_bitmap && has_label) { + lw -= wxMin(m_labelMargin.x, m_bitmapMargin.x); } - if (m_bmpLabel.Ok()) - { - bw = m_bmpLabel.GetWidth() + 2*m_bitmapMargin.x; - bh = m_bmpLabel.GetHeight() + 2*m_bitmapMargin.y; - has_bitmap = true; - } - - if ((m_button_style & wxCUSTBUT_LEFT) || (m_button_style & wxCUSTBUT_RIGHT)) - { - int h = bh > lh ? bh : lh; - if (has_bitmap && has_label) lw -= wxMin(m_labelMargin.x, m_bitmapMargin.x); - return wxSize(lw+bw, h); - } - - int w = bw > lw ? bw : lw; - if (has_bitmap && has_label) lh -= wxMin(m_labelMargin.y, m_bitmapMargin.y); - return wxSize(w, lh+bh); + return wxSize(lw + bw, h); + } + + int w = bw > lw ? bw : lw; + if (has_bitmap && has_label) { + lh -= wxMin(m_labelMargin.y, m_bitmapMargin.y); + } + return wxSize(w, lh + bh); } void wxCustomButton::CalcLayout(bool refresh) { - int w, h; - GetSize(&w,&h); - - int bw = 0, bh = 0; - int lw = 0, lh = 0; - - if (m_bmpLabel.Ok()) // assume they're all the same size - { - bw = m_bmpLabel.GetWidth(); - bh = m_bmpLabel.GetHeight(); - } - wxString label = GetLabel(); - if (!label.IsEmpty()) - { - GetTextExtent(label, &lw, &lh); - } - - // Center the label or bitmap if only one or the other - if (!m_bmpLabel.Ok()) - { - m_bitmapPos = wxPoint(0,0); - m_labelPos = wxPoint((w-lw)/2, (h-lh)/2); - } - else if (label.IsEmpty()) - { - m_bitmapPos = wxPoint((w-bw)/2, (h-bh)/2); - m_labelPos = wxPoint(0,0); - } - else if (m_button_style & wxCUSTBUT_LEFT) - { - int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); - m_labelPos = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_labelMargin.x, (h - lh)/2); - m_bitmapPos = wxPoint(m_labelPos.x + lw + mid_margin, (h - bh)/2); - } - else if (m_button_style & wxCUSTBUT_RIGHT) - { - int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); - m_bitmapPos = wxPoint((w - (bw+lw+m_labelMargin.x+m_bitmapMargin.x+mid_margin))/2 + m_bitmapMargin.x, (h - bh)/2); - m_labelPos = wxPoint(m_bitmapPos.x + bw + mid_margin, (h - lh)/2); - } - else if (m_button_style & wxCUSTBUT_TOP) - { - int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); - m_labelPos = wxPoint((w - lw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_labelMargin.y); - m_bitmapPos = wxPoint((w - bw)/2, m_labelPos.y + lh + mid_margin); - } - else // if (m_button_style & wxCUSTBUT_BOTTOM) DEFAULT - { - int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); - m_bitmapPos = wxPoint((w - bw)/2, (h - (bh+lh+m_labelMargin.y+m_bitmapMargin.y+mid_margin))/2 + m_bitmapMargin.y); - m_labelPos = wxPoint((w - lw)/2, m_bitmapPos.y + bh + mid_margin); - } - - if (refresh) Refresh(false); + int w, h; + GetSize(&w, &h); + + int bw = 0, bh = 0; + int lw = 0, lh = 0; + + if (m_bmpLabel.Ok()) // assume they're all the same size + { + bw = m_bmpLabel.GetWidth(); + bh = m_bmpLabel.GetHeight(); + } + wxString label = GetLabel(); + if (!label.IsEmpty()) { + GetTextExtent(label, &lw, &lh); + } + + // Center the label or bitmap if only one or the other + if (!m_bmpLabel.Ok()) { + m_bitmapPos = wxPoint(0, 0); + m_labelPos = wxPoint((w - lw) / 2, (h - lh) / 2); + } + else if (label.IsEmpty()) { + m_bitmapPos = wxPoint((w - bw) / 2, (h - bh) / 2); + m_labelPos = wxPoint(0, 0); + } + else if (m_button_style & wxCUSTBUT_LEFT) { + int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); + m_labelPos = wxPoint((w - (bw + lw + m_labelMargin.x + m_bitmapMargin.x + mid_margin)) / 2 + + m_labelMargin.x, + (h - lh) / 2); + m_bitmapPos = wxPoint(m_labelPos.x + lw + mid_margin, (h - bh) / 2); + } + else if (m_button_style & wxCUSTBUT_RIGHT) { + int mid_margin = wxMax(m_labelMargin.x, m_bitmapMargin.x); + m_bitmapPos = wxPoint((w - (bw + lw + m_labelMargin.x + m_bitmapMargin.x + mid_margin)) / 2 + + m_bitmapMargin.x, + (h - bh) / 2); + m_labelPos = wxPoint(m_bitmapPos.x + bw + mid_margin, (h - lh) / 2); + } + else if (m_button_style & wxCUSTBUT_TOP) { + int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); + m_labelPos = wxPoint((w - lw) / 2, + (h - (bh + lh + m_labelMargin.y + m_bitmapMargin.y + mid_margin)) / 2 + + m_labelMargin.y); + m_bitmapPos = wxPoint((w - bw) / 2, m_labelPos.y + lh + mid_margin); + } + else // if (m_button_style & wxCUSTBUT_BOTTOM) DEFAULT + { + int mid_margin = wxMax(m_labelMargin.y, m_bitmapMargin.y); + m_bitmapPos = wxPoint((w - bw) / 2, + (h - (bh + lh + m_labelMargin.y + m_bitmapMargin.y + mid_margin)) / 2 + + m_bitmapMargin.y); + m_labelPos = wxPoint((w - lw) / 2, m_bitmapPos.y + bh + mid_margin); + } + + if (refresh) { + Refresh(false); + } } diff --git a/src/pygambit/nash.h b/src/pygambit/nash.h index 4bfb5620a..c6ad0f2f5 100644 --- a/src/pygambit/nash.h +++ b/src/pygambit/nash.h @@ -38,25 +38,23 @@ logit_estimate(std::shared_ptr> p_frequencies) StrategicQREEstimator alg; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); - LogitQREMixedStrategyProfile result = alg.Estimate(start, *p_frequencies, - null_stream, 1000000.0, 1.0); + LogitQREMixedStrategyProfile result = + alg.Estimate(start, *p_frequencies, null_stream, 1000000.0, 1.0); return make_shared(result); } -std::shared_ptr -logit_atlambda(const Game &p_game, double p_lambda) +std::shared_ptr logit_atlambda(const Game &p_game, double p_lambda) { LogitQREMixedStrategyProfile start(p_game); StrategicQREPathTracer alg; NullBuffer null_buffer; std::ostream null_stream(&null_buffer); return make_shared( - alg.SolveAtLambda(start, null_stream, p_lambda, 1.0) - ); + alg.SolveAtLambda(start, null_stream, p_lambda, 1.0)); } -List -logit_principal_branch(const Game &p_game, double p_maxLambda=1000000.0) +List logit_principal_branch(const Game &p_game, + double p_maxLambda = 1000000.0) { LogitQREMixedStrategyProfile start(p_game); StrategicQREPathTracer alg; diff --git a/src/pygambit/util.h b/src/pygambit/util.h index 8e3358968..1ed1d52cb 100644 --- a/src/pygambit/util.h +++ b/src/pygambit/util.h @@ -36,8 +36,7 @@ using namespace std; using namespace Gambit; using namespace Gambit::Nash; -inline Game NewTable(Array *dim) -{ return NewTable(*dim); } +inline Game NewTable(Array *dim) { return NewTable(*dim); } Game ReadGame(char *fn) { @@ -78,23 +77,33 @@ std::string WriteGame(const StrategySupportProfile &p_support) // Create a copy on the heap (via new) of the element at index p_index of // container p_container. -template class C, class T, class X> +template