]> git.tdb.fi Git - poefilter.git/blob - source/choicecondition.h
Correctly merge icon and light beam appearances
[poefilter.git] / source / choicecondition.h
1 #ifndef CHOICECONDITION_H_
2 #define CHOICECONDITION_H_
3
4 #include <msp/core/algorithm.h>
5 #include "condition.h"
6 #include "filter.h"
7
8 template<typename T>
9 class ChoiceCondition: public Condition
10 {
11 public:
12         typedef T Traits;
13         typedef typename Traits::Type Type;
14
15 private:
16         std::vector<Type> values;
17
18 public:
19         ChoiceCondition(Type);
20         ChoiceCondition(const std::vector<Type> &);
21
22         virtual ChoiceCondition<T> *clone() const;
23         virtual bool equals(const Condition &) const;
24         virtual bool can_merge(const Condition &, const CompoundCondition &) const;
25         virtual ChoiceCondition<T> *merge(const std::vector<const Condition *> &, const CompoundCondition &) const;
26         virtual void add_lines(std::list<FilterStatement> &) const;
27 };
28
29
30 struct ClassTraits
31 {
32         typedef std::string Type;
33         static const char *get_keyword() { return "Class"; }
34 };
35
36 typedef ChoiceCondition<ClassTraits> ClassCondition;
37
38
39 struct BaseTypeTraits
40 {
41         typedef std::string Type;
42         static const char *get_keyword() { return "BaseType"; }
43 };
44
45 typedef ChoiceCondition<BaseTypeTraits> BaseTypeCondition;
46
47
48 template<typename T>
49 ChoiceCondition<T>::ChoiceCondition(Type v)
50 {
51         values.push_back(v);
52 }
53
54 template<typename T>
55 ChoiceCondition<T>::ChoiceCondition(const std::vector<Type> &v):
56         values(v)
57 { }
58
59 template<typename T>
60 ChoiceCondition<T> *ChoiceCondition<T>::clone() const
61 {
62         return new ChoiceCondition<T>(values);
63 }
64
65 template<typename T>
66 bool ChoiceCondition<T>::equals(const Condition &other) const
67 {
68         const ChoiceCondition<T> *other_choice = dynamic_cast<const ChoiceCondition<T> *>(&other);
69         if(!other_choice || values.size()!=other_choice->values.size())
70                 return false;
71
72         for(unsigned i=0; i<values.size(); ++i)
73                 if(values[i]!=other_choice->values[i])
74                         return false;
75
76         return true;
77 }
78
79 template<typename T>
80 bool ChoiceCondition<T>::can_merge(const Condition &other, const CompoundCondition &parent) const
81 {
82         return dynamic_cast<const ChoiceCondition<T> *>(&other) && dynamic_cast<const OrCondition *>(&parent);
83 }
84
85 template<typename T>
86 ChoiceCondition<T> *ChoiceCondition<T>::merge(const std::vector<const Condition *> &conditions, const CompoundCondition &parent) const
87 {
88         if(dynamic_cast<const OrCondition *>(&parent) && !conditions.empty())
89         {
90                 ChoiceCondition<T> *result = new ChoiceCondition<T>(std::vector<Type>());
91                 for(std::vector<const Condition *>::const_iterator i=conditions.begin(); i!=conditions.end(); ++i)
92                 {
93                         const std::vector<Type> &v = static_cast<const ChoiceCondition<T> *>(*i)->values;
94                         for(typename std::vector<Type>::const_iterator j=v.begin(); j!=v.end(); ++j)
95                                 if(Msp::find(result->values, *j)==result->values.end())
96                                         result->values.push_back(*j);
97                 }
98                 return result;
99         }
100         else
101                 return 0;
102 }
103
104 template<typename T>
105 void ChoiceCondition<T>::add_lines(std::list<FilterStatement> &st) const
106 {
107         std::string line = Traits::get_keyword();
108         for(typename std::vector<Type>::const_iterator i=values.begin(); i!=values.end(); ++i)
109                 line += Msp::format(" \"%s\"", *i);
110         FilterStatement::add_line(st, line);
111 }
112
113 #endif