Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
magicseteditor
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
magicseteditor
Commits
67c0e51f
Commit
67c0e51f
authored
Jul 09, 2007
by
twanvl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Symbol editor now has constraints on selection, but part list allows selection inside groups.
Added logical 'xor' operator for scripting.
parent
b4d89e6a
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
519 additions
and
287 deletions
+519
-287
src/data/action/symbol.cpp
src/data/action/symbol.cpp
+49
-19
src/data/action/symbol.hpp
src/data/action/symbol.hpp
+23
-7
src/data/symbol.cpp
src/data/symbol.cpp
+22
-11
src/data/symbol.hpp
src/data/symbol.hpp
+30
-22
src/gui/symbol/basic_shape_editor.cpp
src/gui/symbol/basic_shape_editor.cpp
+3
-1
src/gui/symbol/control.cpp
src/gui/symbol/control.cpp
+19
-24
src/gui/symbol/control.hpp
src/gui/symbol/control.hpp
+4
-3
src/gui/symbol/part_list.cpp
src/gui/symbol/part_list.cpp
+180
-101
src/gui/symbol/part_list.hpp
src/gui/symbol/part_list.hpp
+23
-7
src/gui/symbol/select_editor.cpp
src/gui/symbol/select_editor.cpp
+58
-79
src/gui/symbol/select_editor.hpp
src/gui/symbol/select_editor.hpp
+11
-3
src/gui/symbol/window.cpp
src/gui/symbol/window.cpp
+55
-9
src/mse.vcproj
src/mse.vcproj
+12
-0
src/render/symbol/viewer.cpp
src/render/symbol/viewer.cpp
+19
-1
src/script/context.cpp
src/script/context.cpp
+1
-0
src/script/parser.cpp
src/script/parser.cpp
+1
-0
src/script/script.cpp
src/script/script.cpp
+1
-0
src/script/script.hpp
src/script/script.hpp
+1
-0
src/util/window_id.hpp
src/util/window_id.hpp
+7
-0
No files found.
src/data/action/symbol.cpp
View file @
67c0e51f
...
...
@@ -105,6 +105,7 @@ void SymbolPartMatrixAction::transform(SymbolPart& part, const Matrix2D& m) {
// bounds change after transforming
s
->
calculateBounds
();
}
else
if
(
SymbolSymmetry
*
s
=
part
.
isSymbolSymmetry
())
{
s
->
center
=
(
s
->
center
-
center
)
*
m
+
center
;
s
->
handle
=
s
->
handle
*
m
;
}
else
if
(
SymbolGroup
*
g
=
part
.
isSymbolGroup
())
{
FOR_EACH
(
p
,
g
->
parts
)
{
...
...
@@ -280,7 +281,8 @@ void SymbolPartScaleAction::transformPart(SymbolPart& part) {
pnt
->
delta_after
=
pnt
->
delta_after
.
mul
(
scale
);
}
}
else
if
(
SymbolSymmetry
*
s
=
part
.
isSymbolSymmetry
())
{
throw
"TODO"
;
transform
(
s
->
center
);
s
->
handle
.
mul
(
new_size
.
div
(
old_size
));
}
else
if
(
SymbolGroup
*
g
=
part
.
isSymbolGroup
())
{
FOR_EACH
(
p
,
g
->
parts
)
{
transformPart
(
*
p
);
...
...
@@ -450,8 +452,9 @@ void DuplicateSymbolPartsAction::getParts(set<SymbolPartP>& parts) {
// ----------------------------------------------------------------------------- : Reorder symbol parts
ReorderSymbolPartsAction
::
ReorderSymbolPartsAction
(
Symbol
&
symbol
,
size_t
old_position
,
size_t
new_position
)
:
symbol
(
symbol
),
old_position
(
old_position
),
new_position
(
new_position
)
ReorderSymbolPartsAction
::
ReorderSymbolPartsAction
(
SymbolGroup
&
old_parent
,
size_t
old_position
,
SymbolGroup
&
new_parent
,
size_t
new_position
)
:
old_parent
(
&
old_parent
),
new_parent
(
&
new_parent
)
,
old_position
(
old_position
),
new_position
(
new_position
)
{}
String
ReorderSymbolPartsAction
::
getName
(
bool
to_undo
)
const
{
...
...
@@ -459,31 +462,58 @@ String ReorderSymbolPartsAction::getName(bool to_undo) const {
}
void
ReorderSymbolPartsAction
::
perform
(
bool
to_undo
)
{
assert
(
old_position
<
symbol
.
parts
.
size
());
assert
(
new_position
<
symbol
.
parts
.
size
());
SymbolPartP
part
=
symbol
.
parts
.
at
(
old_position
);
symbol
.
parts
.
erase
(
symbol
.
parts
.
begin
()
+
old_position
);
symbol
.
parts
.
insert
(
symbol
.
parts
.
begin
()
+
new_position
,
part
);
// remove from old
assert
(
old_position
<
old_parent
->
parts
.
size
());
SymbolPartP
part
=
old_parent
->
parts
.
at
(
old_position
);
old_parent
->
parts
.
erase
(
old_parent
->
parts
.
begin
()
+
old_position
);
// add to new
assert
(
new_position
<=
new_parent
->
parts
.
size
());
new_parent
->
parts
.
insert
(
new_parent
->
parts
.
begin
()
+
new_position
,
part
);
// next time the other way around
swap
(
old_parent
,
new_parent
);
swap
(
old_position
,
new_position
);
}
UngroupReorderSymbolPartsAction
::
UngroupReorderSymbolPartsAction
(
SymbolGroup
&
group_parent
,
size_t
group_pos
,
SymbolGroup
&
target_parent
,
size_t
target_pos
)
:
group_parent
(
group_parent
),
group_pos
(
group_pos
)
,
target_parent
(
target_parent
),
target_pos
(
target_pos
)
{
group
=
dynamic_pointer_cast
<
SymbolGroup
>
(
group_parent
.
parts
.
at
(
group_pos
));
assert
(
group
);
}
String
UngroupReorderSymbolPartsAction
::
getName
(
bool
to_undo
)
const
{
return
_ACTION_
(
"reorder parts"
);
}
void
UngroupReorderSymbolPartsAction
::
perform
(
bool
to_undo
)
{
if
(
!
to_undo
)
{
group_parent
.
parts
.
erase
(
group_parent
.
parts
.
begin
()
+
group_pos
);
target_parent
.
parts
.
insert
(
target_parent
.
parts
.
begin
()
+
target_pos
,
group
->
parts
.
begin
(),
group
->
parts
.
end
());
}
else
{
target_parent
.
parts
.
erase
(
target_parent
.
parts
.
begin
()
+
target_pos
,
target_parent
.
parts
.
begin
()
+
target_pos
+
group
->
parts
.
size
());
group_parent
.
parts
.
insert
(
group_parent
.
parts
.
begin
()
+
group_pos
,
group
);
}
}
// ----------------------------------------------------------------------------- : Group symbol parts
GroupSymbolPartsActionBase
::
GroupSymbolPartsActionBase
(
Symbol
&
symbol
)
:
symbol
(
symbol
)
GroupSymbolPartsActionBase
::
GroupSymbolPartsActionBase
(
Symbol
Group
&
root
)
:
root
(
root
)
{}
void
GroupSymbolPartsActionBase
::
perform
(
bool
to_undo
)
{
swap
(
symbol
.
parts
,
old_part_list
);
swap
(
root
.
parts
,
old_part_list
);
}
GroupSymbolPartsAction
::
GroupSymbolPartsAction
(
Symbol
&
symbol
,
const
set
<
SymbolPartP
>&
parts
)
:
GroupSymbolPartsActionBase
(
symbol
)
GroupSymbolPartsAction
::
GroupSymbolPartsAction
(
Symbol
Group
&
root
,
const
set
<
SymbolPartP
>&
parts
,
const
SymbolGroupP
&
group
)
:
GroupSymbolPartsActionBase
(
root
)
{
// group parts in the old parts list
bool
done
=
false
;
SymbolGroupP
group
(
new
SymbolGroup
);
group
->
name
=
_
(
"Group"
);
FOR_EACH
(
p
,
symbol
.
parts
)
{
FOR_EACH
(
p
,
root
.
parts
)
{
assert
(
p
!=
group
);
if
(
parts
.
find
(
p
)
!=
parts
.
end
())
{
// add to group instead
group
->
parts
.
push_back
(
p
);
...
...
@@ -502,11 +532,11 @@ String GroupSymbolPartsAction::getName(bool to_undo) const {
return
_ACTION_
(
"group parts"
);
}
UngroupSymbolPartsAction
::
UngroupSymbolPartsAction
(
Symbol
&
symbol
,
const
set
<
SymbolPartP
>&
parts
)
:
GroupSymbolPartsActionBase
(
symbol
)
UngroupSymbolPartsAction
::
UngroupSymbolPartsAction
(
Symbol
Group
&
root
,
const
set
<
SymbolPartP
>&
parts
)
:
GroupSymbolPartsActionBase
(
root
)
{
// break up the parts in the old parts list
FOR_EACH
(
p
,
symbol
.
parts
)
{
FOR_EACH
(
p
,
root
.
parts
)
{
if
(
parts
.
find
(
p
)
!=
parts
.
end
()
&&
p
->
isSymbolGroup
())
{
// break up the group
SymbolGroup
*
g
=
p
->
isSymbolGroup
();
...
...
src/data/action/symbol.hpp
View file @
67c0e51f
...
...
@@ -240,36 +240,52 @@ class DuplicateSymbolPartsAction : public SymbolPartListAction {
/// Change the position of a part in a symbol, by moving a part.
class
ReorderSymbolPartsAction
:
public
SymbolPartListAction
{
public:
ReorderSymbolPartsAction
(
Symbol
&
symbol
,
size_t
old_position
,
size_t
new_position
);
ReorderSymbolPartsAction
(
Symbol
Group
&
old_parent
,
size_t
old_position
,
SymbolGroup
&
new_parent
,
size_t
new_position
);
virtual
String
getName
(
bool
to_undo
)
const
;
virtual
void
perform
(
bool
to_undo
);
private:
Symbol
&
symbol
;
///< Symbol to swap the parts in
Symbol
Group
*
old_parent
,
*
new_parent
;
///< Parents to move from and to
public:
size_t
old_position
,
new_position
;
///< Positions to move from and to
};
/// Break up a single group, and put its contents at a specific position
class
UngroupReorderSymbolPartsAction
:
public
SymbolPartListAction
{
public:
/// Remove all the given groups
UngroupReorderSymbolPartsAction
(
SymbolGroup
&
group_parent
,
size_t
group_pos
,
SymbolGroup
&
target_parent
,
size_t
target_pos
);
virtual
String
getName
(
bool
to_undo
)
const
;
virtual
void
perform
(
bool
to_undo
);
private:
SymbolGroup
&
group_parent
;
size_t
group_pos
;
SymbolGroupP
group
;
///< Group to destroy
SymbolGroup
&
target_parent
;
size_t
target_pos
;
};
// ----------------------------------------------------------------------------- : Group symbol parts
/// Group multiple symbol parts together
class
GroupSymbolPartsActionBase
:
public
SymbolPartListAction
{
public:
GroupSymbolPartsActionBase
(
Symbol
&
symbol
);
GroupSymbolPartsActionBase
(
Symbol
Group
&
root
);
virtual
void
perform
(
bool
to_undo
);
protected:
Symbol
&
symbol
;
///< Symbol
to group stuff in
Symbol
Group
&
root
;
///< Symbol or group
to group stuff in
vector
<
SymbolPartP
>
old_part_list
;
///< Old part list of the symbol
};
/// Group multiple symbol parts together
class
GroupSymbolPartsAction
:
public
GroupSymbolPartsActionBase
{
public:
GroupSymbolPartsAction
(
Symbol
&
symbol
,
const
set
<
SymbolPartP
>&
parts
);
GroupSymbolPartsAction
(
Symbol
Group
&
root
,
const
set
<
SymbolPartP
>&
parts
,
const
SymbolGroupP
&
group
);
virtual
String
getName
(
bool
to_undo
)
const
;
};
...
...
@@ -277,11 +293,11 @@ class GroupSymbolPartsAction : public GroupSymbolPartsActionBase {
/// Break up one or more SymbolGroups
class
UngroupSymbolPartsAction
:
public
GroupSymbolPartsActionBase
{
public:
UngroupSymbolPartsAction
(
Symbol
&
symbol
,
const
set
<
SymbolPartP
>&
groups
);
/// Remove all the given groups
UngroupSymbolPartsAction
(
SymbolGroup
&
root
,
const
set
<
SymbolPartP
>&
groups
);
virtual
String
getName
(
bool
to_undo
)
const
;
};
// ----------------------------------------------------------------------------- : EOF
#endif
src/data/symbol.cpp
View file @
67c0e51f
...
...
@@ -204,7 +204,12 @@ String SymbolSymmetry::typeName() const {
}
SymbolPartP
SymbolSymmetry
::
clone
()
const
{
return
new_intrusive1
<
SymbolSymmetry
>
(
*
this
);
SymbolSymmetryP
part
(
new
SymbolSymmetry
(
*
this
));
// also clone the parts inside
FOR_EACH
(
p
,
part
->
parts
)
{
p
=
p
->
clone
();
}
return
part
;
}
IMPLEMENT_REFLECTION
(
SymbolSymmetry
)
{
...
...
@@ -213,20 +218,16 @@ IMPLEMENT_REFLECTION(SymbolSymmetry) {
REFLECT
(
copies
);
REFLECT
(
center
);
REFLECT
(
handle
);
// Fixes after reading
REFLECT_IF_READING
{
if
(
name
.
empty
())
{
if
(
kind
==
SYMMETRY_REFLECTION
)
{
name
=
_
(
"Mirror"
);
}
else
{
name
=
_
(
"Symmetry"
);
}
}
}
REFLECT
(
parts
);
REFLECT_IF_READING
calculateBoundsNonRec
();
}
// ----------------------------------------------------------------------------- : SymbolGroup
SymbolGroup
::
SymbolGroup
()
{
name
=
capitalize
(
_TYPE_
(
"group"
));
}
String
SymbolGroup
::
typeName
()
const
{
return
_
(
"group"
);
}
...
...
@@ -240,6 +241,14 @@ SymbolPartP SymbolGroup::clone() const {
return
part
;
}
bool
SymbolGroup
::
isAncestor
(
const
SymbolPart
&
that
)
const
{
if
(
this
==
&
that
)
return
true
;
FOR_EACH_CONST
(
p
,
parts
)
{
if
(
p
->
isAncestor
(
that
))
return
true
;
}
return
false
;
}
void
SymbolGroup
::
calculateBounds
()
{
FOR_EACH
(
p
,
parts
)
p
->
calculateBounds
();
calculateBoundsNonRec
();
...
...
@@ -256,12 +265,14 @@ void SymbolGroup::calculateBoundsNonRec() {
IMPLEMENT_REFLECTION
(
SymbolGroup
)
{
REFLECT_BASE
(
SymbolPart
);
REFLECT
(
parts
);
REFLECT_IF_READING
calculateBoundsNonRec
();
}
// ----------------------------------------------------------------------------- : Symbol
IMPLEMENT_REFLECTION
(
Symbol
)
{
REFLECT
(
parts
);
REFLECT_IF_READING
calculateBoundsNonRec
();
}
// ----------------------------------------------------------------------------- : Default symbol
...
...
src/data/symbol.hpp
View file @
67c0e51f
...
...
@@ -133,6 +133,10 @@ class SymbolPart : public IntrusivePtrVirtualBase {
virtual
SymbolGroup
*
isSymbolGroup
()
{
return
nullptr
;
}
virtual
const
SymbolGroup
*
isSymbolGroup
()
const
{
return
nullptr
;
}
/// Does this part contain another?
/** also true if this==that*/
virtual
bool
isAncestor
(
const
SymbolPart
&
that
)
const
{
return
this
==
&
that
;
}
/// Calculate the position and size of the part (min_pos and max_pos)
virtual
void
calculateBounds
();
...
...
@@ -191,6 +195,30 @@ class SymbolShape : public SymbolPart {
DECLARE_REFLECTION
();
};
// ----------------------------------------------------------------------------- : SymbolGroup
/// A group of symbol parts
class
SymbolGroup
:
public
SymbolPart
{
public:
vector
<
SymbolPartP
>
parts
;
///< The parts in this group, first item is on top
SymbolGroup
();
virtual
String
typeName
()
const
;
virtual
SymbolPartP
clone
()
const
;
virtual
int
icon
()
const
{
return
SYMBOL_COMBINE_BORDER
+
3
;
}
virtual
SymbolGroup
*
isSymbolGroup
()
{
return
this
;
}
virtual
const
SymbolGroup
*
isSymbolGroup
()
const
{
return
this
;
}
virtual
bool
isAncestor
(
const
SymbolPart
&
that
)
const
;
virtual
void
calculateBounds
();
/// re-calculate the bounds, but not of the contained parts
void
calculateBoundsNonRec
();
DECLARE_REFLECTION
();
};
// ----------------------------------------------------------------------------- : SymbolSymmetry
enum
SymbolSymmetryType
...
...
@@ -198,9 +226,9 @@ enum SymbolSymmetryType
,
SYMMETRY_REFLECTION
};
/// A mirror, reflecting
part of the symbol
/// A mirror, reflecting
the part of the symbol in the group
/** Can handle rotation symmetry with any number of reflections */
class
SymbolSymmetry
:
public
Symbol
Part
{
class
SymbolSymmetry
:
public
Symbol
Group
{
public:
SymbolSymmetryType
kind
;
///< What kind of symmetry
int
copies
;
///< How many times is the orignal reflected (including the original itself)
...
...
@@ -219,26 +247,6 @@ class SymbolSymmetry : public SymbolPart {
DECLARE_REFLECTION
();
};
// ----------------------------------------------------------------------------- : SymbolGroup
/// A group of symbol parts
class
SymbolGroup
:
public
SymbolPart
{
public:
vector
<
SymbolPartP
>
parts
;
///< The parts in this group, first item is on top
virtual
String
typeName
()
const
;
virtual
SymbolPartP
clone
()
const
;
virtual
int
icon
()
const
{
return
SYMMETRY_REFLECTION
+
1
;
}
virtual
SymbolGroup
*
isSymbolGroup
()
{
return
this
;
}
virtual
const
SymbolGroup
*
isSymbolGroup
()
const
{
return
this
;
}
virtual
void
calculateBounds
();
/// re-calculate the bounds, but not of the contained parts
void
calculateBoundsNonRec
();
DECLARE_REFLECTION
();
};
// ----------------------------------------------------------------------------- : Symbol
/// An editable symbol, consists of any number of SymbolParts
...
...
src/gui/symbol/basic_shape_editor.cpp
View file @
67c0e51f
...
...
@@ -28,7 +28,7 @@ SymbolBasicShapeEditor::SymbolBasicShapeEditor(SymbolControl* control)
void
SymbolBasicShapeEditor
::
draw
(
DC
&
dc
)
{
// highlight the part we are drawing
if
(
drawing
)
{
if
(
shape
)
{
control
.
highlightPart
(
dc
,
*
shape
,
HIGHLIGHT_BORDER
);
}
}
...
...
@@ -64,6 +64,7 @@ void SymbolBasicShapeEditor::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
delete
sides
;
delete
sidesL
;
#endif
stopActions
();
// set status text
}
void
SymbolBasicShapeEditor
::
onUpdateUI
(
wxUpdateUIEvent
&
ev
)
{
...
...
@@ -80,6 +81,7 @@ void SymbolBasicShapeEditor::onCommand(int id) {
if
(
id
>=
ID_SHAPE
&&
id
<
ID_SHAPE_MAX
)
{
// change shape mode
mode
=
id
;
stopActions
();
}
}
...
...
src/gui/symbol/control.cpp
View file @
67c0e51f
...
...
@@ -12,6 +12,7 @@
#include <gui/symbol/select_editor.hpp>
#include <gui/symbol/point_editor.hpp>
#include <gui/symbol/basic_shape_editor.hpp>
#include <gui/symbol/symmetry_editor.hpp>
#include <gui/util.hpp>
#include <data/action/symbol.hpp>
#include <data/settings.hpp>
...
...
@@ -36,7 +37,7 @@ void SymbolControl::switchEditor(const SymbolEditorBaseP& e) {
}
void
SymbolControl
::
onChangeSymbol
()
{
selected_parts
.
clear
(
);
selected_parts
.
setSymbol
(
symbol
);
switchEditor
(
new_intrusive2
<
SymbolSelectEditor
>
(
this
,
false
));
Refresh
(
false
);
}
...
...
@@ -51,7 +52,7 @@ void SymbolControl::onModeChange(wxCommandEvent& ev) {
break
;
case
ID_MODE_POINTS
:
if
(
selected_parts
.
size
()
==
1
)
{
selected_shape
=
dynamic_pointer_cast
<
SymbolShape
>
(
*
selected_parts
.
begin
()
);
selected_shape
=
selected_parts
.
getAShape
(
);
if
(
selected_shape
)
{
switchEditor
(
new_intrusive2
<
SymbolPointEditor
>
(
this
,
selected_shape
));
}
...
...
@@ -64,6 +65,9 @@ void SymbolControl::onModeChange(wxCommandEvent& ev) {
}
switchEditor
(
new_intrusive1
<
SymbolBasicShapeEditor
>
(
this
));
break
;
case
ID_MODE_SYMMETRY
:
switchEditor
(
new_intrusive1
<
SymbolSymmetryEditor
>
(
this
));
break
;
}
}
...
...
@@ -92,25 +96,17 @@ void SymbolControl::onUpdateSelection() {
switch
(
editor
->
modeToolId
())
{
case
ID_MODE_POINTS
:
{
// can only select a single part!
if
(
selected_parts
.
size
()
>
1
)
{
// TODO: find a part that is a shape
SymbolPartP
part
=
*
selected_parts
.
begin
();
selected_parts
.
clear
();
selected_parts
.
insert
(
part
);
signalSelectionChange
();
}
else
if
(
selected_parts
.
empty
())
{
selected_parts
.
insert
(
selected_shape
);
signalSelectionChange
();
break
;
}
SymbolShapeP
shape
=
dynamic_pointer_cast
<
SymbolShape
>
(
*
selected_parts
.
begin
());
SymbolShapeP
shape
=
selected_parts
.
getAShape
();
if
(
!
shape
)
{
selected_parts
.
clear
();
selected_parts
.
insert
(
selected_shape
);
signalSelectionChange
();
if
(
selected_parts
.
select
(
selected_shape
))
{
signalSelectionChange
(
);
}
break
;
}
if
(
shape
!=
selected_shape
)
{
if
(
selected_parts
.
select
(
shape
))
{
signalSelectionChange
();
}
// begin editing another part
selected_shape
=
shape
;
editor
=
new_intrusive2
<
SymbolPointEditor
>
(
this
,
selected_shape
);
...
...
@@ -131,16 +127,14 @@ void SymbolControl::onUpdateSelection() {
}
void
SymbolControl
::
selectPart
(
const
SymbolPartP
&
part
)
{
selected_parts
.
clear
();
selected_parts
.
insert
(
part
);
selected_parts
.
select
(
part
);
switchEditor
(
new_intrusive2
<
SymbolSelectEditor
>
(
this
,
false
));
signalSelectionChange
();
}
void
SymbolControl
::
activatePart
(
const
SymbolPartP
&
part
)
{
if
(
part
->
isSymbolShape
())
{
selected_parts
.
clear
();
selected_parts
.
insert
(
part
);
selected_parts
.
select
(
part
);
switchEditor
(
new_intrusive2
<
SymbolPointEditor
>
(
this
,
static_pointer_cast
<
SymbolShape
>
(
part
)));
}
}
...
...
@@ -247,11 +241,12 @@ void SymbolControl::onSize(wxSizeEvent& ev) {
void
SymbolControl
::
onUpdateUI
(
wxUpdateUIEvent
&
ev
)
{
if
(
!
editor
)
return
;
switch
(
ev
.
GetId
())
{
case
ID_MODE_SELECT
:
case
ID_MODE_ROTATE
:
case
ID_MODE_POINTS
:
case
ID_MODE_SHAPES
:
//case ID_MODE_PAINT:
case
ID_MODE_SELECT
:
case
ID_MODE_ROTATE
:
case
ID_MODE_POINTS
:
case
ID_MODE_SHAPES
:
case
ID_MODE_SYMMETRY
:
//case ID_MODE_PAINT:
ev
.
Check
(
editor
->
modeToolId
()
==
ev
.
GetId
());
if
(
ev
.
GetId
()
==
ID_MODE_POINTS
)
{
// can only edit points when a s
ingle part is selected <TODO?>
ev
.
Enable
(
selected_parts
.
size
()
==
1
&&
(
*
selected_parts
.
begin
())
->
isSymbol
Shape
());
// can only edit points when a s
hape is available
ev
.
Enable
(
selected_parts
.
getA
Shape
());
}
break
;
case
ID_MODE_PAINT
:
...
...
src/gui/symbol/control.hpp
View file @
67c0e51f
...
...
@@ -11,6 +11,7 @@
#include <util/prec.hpp>
#include <data/symbol.hpp>
#include <gui/symbol/selection.hpp>
#include <render/symbol/viewer.hpp>
class
SymbolWindow
;
...
...
@@ -71,9 +72,9 @@ class SymbolControl : public wxControl, public SymbolViewer {
public:
/// What parts are selected?
set
<
SymbolPartP
>
selected_parts
;
SymbolPartP
highlight_part
;
///< part the mouse cursor is over
SymbolShapeP
selected_shape
;
///< if there is a single selection
SymbolPartsSelection
selected_parts
;
SymbolPartP
highlight_part
;
///< part the mouse cursor is over
SymbolShapeP
selected_shape
;
///< if there is a single selection
/// Parent window
SymbolWindow
*
parent
;
...
...
src/gui/symbol/part_list.cpp
View file @
67c0e51f
...
...
@@ -7,10 +7,12 @@
// ----------------------------------------------------------------------------- : Includes
#include <gui/symbol/part_list.hpp>
#include <gui/symbol/selection.hpp>
#include <gui/util.hpp>
#include <data/action/symbol.hpp>
#include <gfx/gfx.hpp>
#include <render/symbol/filter.hpp>
#include <util/error.hpp>
#include <wx/dcbuffer.h>
#include <wx/caret.h>
...
...
@@ -24,11 +26,12 @@ DEFINE_EVENT_TYPE(EVENT_PART_ACTIVATE);
// ----------------------------------------------------------------------------- : SymbolPartList
SymbolPartList
::
SymbolPartList
(
Window
*
parent
,
int
id
,
set
<
SymbolPartP
>
&
selection
,
SymbolP
symbol
)
SymbolPartList
::
SymbolPartList
(
Window
*
parent
,
int
id
,
SymbolPartsSelection
&
selection
,
SymbolP
symbol
)
:
wxScrolledWindow
(
parent
,
id
,
wxDefaultPosition
,
wxDefaultSize
,
wxSUNKEN_BORDER
|
wxVSCROLL
)
,
selection
(
selection
)
,
state_icons
(
9
,
8
)
{
SetScrollRate
(
0
,
ITEM_HEIGHT
+
1
);
// NOTE: this is based on the order of the SymbolShapeCombine and SymbolSymmetryType enums!
state_icons
.
Add
(
load_resource_image
(
_
(
"icon_combine_merge"
)));
state_icons
.
Add
(
load_resource_image
(
_
(
"icon_combine_subtract"
)));
...
...
@@ -69,7 +72,7 @@ void SymbolPartList::onAction(const Action& action, bool undone) {
TYPE_CASE_
(
action
,
SymbolPartAction
)
{
symbol_preview
.
up_to_date
=
false
;
// some part changed, but we don't know which one, assume it is the selection
updateParts
(
selection
);
updateParts
(
selection
.
get
()
);
return
;
}
}
...
...
@@ -84,7 +87,7 @@ wxSize SymbolPartList::DoGetBestSize() const {
void
SymbolPartList
::
update
()
{
// count items
number_of_items
=
childCount
(
symbol
);
SetVirtualSize
(
110
,
number_of_items
*
(
ITEM_HEIGHT
+
1
));
SetVirtualSize
(
110
,
number_of_items
*
(
ITEM_HEIGHT
+
1
));
// invalidate previews
symbol_preview
.
up_to_date
=
false
;
for
(
size_t
i
=
0
;
i
<
part_previews
.
size
()
;
++
i
)
{
...
...
@@ -118,23 +121,19 @@ void SymbolPartList::updatePart(const set<SymbolPartP>& parts, int& i, bool pare
// ----------------------------------------------------------------------------- : Events
void
SymbolPartList
::
onLeftDown
(
wxMouseEvent
&
ev
)
{
int
top
;
GetViewStart
(
0
,
&
top
);
// find item under cursor
if
(
ev
.
GetX
()
<
0
||
ev
.
GetX
()
>=
GetClientSize
().
x
)
return
;
SymbolPartP
part
=
findItem
(
ev
.
GetY
()
/
(
ITEM_HEIGHT
+
1
));
int
pos
=
top
+
ev
.
GetY
()
/
(
ITEM_HEIGHT
+
1
);
SymbolPartP
part
=
findItem
(
pos
,
ev
.
GetX
());
if
(
part
)
{
// toggle/select
if
(
!
ev
.
ShiftDown
())
{
selection
.
clear
();
}
if
(
selection
.
find
(
part
)
!=
selection
.
end
())
{
selection
.
erase
(
part
);
}
else
{
selection
.
insert
(
part
);
}
if
(
!
ev
.
ShiftDown
())
{
selection
.
select
(
part
,
ev
.
ShiftDown
()
?
SELECT_TOGGLE
:
SELECT_OVERRIDE
);
if
(
!
ev
.
ShiftDown
()
&&
selection
.
selected
(
part
))
{
// drag item
mouse_down_on
=
part
;
drop_position
=
-
1
;
drag
=
part
;
findParent
(
*
part
,
drag_parent
,
drag_position
);
drop_parent
=
SymbolGroupP
();
CaptureMouse
();
}
sendEvent
(
EVENT_PART_SELECT
);
...
...
@@ -144,43 +143,65 @@ void SymbolPartList::onLeftDown(wxMouseEvent& ev) {
}
void
SymbolPartList
::
onLeftUp
(
wxMouseEvent
&
ev
)
{
if
(
HasCapture
())
ReleaseMouse
();
if
(
mouse_down_on
&&
drop_position
!=
-
1
)
{
if
(
drag_parent
&&
drop_parent
)
{
// move part
// find old position
vector
<
SymbolPartP
>::
const_iterator
it
=
find
(
symbol
->
parts
.
begin
(),
symbol
->
parts
.
end
(),
mouse_down_on
);
mouse_down_on
=
SymbolPartP
();
if
(
it
==
symbol
->
parts
.
end
())
{
Refresh
(
false
);
return
;
}
size_t
old_position
=
it
-
symbol
->
parts
.
begin
();
// find new position
size_t
new_position
;
SymbolPartP
drop_before
=
findItem
(
drop_position
);
it
=
find
(
symbol
->
parts
.
begin
(),
symbol
->
parts
.
end
(),
drop_before
);
if
(
it
==
symbol
->
parts
.
end
())
{
new_position
=
number_of_items
-
1
;
}
else
{
new_position
=
it
-
symbol
->
parts
.
begin
();
if
(
old_position
<
new_position
)
new_position
-=
1
;
if
(
drag_parent
==
drop_parent
&&
drag_position
<
drop_position
)
{
drop_position
-=
1
;
// adjust for removal of the dragged part
}
// move part
if
(
old_position
!=
new_position
)
{
symbol
->
actions
.
add
(
new
ReorderSymbolPartsAction
(
*
symbol
,
old_position
,
new_position
));
SymbolGroupP
par
=
drag_parent
;
drag_parent
=
SymbolGroupP
();
if
(
par
!=
drop_parent
||
drag_position
!=
drop_position
)
{
if
(
par
!=
drop_parent
&&
par
->
parts
.
size
()
==
1
&&
!
par
->
isSymbolSymmetry
())
{
// this leaves a group without elements, remove it
findParent
(
*
par
,
par
,
drag_position
);
// parent of the group
symbol
->
actions
.
add
(
new
UngroupReorderSymbolPartsAction
(
*
par
,
drag_position
,
*
drop_parent
,
drop_position
));
}
else
{
symbol
->
actions
.
add
(
new
ReorderSymbolPartsAction
(
*
par
,
drag_position
,
*
drop_parent
,
drop_position
));
}
}
else
{
Refresh
(
false
);
}
}
else
{
mouse_down_on
=
SymbolPart
P
();
drag_parent
=
SymbolGroup
P
();
}
}
void
SymbolPartList
::
onMotion
(
wxMouseEvent
&
ev
)
{
if
(
mouse_down_on
)
{
int
new_drop_position
=
(
ev
.
GetY
()
+
ITEM_HEIGHT
/
2
)
/
(
ITEM_HEIGHT
+
1
);
if
(
new_drop_position
<
0
||
new_drop_position
>
number_of_items
)
new_drop_position
=
-
1
;
// TODO: make sure it is not in a group
if
(
drop_position
!=
new_drop_position
)
{
drop_position
=
new_drop_position
;
int
top
;
GetViewStart
(
0
,
&
top
);
if
(
drag_parent
)
{
int
pos
=
top
+
(
ev
.
GetY
()
+
ITEM_HEIGHT
/
2
)
/
(
ITEM_HEIGHT
+
1
);
if
(
pos
<
0
)
pos
=
0
;
if
(
pos
>=
number_of_items
)
pos
=
number_of_items
;
bool
before
=
ev
.
GetY
()
<
(
pos
-
top
)
*
(
ITEM_HEIGHT
+
1
);
// old stuff
SymbolGroupP
old_drop_parent
=
drop_parent
;
size_t
old_drop_position
=
drop_position
;
bool
old_drop_inside
=
drop_inside
;
// find drop target
drop_parent
=
SymbolGroupP
();
findDropTarget
(
symbol
,
pos
,
before
);
// the drop parent must be an ancestor or sibling of ancestor of the drag_parent
// i.e. the drop parent's parent must be an ancestor of drag_parent
if
(
drop_parent
)
{
drop_inside
=
!
drop_parent
->
isAncestor
(
*
drag_parent
);
while
(
drop_parent
!=
symbol
)
{
// is drop_parent a sibling of an ancestor of drag_parent?
SymbolGroupP
drop_parent_parent
;
size_t
drop_parent_position
;
findParent
(
*
drop_parent
,
drop_parent_parent
,
drop_parent_position
);
if
(
!
drop_parent_parent
->
isAncestor
(
*
drag_parent
))
{
// move up one level
drop_parent
=
drop_parent_parent
;
drop_position
=
drop_parent_position
;
}
else
{
break
;
}
}
if
(
drop_parent
==
symbol
)
{
drop_inside
=
false
;
}
}
// refresh?
if
(
drop_parent
!=
old_drop_parent
||
drop_position
!=
old_drop_position
||
drop_inside
!=
old_drop_inside
)
{
Refresh
(
false
);
}
}
...
...
@@ -262,26 +283,76 @@ void SymbolPartList::sendEvent(int type) {
// ----------------------------------------------------------------------------- : Items
SymbolPartP
SymbolPartList
::
findItem
(
int
i
)
const
{
SymbolPartP
SymbolPartList
::
findItem
(
int
i
,
int
x
)
const
{
FOR_EACH
(
p
,
symbol
->
parts
)
{
SymbolPartP
f
=
findItem
(
i
,
p
);
SymbolPartP
f
=
findItem
(
i
,
x
,
p
);
if
(
f
)
return
f
;
}
return
SymbolPartP
();
}
SymbolPartP
SymbolPartList
::
findItem
(
int
&
i
,
const
SymbolPartP
&
part
)
{
SymbolPartP
SymbolPartList
::
findItem
(
int
&
i
,
int
x
,
const
SymbolPartP
&
part
)
{
if
(
i
<
0
)
return
SymbolPartP
();
if
(
i
==
0
)
return
part
;
i
-=
1
;
// sub item?
if
(
SymbolGroup
*
g
=
part
->
isSymbolGroup
())
{
FOR_EACH
(
p
,
g
->
parts
)
{
if
(
findItem
(
i
,
p
))
return
part
;
SymbolPartP
f
=
findItem
(
i
,
x
-
5
,
p
);
if
(
f
)
return
x
<
5
?
part
:
f
;
// clicked on bar at the left of group?
}
}
return
SymbolPartP
();
}
void
SymbolPartList
::
findParent
(
const
SymbolPart
&
of
,
SymbolGroupP
&
parent_out
,
size_t
&
pos_out
)
{
if
(
!
findParent
(
of
,
symbol
,
parent_out
,
pos_out
))
{
throw
InternalError
(
_
(
"Symbol part without a parent"
));
}
}
bool
SymbolPartList
::
findParent
(
const
SymbolPart
&
of
,
const
SymbolGroupP
&
g
,
SymbolGroupP
&
parent_out
,
size_t
&
pos_out
)
{
if
(
!
g
)
return
false
;
for
(
size_t
i
=
0
;
i
<
g
->
parts
.
size
()
;
++
i
)
{
if
(
g
->
parts
[
i
].
get
()
==
&
of
)
{
parent_out
=
g
;
pos_out
=
i
;
return
true
;
}
if
(
findParent
(
of
,
dynamic_pointer_cast
<
SymbolGroup
>
(
g
->
parts
[
i
]),
parent_out
,
pos_out
))
return
true
;
}
return
false
;
}
bool
SymbolPartList
::
findDropTarget
(
const
SymbolPartP
&
parent
,
int
&
i
,
bool
before
)
{
if
(
parent
!=
symbol
)
--
i
;
if
(
SymbolGroup
*
g
=
parent
->
isSymbolGroup
())
{
size_t
pos
=
0
;
FOR_EACH
(
p
,
g
->
parts
)
{
if
(
i
<=
0
)
{
// drop before this part
drop_parent
=
static_pointer_cast
<
SymbolGroup
>
(
parent
);
drop_position
=
pos
;
return
true
;
}
if
(
p
==
drag
)
{
i
-=
childCount
(
p
)
+
1
;
// don't drop inside
}
else
{
if
(
findDropTarget
(
p
,
i
,
before
))
{
return
true
;
}
}
++
pos
;
}
if
(
i
<=
0
&&
(
parent
==
symbol
||
before
))
{
// drop at the end
drop_parent
=
static_pointer_cast
<
SymbolGroup
>
(
parent
);
drop_position
=
g
->
parts
.
size
();
return
true
;
}
}
return
false
;
}
int
SymbolPartList
::
childCount
(
const
SymbolPartP
&
part
)
{
if
(
SymbolGroup
*
g
=
part
->
isSymbolGroup
())
{
int
count
=
0
;
...
...
@@ -292,9 +363,6 @@ int SymbolPartList::childCount(const SymbolPartP& part) {
}
}
// ----------------------------------------------------------------------------- : Text editor
// ----------------------------------------------------------------------------- : Drawing
...
...
@@ -307,23 +375,13 @@ void SymbolPartList::OnDraw(DC& dc) {
// init
dc
.
SetFont
(
*
wxNORMAL_FONT
);
// clear background
wxSize
size
=
GetClientSize
(
);
wxSize
size
=
piecewise_max
(
GetVirtualSize
()
+
RealSize
(
0
,
ITEM_HEIGHT
+
1
),
GetClientSize
()
);
dc
.
SetPen
(
*
wxTRANSPARENT_PEN
);
dc
.
SetBrush
(
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOW
));
dc
.
DrawRectangle
(
0
,
0
,
size
.
x
,
size
.
y
);
// items
int
i
=
0
;
FOR_EACH
(
p
,
symbol
->
parts
)
{
drawItem
(
dc
,
0
,
i
,
false
,
p
);
}
// drag/drop indicator
if
(
mouse_down_on
&&
drop_position
!=
-
1
)
{
dc
.
SetPen
(
wxPen
(
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOWTEXT
),
3
));
int
y
=
drop_position
*
(
ITEM_HEIGHT
+
1
)
-
1
;
dc
.
DrawLine
(
0
,
y
,
size
.
x
,
y
);
dc
.
DrawLine
(
0
,
y
-
3
,
0
,
y
+
3
);
dc
.
DrawLine
(
size
.
x
-
1
,
y
-
3
,
size
.
x
-
1
,
y
+
3
);
}
drawItem
(
dc
,
0
,
i
,
false
,
symbol
);
// hide caret
if
(
selection
.
size
()
!=
1
)
{
typing_in
=
SymbolPartP
();
...
...
@@ -339,7 +397,7 @@ void SymbolPartList::drawItem(DC& dc, int x, int& i, bool parent_active, const S
// draw item : highlight
Color
background
;
dc
.
SetPen
(
*
wxTRANSPARENT_PEN
);
bool
active
=
selection
.
find
(
part
)
!=
selection
.
end
(
);
bool
active
=
selection
.
selected
(
part
);
if
(
active
)
{
background
=
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_HIGHLIGHT
);
dc
.
SetBrush
(
background
);
...
...
@@ -352,47 +410,67 @@ void SymbolPartList::drawItem(DC& dc, int x, int& i, bool parent_active, const S
background
=
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOW
);
dc
.
SetTextForeground
(
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOWTEXT
));
}
// draw item : name
int
h
=
dc
.
GetCharHeight
();
dc
.
DrawText
(
part
->
name
,
ITEM_HEIGHT
+
x
+
3
,
y
+
(
ITEM_HEIGHT
-
h
)
/
2
);
// draw item : icon
dc
.
SetBrush
(
lerp
(
background
,
wxColour
(
0
,
128
,
0
),
0.7
));
dc
.
DrawRectangle
(
x
,
y
,
ITEM_HEIGHT
,
ITEM_HEIGHT
);
dc
.
DrawBitmap
(
symbolPreview
(),
x
,
y
);
dc
.
DrawBitmap
(
itemPreview
(
i
,
part
),
x
,
y
);
// draw item : border
wxPen
line_pen
=
lerp
(
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOW
),
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOWTEXT
),
0.5
);
dc
.
SetPen
(
line_pen
);
dc
.
DrawLine
(
x
+
ITEM_HEIGHT
,
y
,
x
+
ITEM_HEIGHT
,
y
+
ITEM_HEIGHT
+
1
);
// line after image
dc
.
DrawLine
(
x
,
y
+
ITEM_HEIGHT
,
size
.
x
,
y
+
ITEM_HEIGHT
);
// line below
// update caret
if
(
selection
.
size
()
==
1
&&
active
)
{
updateCaret
(
dc
,
x
+
ITEM_HEIGHT
+
3
,
y
+
(
ITEM_HEIGHT
-
h
)
/
2
,
h
,
part
);
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOWTEXT
),
0.5
);
if
(
part
!=
symbol
)
{
// draw item : name
int
h
=
dc
.
GetCharHeight
();
dc
.
DrawText
(
part
->
name
,
ITEM_HEIGHT
+
x
+
3
,
y
+
(
ITEM_HEIGHT
-
h
)
/
2
);
// draw item : icon
dc
.
SetBrush
(
lerp
(
background
,
wxColour
(
0
,
128
,
0
),
0.7
));
dc
.
DrawRectangle
(
x
,
y
,
ITEM_HEIGHT
,
ITEM_HEIGHT
);
dc
.
DrawBitmap
(
symbolPreview
(),
x
,
y
);
dc
.
DrawBitmap
(
itemPreview
(
i
,
part
),
x
,
y
);
// draw item : border
dc
.
SetPen
(
line_pen
);
dc
.
DrawLine
(
x
+
ITEM_HEIGHT
,
y
,
x
+
ITEM_HEIGHT
,
y
+
ITEM_HEIGHT
+
1
);
// line after image
dc
.
DrawLine
(
x
,
y
+
ITEM_HEIGHT
,
size
.
x
,
y
+
ITEM_HEIGHT
);
// line below
// update caret
if
(
selection
.
size
()
==
1
&&
active
)
{
updateCaret
(
dc
,
x
+
ITEM_HEIGHT
+
3
,
y
+
(
ITEM_HEIGHT
-
h
)
/
2
,
h
,
part
);
}
// draw icon
state_icons
.
Draw
(
part
->
icon
(),
dc
,
size
.
x
-
10
,
y
+
1
);
// move down
i
+=
1
;
}
// Draw children
int
child_x
=
part
==
symbol
?
x
:
x
+
5
;
if
(
SymbolGroup
*
g
=
part
->
isSymbolGroup
())
{
FOR_EACH
(
p
,
g
->
parts
)
drawItem
(
dc
,
child_x
,
i
,
active
||
parent_active
,
p
);
}
// move down
i
+=
1
;
// draw more?
if
(
SymbolShape
*
s
=
part
->
isSymbolShape
())
{
// combine state
state_icons
.
Draw
(
s
->
combine
,
dc
,
size
.
x
-
10
,
y
+
1
);
}
else
if
(
SymbolSymmetry
*
s
=
part
->
isSymbolSymmetry
())
{
// kind of symmetry
state_icons
.
Draw
(
s
->
kind
,
dc
,
size
.
x
-
10
,
y
+
1
);
// TODO: show clip mode?
}
else
if
(
SymbolGroup
*
g
=
part
->
isSymbolGroup
())
{
state_icons
.
Draw
(
SYMMETRY_REFLECTION
+
1
,
dc
,
size
.
x
-
10
,
y
+
1
);
FOR_EACH
(
p
,
g
->
parts
)
drawItem
(
dc
,
x
+
5
,
i
,
active
||
parent_active
,
p
);
// draw bar on the left
int
new_y
=
i
*
(
ITEM_HEIGHT
+
1
);
y
+=
ITEM_HEIGHT
+
1
;
if
(
y
!=
new_y
)
{
dc
.
SetPen
(
line_pen
);
dc
.
SetBrush
(
background
);
dc
.
DrawRectangle
(
x
-
1
,
y
-
1
,
5
+
1
,
new_y
-
y
+
1
);
// draw bar on the left?
int
old_y
=
y
+
ITEM_HEIGHT
+
1
;
// after part itself
int
new_y
=
i
*
(
ITEM_HEIGHT
+
1
);
// after children
if
(
old_y
!=
new_y
&&
part
!=
symbol
)
{
dc
.
SetPen
(
line_pen
);
dc
.
SetBrush
(
background
);
dc
.
DrawRectangle
(
x
-
1
,
old_y
-
1
,
5
+
1
,
new_y
-
old_y
+
1
);
}
// Drop indicator?
if
(
drag_parent
&&
drop_parent
)
{
dc
.
SetPen
(
wxPen
(
wxSystemSettings
::
GetColour
(
wxSYS_COLOUR_WINDOWTEXT
),
3
));
if
(
drop_inside
)
{
if
(
part
==
drop_parent
)
{
// drop inside part
dc
.
SetBrush
(
*
wxTRANSPARENT_BRUSH
);
dc
.
DrawRectangle
(
x
,
y
,
w
,
new_y
-
y
);
}
}
else
if
(
drop_position
<
drop_parent
->
parts
.
size
())
{
if
(
part
==
drop_parent
->
parts
[
drop_position
])
{
// drop before part
dc
.
DrawLine
(
x
,
y
,
size
.
x
,
y
);
dc
.
DrawLine
(
x
,
y
-
3
,
x
,
y
+
3
);
dc
.
DrawLine
(
size
.
x
-
1
,
y
-
3
,
size
.
x
-
1
,
y
+
3
);
}
}
else
{
if
(
part
==
drop_parent
)
{
// drop after part
dc
.
DrawLine
(
child_x
,
new_y
,
size
.
x
,
new_y
);
dc
.
DrawLine
(
child_x
,
new_y
-
3
,
child_x
,
new_y
+
3
);
dc
.
DrawLine
(
size
.
x
-
1
,
new_y
-
3
,
size
.
x
-
1
,
new_y
+
3
);
}
}
}
else
{
throw
"Unknown symbol part type"
;
}
}
...
...
@@ -432,6 +510,7 @@ const Image& SymbolPartList::symbolPreview() {
}
void
SymbolPartList
::
updateCaret
(
DC
&
dc
,
int
x
,
int
y
,
int
h
,
const
SymbolPartP
&
part
)
{
int
top
;
GetViewStart
(
0
,
&
top
);
// make caret
wxCaret
*
caret
=
GetCaret
();
if
(
!
caret
)
{
...
...
@@ -446,7 +525,7 @@ void SymbolPartList::updateCaret(DC& dc, int x, int y, int h, const SymbolPartP&
cursor
=
min
(
cursor
,
typing_in
->
name
.
size
());
int
w
;
dc
.
GetTextExtent
(
typing_in
->
name
.
substr
(
0
,
cursor
),
&
w
,
nullptr
);
caret
->
Move
(
x
+
w
,
y
);
caret
->
Move
(
x
+
w
,
y
-
top
*
(
ITEM_HEIGHT
+
1
)
);
if
(
!
caret
->
IsVisible
())
caret
->
Show
();
}
...
...
src/gui/symbol/part_list.hpp
View file @
67c0e51f
...
...
@@ -12,6 +12,8 @@
#include <util/prec.hpp>
#include <data/symbol.hpp>
class
SymbolPartsSelection
;
// ----------------------------------------------------------------------------- : Events
DECLARE_EVENT_TYPE
(
EVENT_PART_SELECT
,
<
not
used
>
)
...
...
@@ -26,7 +28,7 @@ DECLARE_EVENT_TYPE(EVENT_PART_ACTIVATE, <not used>)
class
SymbolPartList
:
public
wxScrolledWindow
,
public
SymbolView
{
public:
SymbolPartList
(
Window
*
parent
,
int
id
,
set
<
SymbolPartP
>
&
selection
,
SymbolP
symbol
=
SymbolP
());
SymbolPartList
(
Window
*
parent
,
int
id
,
SymbolPartsSelection
&
selection
,
SymbolP
symbol
=
SymbolP
());
/// Another symbol is being viewed
virtual
void
onChangeSymbol
();
...
...
@@ -41,12 +43,14 @@ class SymbolPartList : public wxScrolledWindow, public SymbolView {
protected:
virtual
wxSize
DoGetBestSize
()
const
;
private:
set
<
SymbolPartP
>&
selection
;
///< Store selection here
SymbolPartP
mouse_down_on
;
int
drop_position
;
SymbolPartsSelection
&
selection
;
///< Store selection here
int
number_of_items
;
SymbolPartP
drag
;
SymbolGroupP
drag_parent
,
drop_parent
;
size_t
drag_position
,
drop_position
;
bool
drop_inside
;
// drop inside the drop parent, not at a specific position
SymbolPartP
typing_in
;
size_t
cursor
;
...
...
@@ -79,8 +83,20 @@ class SymbolPartList : public wxScrolledWindow, public SymbolView {
const
Image
&
symbolPreview
();
void
updatePart
(
const
set
<
SymbolPartP
>&
parts
,
int
&
i
,
bool
parent_updated
,
const
SymbolPartP
&
part
);
SymbolPartP
findItem
(
int
i
)
const
;
static
SymbolPartP
findItem
(
int
&
i
,
const
SymbolPartP
&
part
);
/// find item by position
SymbolPartP
findItem
(
int
i
,
int
x
)
const
;
static
SymbolPartP
findItem
(
int
&
i
,
int
x
,
const
SymbolPartP
&
part
);
/// parent of 'of' and the position of 'of' in that parent
void
findParent
(
const
SymbolPart
&
of
,
SymbolGroupP
&
parent_out
,
size_t
&
pos_out
);
static
bool
findParent
(
const
SymbolPart
&
of
,
const
SymbolGroupP
&
in
,
SymbolGroupP
&
parent_out
,
size_t
&
pos_out
);
/// Where is the drop position?
/** i = index before which the cursor is
* before = is the cursor before or after the separator line?
* Returns whether a drop position was found, sets drop_...
*/
bool
findDropTarget
(
const
SymbolPartP
&
parent
,
int
&
i
,
bool
before
);
static
int
childCount
(
const
SymbolPartP
&
part
);
...
...
src/gui/symbol/select_editor.cpp
View file @
67c0e51f
...
...
@@ -21,6 +21,7 @@ DECLARE_TYPEOF_COLLECTION(SymbolPartP);
SymbolSelectEditor
::
SymbolSelectEditor
(
SymbolControl
*
control
,
bool
rotate
)
:
SymbolEditorBase
(
control
)
,
click_mode
(
CLICK_NONE
)
,
rotate
(
rotate
)
,
cursorRotate
(
load_resource_cursor
(
_
(
"rotate"
)))
,
cursorShearX
(
load_resource_cursor
(
_
(
"shear_x"
)))
...
...
@@ -45,19 +46,27 @@ SymbolSelectEditor::SymbolSelectEditor(SymbolControl* control, bool rotate)
void
SymbolSelectEditor
::
draw
(
DC
&
dc
)
{
// highlight selected parts
FOR_EACH
(
p
,
control
.
selected_parts
)
{
FOR_EACH
(
p
,
control
.
selected_parts
.
get
()
)
{
control
.
highlightPart
(
dc
,
*
p
,
HIGHLIGHT_INTERIOR
);
}
// highlight the part under the cursor
if
(
highlightPart
)
{
control
.
highlightPart
(
dc
,
*
highlightPart
,
HIGHLIGHT_BORDER
);
}
// draw handles
drawHandles
(
dc
);
if
(
click_mode
==
CLICK_RECT
)
{
// draw selection rectangle
dc
.
SetBrush
(
*
wxTRANSPARENT_BRUSH
);
dc
.
SetPen
(
wxPen
(
*
wxBLUE
,
1
,
wxDOT
));
RealRect
rect
=
control
.
rotation
.
tr
(
RealRect
(
selection_rect_a
,
RealSize
(
selection_rect_b
-
selection_rect_a
)));
dc
.
DrawRectangle
(
rect
);
}
else
{
// draw handles
drawHandles
(
dc
);
}
}
void
SymbolSelectEditor
::
drawHandles
(
DC
&
dc
)
{
if
(
control
.
selected_parts
.
empty
())
return
;
if
(
control
.
selected_parts
.
empty
())
return
;
if
(
rotateAction
)
return
;
// not when rotating
updateBoundingBox
();
// Draw handles on all sides
...
...
@@ -130,7 +139,7 @@ void SymbolSelectEditor::onUpdateUI(wxUpdateUIEvent& ev) {
if
(
ev
.
GetId
()
>=
ID_SYMBOL_COMBINE
&&
ev
.
GetId
()
<
ID_SYMBOL_COMBINE_MAX
)
{
bool
enable
=
false
;
bool
check
=
true
;
FOR_EACH
(
p
,
control
.
selected_parts
)
{
FOR_EACH
(
p
,
control
.
selected_parts
.
get
()
)
{
if
(
SymbolShape
*
s
=
p
->
isSymbolShape
())
{
enable
=
true
;
if
(
s
->
combine
!=
ev
.
GetId
()
-
ID_SYMBOL_COMBINE
)
{
...
...
@@ -147,8 +156,8 @@ void SymbolSelectEditor::onUpdateUI(wxUpdateUIEvent& ev) {
ev
.
Enable
(
control
.
selected_parts
.
size
()
>=
2
);
}
else
if
(
ev
.
GetId
()
==
ID_EDIT_UNGROUP
)
{
// is a group selected
FOR_EACH
(
p
,
control
.
selected_parts
)
{
if
(
p
->
isSymbolGroup
())
{
FOR_EACH
(
p
,
control
.
selected_parts
.
get
()
)
{
if
(
p
->
isSymbolGroup
()
&&
!
p
->
isSymbolSymmetry
()
)
{
ev
.
Enable
(
true
);
return
;
}
...
...
@@ -163,21 +172,21 @@ void SymbolSelectEditor::onCommand(int id) {
if
(
id
>=
ID_SYMBOL_COMBINE
&&
id
<
ID_SYMBOL_COMBINE_MAX
)
{
// change combine mode
getSymbol
()
->
actions
.
add
(
new
CombiningModeAction
(
control
.
selected_parts
,
control
.
selected_parts
.
get
()
,
static_cast
<
SymbolShapeCombine
>
(
id
-
ID_SYMBOL_COMBINE
)
));
control
.
Refresh
(
false
);
}
else
if
(
id
==
ID_EDIT_DUPLICATE
&&
!
isEditing
())
{
// duplicate selection, not when dragging
getSymbol
()
->
actions
.
add
(
new
DuplicateSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
));
getSymbol
()
->
actions
.
add
(
new
DuplicateSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
.
get
()
));
control
.
Refresh
(
false
);
}
else
if
(
id
==
ID_EDIT_GROUP
&&
!
isEditing
())
{
// group selection, not when dragging
getSymbol
()
->
actions
.
add
(
new
GroupSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
));
getSymbol
()
->
actions
.
add
(
new
GroupSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
.
get
(),
new_intrusive
<
SymbolGroup
>
()
));
control
.
Refresh
(
false
);
}
else
if
(
id
==
ID_EDIT_UNGROUP
&&
!
isEditing
())
{
// ungroup selection, not when dragging
getSymbol
()
->
actions
.
add
(
new
UngroupSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
));
getSymbol
()
->
actions
.
add
(
new
UngroupSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
.
get
()
));
control
.
Refresh
(
false
);
}
}
...
...
@@ -189,35 +198,27 @@ int SymbolSelectEditor::modeToolId() {
// ----------------------------------------------------------------------------- : Mouse Events
void
SymbolSelectEditor
::
onLeftDown
(
const
Vector2D
&
pos
,
wxMouseEvent
&
ev
)
{
have_dragged
=
true
;
// change selection
// Are we on a handle?
int
dx
,
dy
;
if
(
onAnyHandle
(
pos
,
&
dx
,
&
dy
))
return
;
// don't change the selection
if
(
onAnyHandle
(
pos
,
&
dx
,
&
dy
))
{
click_mode
=
CLICK_HANDLE
;
return
;
// don't change the selection
}
// Select the part under the cursor
SymbolPartP
part
=
findPart
(
pos
);
SymbolPartP
part
=
control
.
selected_parts
.
find
(
pos
);
if
(
part
)
{
if
(
ev
.
ShiftDown
())
{
// toggle selection
set
<
SymbolPartP
>::
iterator
it
=
control
.
selected_parts
.
find
(
part
);
if
(
it
!=
control
.
selected_parts
.
end
())
{
control
.
selected_parts
.
erase
(
it
);
}
else
{
control
.
selected_parts
.
insert
(
part
);
}
}
else
{
if
(
control
.
selected_parts
.
find
(
part
)
!=
control
.
selected_parts
.
end
())
{
// already selected, do nothing
have_dragged
=
false
;
// we haven't done anything
}
else
{
// select the part under the cursor
control
.
selected_parts
.
clear
();
control
.
selected_parts
.
insert
(
part
);
}
click_mode
=
control
.
selected_parts
.
select
(
part
,
ev
.
ShiftDown
()
?
SELECT_TOGGLE
:
SELECT_IF_OUTSIDE
)
?
(
ev
.
ShiftDown
()
?
CLICK_NONE
:
CLICK_MOVE
)
:
CLICK_TOGGLE
;
}
else
{
// selection rectangle
click_mode
=
CLICK_RECT
;
selection_rect_a
=
selection_rect_b
=
pos
;
if
(
!
ev
.
ShiftDown
())
{
// select nothing
control
.
selected_parts
.
clear
();
}
}
else
if
(
!
ev
.
ShiftDown
())
{
// select nothing
control
.
selected_parts
.
clear
();
}
// selection has changed
updateBoundingBox
();
...
...
@@ -231,24 +232,18 @@ void SymbolSelectEditor::onLeftUp (const Vector2D& pos, wxMouseEvent& ev) {
resetActions
();
}
else
{
// mouse not moved -> change selection
if
(
!
have_dragged
&&
!
ev
.
ShiftDown
())
{
int
dx
,
dy
;
if
(
onAnyHandle
(
pos
,
&
dx
,
&
dy
))
return
;
// don't change the selection
// Find the part under the cursor
SymbolPartP
part
=
findPart
(
pos
);
if
(
control
.
selected_parts
.
find
(
part
)
!=
control
.
selected_parts
.
end
())
{
// already selected, don't change selection
// instead switch between rotate and resize mode
rotate
=
!
rotate
;
}
if
(
click_mode
==
CLICK_TOGGLE
)
{
// switch between rotate and resize mode
rotate
=
!
rotate
;
}
}
click_mode
=
CLICK_NONE
;
control
.
Refresh
(
false
);
}
void
SymbolSelectEditor
::
onLeftDClick
(
const
Vector2D
&
pos
,
wxMouseEvent
&
ev
)
{
// start editing the points of the clicked part
highlightPart
=
findPart
(
pos
);
highlightPart
=
control
.
selected_parts
.
find
(
pos
);
if
(
highlightPart
)
{
control
.
activatePart
(
highlightPart
);
}
...
...
@@ -256,7 +251,7 @@ void SymbolSelectEditor::onLeftDClick(const Vector2D& pos, wxMouseEvent& ev) {
void
SymbolSelectEditor
::
onMouseMove
(
const
Vector2D
&
from
,
const
Vector2D
&
to
,
wxMouseEvent
&
ev
)
{
// can we highlight a part?
highlightPart
=
findPart
(
to
);
highlightPart
=
control
.
selected_parts
.
find
(
to
);
// are we on a handle?
int
dx
,
dy
;
if
(
!
control
.
selected_parts
.
empty
()
&&
onAnyHandle
(
to
,
&
dx
,
&
dy
))
{
...
...
@@ -296,31 +291,39 @@ template <typename Event> int snap(Event& ev) {
}
void
SymbolSelectEditor
::
onMouseDrag
(
const
Vector2D
&
from
,
const
Vector2D
&
to
,
wxMouseEvent
&
ev
)
{
have_dragged
=
true
;
if
(
click_mode
==
CLICK_NONE
)
return
;
if
(
control
.
selected_parts
.
empty
())
return
;
if
(
click_mode
==
CLICK_RECT
)
{
// rectangle
control
.
selected_parts
.
selectRect
(
selection_rect_a
,
selection_rect_b
,
to
,
SELECT_TOGGLE
);
selection_rect_b
=
to
;
control
.
Refresh
(
false
);
}
if
(
!
isEditing
())
{
// we don't have an action yet, determine what to do
// note: base it on the from position, which is the position where dragging started
if
(
onAnyHandle
(
from
,
&
scaleX
,
&
scaleY
))
{
click_mode
=
CLICK_HANDLE
;
if
(
rotate
)
{
if
(
scaleX
==
0
||
scaleY
==
0
)
{
// shear, center/fixed point on the opposite side
shearAction
=
new
SymbolPartShearAction
(
control
.
selected_parts
,
handlePos
(
-
scaleX
,
-
scaleY
));
shearAction
=
new
SymbolPartShearAction
(
control
.
selected_parts
.
get
()
,
handlePos
(
-
scaleX
,
-
scaleY
));
getSymbol
()
->
actions
.
add
(
shearAction
);
}
else
{
// rotate
rotateAction
=
new
SymbolPartRotateAction
(
control
.
selected_parts
,
center
);
rotateAction
=
new
SymbolPartRotateAction
(
control
.
selected_parts
.
get
()
,
center
);
getSymbol
()
->
actions
.
add
(
rotateAction
);
startAngle
=
angleTo
(
to
);
}
}
else
{
// we are on a handle; start scaling
scaleAction
=
new
SymbolPartScaleAction
(
control
.
selected_parts
,
scaleX
,
scaleY
);
scaleAction
=
new
SymbolPartScaleAction
(
control
.
selected_parts
.
get
()
,
scaleX
,
scaleY
);
getSymbol
()
->
actions
.
add
(
scaleAction
);
}
}
else
{
// move
moveAction
=
new
SymbolPartMoveAction
(
control
.
selected_parts
);
click_mode
=
CLICK_MOVE
;
moveAction
=
new
SymbolPartMoveAction
(
control
.
selected_parts
.
get
());
getSymbol
()
->
actions
.
add
(
moveAction
);
}
}
...
...
@@ -391,8 +394,8 @@ void SymbolSelectEditor::onKeyChange (wxKeyEvent& ev) {
void
SymbolSelectEditor
::
onChar
(
wxKeyEvent
&
ev
)
{
if
(
ev
.
GetKeyCode
()
==
WXK_DELETE
)
{
// delete selected parts
getSymbol
()
->
actions
.
add
(
new
RemoveSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
));
if
(
control
.
selected_parts
.
find
(
highlightPart
)
!=
control
.
selected_parts
.
end
(
))
highlightPart
=
SymbolPartP
();
// deleted it
getSymbol
()
->
actions
.
add
(
new
RemoveSymbolPartsAction
(
*
getSymbol
(),
control
.
selected_parts
.
get
()
));
if
(
control
.
selected_parts
.
selected
(
highlightPart
))
highlightPart
=
SymbolPartP
();
// deleted it
control
.
selected_parts
.
clear
();
resetActions
();
control
.
Refresh
(
false
);
...
...
@@ -408,7 +411,7 @@ void SymbolSelectEditor::onChar(wxKeyEvent& ev) {
ev
.
Skip
();
return
;
}
getSymbol
()
->
actions
.
add
(
new
SymbolPartMoveAction
(
control
.
selected_parts
,
delta
));
getSymbol
()
->
actions
.
add
(
new
SymbolPartMoveAction
(
control
.
selected_parts
.
get
()
,
delta
));
}
}
...
...
@@ -450,35 +453,11 @@ double SymbolSelectEditor::angleTo(const Vector2D& pos) {
return
atan2
(
center
.
x
-
pos
.
x
,
center
.
y
-
pos
.
y
);
}
SymbolPartP
find_part
(
const
SymbolPartP
&
part
,
const
Vector2D
&
pos
)
{
if
(
SymbolShape
*
s
=
part
->
isSymbolShape
())
{
if
(
point_in_shape
(
pos
,
*
s
))
return
part
;
}
else
if
(
SymbolSymmetry
*
s
=
part
->
isSymbolSymmetry
())
{
// TODO
}
else
if
(
SymbolGroup
*
g
=
part
->
isSymbolGroup
())
{
FOR_EACH
(
p
,
g
->
parts
)
{
if
(
find_part
(
p
,
pos
))
return
part
;
}
}
else
{
throw
InternalError
(
_
(
"Invalid symbol part type"
));
}
return
SymbolPartP
();
}
SymbolPartP
SymbolSelectEditor
::
findPart
(
const
Vector2D
&
pos
)
{
FOR_EACH
(
p
,
getSymbol
()
->
parts
)
{
SymbolPartP
found
=
find_part
(
p
,
pos
);
if
(
found
)
return
found
;
}
return
SymbolPartP
();
}
void
SymbolSelectEditor
::
updateBoundingBox
()
{
// Find min and max coordinates
minV
=
Vector2D
::
infinity
();
maxV
=
-
Vector2D
::
infinity
();
FOR_EACH
(
p
,
control
.
selected_parts
)
{
FOR_EACH
(
p
,
control
.
selected_parts
.
get
()
)
{
minV
=
piecewise_min
(
minV
,
p
->
min_pos
);
maxV
=
piecewise_max
(
maxV
,
p
->
max_pos
);
}
...
...
src/gui/symbol/select_editor.hpp
View file @
67c0e51f
...
...
@@ -74,6 +74,15 @@ class SymbolSelectEditor : public SymbolEditorBase {
Vector2D
minV
,
maxV
;
// Where is the rotation center?
Vector2D
center
;
// What kind of clicking/dragging are we doing
enum
ClickMode
{
CLICK_NONE
,
CLICK_MOVE
,
// moving parts around
CLICK_HANDLE
,
// dragging a handle
CLICK_CENTER
,
// dragging the rotation center
CLICK_RECT
,
// selection rectangle
CLICK_TOGGLE
,
// same selection, not moved -> switch to rotate mode
}
click_mode
;
// At what angle is the handle we started draging for rotation
double
startAngle
;
// what side are we dragging/rotating on?
...
...
@@ -82,6 +91,8 @@ class SymbolSelectEditor : public SymbolEditorBase {
bool
have_dragged
;
// Do we want to rotate?
bool
rotate
;
// selection rectangle
Vector2D
selection_rect_a
,
selection_rect_b
;
// Graphics assets
wxCursor
cursorRotate
;
wxCursor
cursorShearX
;
...
...
@@ -104,9 +115,6 @@ class SymbolSelectEditor : public SymbolEditorBase {
/// Return the position of a handle, dx,dy in <-1, 0, 1>
Vector2D
handlePos
(
int
dx
,
int
dy
);
/// Find the first part at the given position
SymbolPartP
findPart
(
const
Vector2D
&
pos
);
/// Update minV and maxV to be the bounding box of the selected_parts
/// Updates center to be the rotation center of the parts
void
updateBoundingBox
();
...
...
src/gui/symbol/window.cpp
View file @
67c0e51f
...
...
@@ -108,27 +108,27 @@ void SymbolWindow::init(Window* parent, SymbolP symbol) {
// Edit mode toolbar
wxPanel
*
emp
=
new
wxPanel
(
this
,
wxID_ANY
);
wxToolBar
*
em
=
new
wxToolBar
(
emp
,
wxID_ANY
,
wxDefaultPosition
,
wxDefaultSize
,
wxTB_FLAT
|
wxTB_VERTICAL
|
wxTB_TEXT
|
wxTB_HORZ_LAYOUT
);
wxToolBar
*
em
=
new
wxToolBar
(
emp
,
wxID_ANY
,
wxDefaultPosition
,
wxDefaultSize
,
wxTB_FLAT
|
wxTB_VERTICAL
|
wxTB_HORZ_TEXT
);
em
->
SetToolBitmapSize
(
wxSize
(
17
,
17
));
em
->
AddTool
(
ID_MODE_SELECT
,
_TOOL_
(
"select"
),
load_resource_tool_image
(
_
(
"mode_select"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"select"
),
_HELP_
(
"select"
));
em
->
AddTool
(
ID_MODE_ROTATE
,
_TOOL_
(
"rotate"
),
load_resource_tool_image
(
_
(
"mode_rotate"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"rotate"
),
_HELP_
(
"rotate"
));
em
->
AddSeparator
();
em
->
AddTool
(
ID_MODE_POINTS
,
_TOOL_
(
"points"
),
load_resource_tool_image
(
_
(
"mode_curve"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"points"
),
_HELP_
(
"points"
));
em
->
AddSeparator
();
em
->
AddTool
(
ID_MODE_SHAPES
,
_TOOL_
(
"basic shapes"
),
load_resource_tool_image
(
_
(
"circle"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"basic shapes"
),
_HELP_
(
"basic shapes"
));
em
->
AddSeparator
();
em
->
AddTool
(
ID_MODE_PAINT
,
_TOOL_
(
"paint"
),
load_resource_tool_image
(
_
(
"mode_paint"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"paint"
),
_HELP_
(
"paint"
));
em
->
AddSeparator
();
em
->
AddTool
(
ID_MODE_SYMMETRY
,
_TOOL_
(
"symmetry"
),
load_resource_tool_image
(
_
(
"mode_symmetry"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"symmetry"
),
_HELP_
(
"symmetry"
));
//em->AddTool(ID_MODE_PAINT, _TOOL_("paint"), load_resource_tool_image(_("mode_paint")), wxNullBitmap, wxITEM_CHECK, _TOOLTIP_("paint"), _HELP_("paint"));
em
->
Realize
();
// Lay out
wxSizer
*
es
=
new
wxBoxSizer
(
wxVERTICAL
);
es
->
Add
(
em
,
1
,
wxEXPAND
|
wxBOTTOM
|
wxALIGN_CENTER
,
5
);
emp
->
SetSizer
(
es
);
// Controls
control
=
new
SymbolControl
(
this
,
ID_CONTROL
,
symbol
);
parts
=
new
SymbolPartList
(
this
,
ID_PART_LIST
,
control
->
selected_parts
,
symbol
);
// Lay out
wxSizer
*
es
=
new
wxBoxSizer
(
wxHORIZONTAL
);
es
->
Add
(
em
,
1
,
wxEXPAND
|
wxTOP
|
wxBOTTOM
|
wxALIGN_CENTER
,
1
);
emp
->
SetSizer
(
es
);
wxSizer
*
s
=
new
wxBoxSizer
(
wxHORIZONTAL
);
wxSizer
*
v
=
new
wxBoxSizer
(
wxVERTICAL
);
v
->
Add
(
emp
,
0
,
wxEXPAND
);
...
...
@@ -137,6 +137,52 @@ void SymbolWindow::init(Window* parent, SymbolP symbol) {
s
->
Add
(
control
,
1
,
wxEXPAND
);
SetSizer
(
s
);
#ifdef __WXMSW__
// only tested on msw, may not even be needed on other platforms
#define USE_HORRIBLE_HORRIBLE_HACK_TO_MAKE_TOOLBAR_THE_RIGHT_SIZE
#endif
#ifdef USE_HORRIBLE_HORRIBLE_HACK_TO_MAKE_TOOLBAR_THE_RIGHT_SIZE
// Welcome to HackWorld
// Prevent clipping of the bottom tool
Layout
();
em
->
SetSize
(
emp
->
GetSize
());
// HACK: force edit mode toolbar to be wide enough by adding spaces to tool names
int
n
=
0
;
while
(
em
->
GetSize
().
x
+
5
<
emp
->
GetSize
().
x
)
{
++
n
;
for
(
int
id
=
ID_MODE_SELECT
;
id
<=
ID_MODE_SYMMETRY
;
++
id
)
{
wxToolBarToolBase
*
tool
=
em
->
FindById
(
id
);
tool
->
SetLabel
(
tool
->
GetLabel
()
+
_
(
" "
));
}
em
->
Realize
();
}
// And now rebuild it, because the above meddling broke the toolbar for some unknown reason
em
->
Destroy
();
em
=
new
wxToolBar
(
emp
,
wxID_ANY
,
wxDefaultPosition
,
wxDefaultSize
,
wxTB_FLAT
|
wxTB_VERTICAL
|
wxTB_HORZ_TEXT
);
em
->
SetToolBitmapSize
(
wxSize
(
17
,
17
));
String
spaces
(
max
(
0
,
n
-
1
),
_
(
' '
));
em
->
AddTool
(
ID_MODE_SELECT
,
_TOOL_
(
"select"
)
+
spaces
,
load_resource_tool_image
(
_
(
"mode_select"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"select"
),
_HELP_
(
"select"
));
em
->
AddTool
(
ID_MODE_ROTATE
,
_TOOL_
(
"rotate"
)
+
spaces
,
load_resource_tool_image
(
_
(
"mode_rotate"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"rotate"
),
_HELP_
(
"rotate"
));
em
->
AddSeparator
();
em
->
AddTool
(
ID_MODE_POINTS
,
_TOOL_
(
"points"
)
+
spaces
,
load_resource_tool_image
(
_
(
"mode_curve"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"points"
),
_HELP_
(
"points"
));
em
->
AddSeparator
();
em
->
AddTool
(
ID_MODE_SHAPES
,
_TOOL_
(
"basic shapes"
)
+
spaces
,
load_resource_tool_image
(
_
(
"circle"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"basic shapes"
),
_HELP_
(
"basic shapes"
));
em
->
AddTool
(
ID_MODE_SYMMETRY
,
_TOOL_
(
"symmetry"
)
+
spaces
,
load_resource_tool_image
(
_
(
"mode_symmetry"
)),
wxNullBitmap
,
wxITEM_CHECK
,
_TOOLTIP_
(
"symmetry"
),
_HELP_
(
"symmetry"
));
//em->AddTool(ID_MODE_PAINT, _TOOL_("paint") + spaces, load_resource_tool_image(_("mode_paint")), wxNullBitmap, wxITEM_CHECK, _TOOLTIP_("paint"), _HELP_("paint"));
em
->
Realize
();
es
=
new
wxBoxSizer
(
wxVERTICAL
);
es
->
Add
(
em
,
1
,
wxEXPAND
|
wxBOTTOM
|
wxALIGN_CENTER
,
5
);
emp
->
SetSizer
(
es
);
// Prevent clipping of the bottom tool
Layout
();
em
->
SetSize
(
emp
->
GetSize
());
#endif
// we want update ui events
wxUpdateUIEvent
::
SetMode
(
wxUPDATE_UI_PROCESS_SPECIFIED
);
SetExtraStyle
(
wxWS_EX_PROCESS_UI_UPDATES
);
...
...
src/mse.vcproj
View file @
67c0e51f
...
...
@@ -877,6 +877,18 @@
<File
RelativePath=
".\gui\symbol\select_editor.hpp"
>
</File>
<File
RelativePath=
".\gui\symbol\selection.cpp"
>
</File>
<File
RelativePath=
".\gui\symbol\selection.hpp"
>
</File>
<File
RelativePath=
".\gui\symbol\symmetry_editor.cpp"
>
</File>
<File
RelativePath=
".\gui\symbol\symmetry_editor.hpp"
>
</File>
<File
RelativePath=
".\gui\symbol\window.cpp"
>
<FileConfiguration
...
...
src/render/symbol/viewer.cpp
View file @
67c0e51f
...
...
@@ -164,7 +164,25 @@ void SymbolViewer::highlightPart(DC& dc, const SymbolShape& shape, HighlightStyl
}
}
void
SymbolViewer
::
highlightPart
(
DC
&
dc
,
const
SymbolSymmetry
&
sym
)
{
// TODO
// center
RealPoint
center
=
rotation
.
tr
(
sym
.
center
);
// draw 'spokes'
double
angle
=
atan2
(
sym
.
handle
.
y
,
sym
.
handle
.
x
);
dc
.
SetPen
(
wxPen
(
Color
(
255
,
200
,
0
),
3
));
for
(
int
i
=
0
;
i
<
sym
.
copies
;
++
i
)
{
double
a
=
angle
+
(
i
+
0.5
)
*
2
*
M_PI
/
sym
.
copies
;
Vector2D
dir
(
cos
(
a
),
sin
(
a
));
Vector2D
dir2
=
rotation
.
tr
(
sym
.
center
+
2
*
dir
);
dc
.
DrawLine
(
center
.
x
,
center
.
y
,
dir2
.
x
,
dir2
.
y
);
}
// draw center
dc
.
SetPen
(
*
wxBLACK_PEN
);
dc
.
SetBrush
(
Color
(
255
,
200
,
0
));
dc
.
DrawCircle
(
center
.
x
,
center
.
y
,
5
);
// draw handle
Vector2D
dir2
=
rotation
.
tr
(
sym
.
center
+
sym
.
handle
);
dc
.
SetPen
(
wxPen
(
Color
(
255
,
200
,
0
),
1
,
wxDOT
));
dc
.
DrawLine
(
center
.
x
,
center
.
y
,
dir2
.
x
,
dir2
.
y
);
}
void
SymbolViewer
::
highlightPart
(
DC
&
dc
,
const
SymbolGroup
&
group
,
HighlightStyle
style
)
{
if
(
style
==
HIGHLIGHT_BORDER
)
{
...
...
src/script/context.cpp
View file @
67c0e51f
...
...
@@ -352,6 +352,7 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP&
break
;
case
I_AND
:
OPERATOR_I
(
&&
);
case
I_OR
:
OPERATOR_I
(
||
);
case
I_XOR
:
a
=
to_script
((
bool
)
*
a
!=
(
bool
)
*
b
);
break
;
case
I_EQ
:
OPERATOR_SDI
(
==
);
case
I_NEQ
:
OPERATOR_SDI
(
!=
);
case
I_LT
:
OPERATOR_DI
(
<
);
...
...
src/script/parser.cpp
View file @
67c0e51f
...
...
@@ -582,6 +582,7 @@ void parseOper(TokenIterator& input, Script& script, Precedence minPrec, Instruc
parseOper
(
input
,
script
,
PREC_CMP
,
I_BINARY
,
I_OR
);
}
}
else
if
(
minPrec
<=
PREC_AND
&&
token
==
_
(
"xor"
))
parseOper
(
input
,
script
,
PREC_CMP
,
I_BINARY
,
I_XOR
);
else
if
(
minPrec
<=
PREC_CMP
&&
token
==
_
(
"="
))
{
if
(
minPrec
<=
PREC_SET
)
{
input
.
add_error
(
_
(
"Use of '=', did you mean ':=' or '=='?"
));
...
...
src/script/script.cpp
View file @
67c0e51f
...
...
@@ -146,6 +146,7 @@ String Script::dumpInstr(unsigned int pos, Instruction i) const {
case
I_MOD
:
ret
+=
_
(
"mod"
);
break
;
case
I_AND
:
ret
+=
_
(
"and"
);
break
;
case
I_OR
:
ret
+=
_
(
"or"
);
break
;
case
I_XOR
:
ret
+=
_
(
"xor"
);
break
;
case
I_EQ
:
ret
+=
_
(
"=="
);
break
;
case
I_NEQ
:
ret
+=
_
(
"!="
);
break
;
case
I_LT
:
ret
+=
_
(
"<"
);
break
;
...
...
src/script/script.hpp
View file @
67c0e51f
...
...
@@ -63,6 +63,7 @@ enum BinaryInstructionType
// Logical
,
I_AND
///< logical and
,
I_OR
///< logical or
,
I_XOR
///< logical xor
// Comparison
,
I_EQ
///< operator ==
,
I_NEQ
///< operator !=
...
...
src/util/window_id.hpp
View file @
67c0e51f
...
...
@@ -152,6 +152,13 @@ enum ChildMenuID {
,
ID_SHAPE_MAX
,
ID_SIDES
// SymbolSymmetryEditor toolbar/menu
,
ID_SYMMETRY
=
2201
,
ID_SYMMETRY_ROTATION
=
ID_SHAPE
,
ID_SYMMETRY_REFLECTION
,
ID_SYMMETRY_MAX
,
ID_COPIES
// On cards panel
,
ID_COLLAPSE_NOTES
=
3001
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment