1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
"""
Prerequisite_ReferencePlaneIsSelected.py (scratch file)
a prerequisite for a command, which requires that a reference plane is selected.
$Id$
what is required?
a ref plane or equiv is selected
write some code to look at selection and determine that
given the model or model-with-selection
(an assy object?)
(or just a "model", implicit that it includes selection?)
(why not receive them both? and you could just pass the current part...)
anyway... it follows that flow chart i wrote, looking at params and prior-loop state
to decide what to do and what to say.
it runs through some code to compute this, may have model side effects...
when does it run? when we "enter the mode", as part of updating the UI.
we can't update the UI until it runs.
it might decide to change modes! this might repeat until it settles down!
"""
## split the code below out of this class: from Commands.Prerequisite import Prerequisite
from utilities import accumulate # combines sublists into a big one... ###IMPLEM
class PreCommand(Command):
"""
Abstract class for a kind of temporary Command which comes before
other commands.
(Note: Instances of specific subclasses are single runs,
as for all Commands.)
Subclasses typically need to override enterSelfWithContinuations
in a nontrivial way, and also delegate some of the command API
to the yes_cmd continuation... eg let it describe the PM (but tell it whether the preq is satisfied)
(but modify the PM it makes or describes, to get our own) (or, pass it values to include in the one it makes? more realistic?)
conclusion: for now, the preq just tells the main cmd what it wants to know to make its PM
and the main cmd has to remember to include that data in its PM desc!!
digr: review: when a preq becomes satsified by user action responding to msg,
do we print something into statusbar or maybe history? or when it is *not* satisfied, ditto?
if so, do it by calling a special log-like function... at what point do we know this happened?
### REVIEW -- do we know yes_cmd/no_cmd at this level
or is that constructed? typically the yes_cmd comes from the "stuff after this pre-command"
and the no_cmd is an error handling command... which might depend -- on what?? ###
"""
pass
class Prerequisite( PreCommand):
# initial values of instance variables
prerequisite_msg = None # None, or a message prefix for the PM
# methods which subclasses should override
def prerequisite_check(self):
"""
(part of the Prerequisite subclass API)
Check whether the prerequisite is satisfied in self's situation (model, selection, prefs and settings).
Do things involving the command sequencer, messages, etc, if it is or is not... ###
Return True (after side effects on self) if it's satisfied, false if not.
"""
assert 0, "subclass must override this method"
# methods which should not normally be overridden
def enterSelfWithContinuations(self, yes_cmd, no_cmd): ### SCRATCH name and API
"""
(proposed new part of the Command API ### REVIEW/TODO)
Enter self, with yes_cmd being the command to run if self *eventually* succeeds
(after whatever user interaction we can provide to help that happen),
and no_cmd being the command to run if we give up on succeeding.
Note: those cmds might be command instances, or just descriptions. ###TODO/REVIEW
"""
# while self has things to do, do them (influenced by yes_cmd),
# then decide which one to replace ourselves with (return value says that)
# To stay in self: return True, None
# To forward to another command immediately: return False, cmd (description or instance)
return True, None ### STUB
pass
class Prerequisite_ReferencePlaneIsSelected( Prerequisite):
# initial values of instance variables
offer_ref_planes_for_selection = False
# whether our UI (in PM and/or graphics area) needs to offer
# the available ref planes for selection
### REVIEW: do we loop around and reset this? (in which case, best to set it at start of prerequisite_check ###TODO)
# or do we make a new preq instance in which it's already reset?? ###
def prerequisite_check(self):
"""
(part of the Prerequisite subclass API)
Check whether exactly one reference plane (or equivalent) is selected.
It's ok if other stuff is also selected.
"""
# require that among the selected things there is exactly one reference plane or equivalent
# (TODO: but if the same or an identical one shows up twice, ignore that!)
# (TODO: if there is one explicit plane and other plane-equivalents,
# let the explicit plane trump the others)
planes = accumulate( lambda node: node.getReferencePlanes(), self.getTopmostSelectedNodes() ) ### IMPLEM in Node & Command
# TODO: canonicalize them and remove duplicates
if len(planes) == 1:
# good!
plane = planes[0]
self.setReferencePlane(plane) ### IMPLEM - puts it into appropriate slot in PM... how is that specified BTW?
### REVIEW -- is there a PM_ReferencePlaneSelector for the widget or combo which is used to help select a ref plane?
# if so, we'd require the PM to contain one (or to be a description to which we can add one)
### SEE mark's user story to see what it says about this
return True # success
elif len(planes) == 0:
self.prerequisite_msg = "Select a reference plane." # TODO: also say "or a surface..."
self.offer_ref_planes_for_selection = True
return False # failure (of our prerequisite to be met)
elif len(planes) > 1:
self.prerequisite_msg = "Select a single reference plane." # TODO: also say "or surface..."
self.offer_ref_planes_for_selection = True
# REVIEW: do we modify the UI in this case to make the already selected ones especially easy to choose from?
return False
pass
# override some graphics area methods to help implement what we do ... also some actions for PM slots in the ref plane selector(?)
def leftDown(self, event):
### do we let user click on a ref plane in graphics area (in 3d area or in MT-in-glpane) to select it?
pass ###STUB
def Draw(self, whatever):###k
self.yes_cmd.Draw(whatever) ### TODO: I guess we need to instantiate that no matter what (be optimistic!)
# REVIEW: maybe put it inside a wrapper to protect us from exceptions in it?
### now also draw the ref plane stuff -- 3d or MTi-in-glpane, for std planes or ones in model, esp selected ones
return
# also whatever we need to handle the PM widget for this
# REVIEW: the PM widget goes with this preq object... but what delegates to what? it seems like this preq is in control...
# as if we took the cmd Seq( preq, yes_cmd) and rewrote it to something fancier, sort of preq(yes_cmd, std_error_handler)
|