summaryrefslogtreecommitdiff
path: root/cad/src/exprs/scratch/demo_create_shapes.py
blob: e25643c886ac3670a3ed09be7217dccebcdbc191 (plain)
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# Copyright 2007 Nanorex, Inc.  See LICENSE file for details. 
"""
demo_create_shapes.py -- some demo commands for creating shapes in the model.

$Id$
"""

from demo_draw_on_surface import * # be really lazy for now -- but don't forget the _private names

#e PLAN: do more of the kind of thing now done in demo_draw_on_surface.py,
# and integrate it all together using demo_ui.py or so.
#
# Solve some problems of relations between model objects, and savable model objects,
# and autoadding State decls (in wrappers or customizations -- use _e_extend??) to exprs for given attrs.
#
# Keep in mind the need for selection state, bindings in MT that fit with those in graphics area when sensible,
# automaking of PM groups, browsing of available commands (by name or by what they can do)...


# sources:

#e class Cylinder -- see dna_ribbon_view.py: 179: class Cylinder(Geom3D)
 # also Cylinder_HelicalPath(Geom3D)...

#e class Sphere

# other solids

# geometry_exprs.py

# demo_polyline.py  and the see also files it mentions


# also 2d shapes? they are sketch entities... i suppose so are 3d shapes...
# all shapes might be based on control points (see geometry_exprs.py)
# defined in various reference objects or grids...
# not all points in a sketch entity have to come from the same ref object!
# and they might be lnked to a snapshot of that object, or to a live instance of it in the model!
# or to a derived one (formula of ones in the model) which is not itself directly visible in the model.


from dna_ribbon_view import Cylinder

class Stateful(InstanceOrExpr):
    """Given an expr and a list of its arg/option attrs, extract the types of those attrs from the expr,
    and act as a stateful type permitting those attrs to be set/changed.
       Also be capable of returning metainfo that would let file save/load mappings, property editors, etc,
    be generated.
       For example, Stateful(Cylinder, ['axis', 'color', 'radius']) ... #doc more
    """
    ###e what is the state-type -- a plain object, or an expr itself? (eg to support relations, ref geom, relative coords)
    # Do we pass this in? if so, how? for each attr or for all? for each type, of the types involved in the attrs?
    # how would the expr say that one arg's precise type, or coordsys, etc, is a function of another arg's value?

    # args
    expr = ArgExpr(Anything, doc = "an expr whose arguments we'll extend into state decls")
    attrs = Arg(list_Expr(str), doc = "list of some or all of its arg attrs, or a filter for them [nim]; we'll only extend these ones")
        #e can this have a useful default of "all of them"??
        #e can we pass it more info like a specific type per attr?

    #
    decls = expr._e_attr_decls # list of decls of attrs of expr, in their declared order; each is an AttrDecl object for it.attr
        ###IMPLEM this attr of an expr, and the AttrDecl object it returns;
        # I guess/hope that object is just the Arg or Option after _E_ATTR gets replaced by the real attr
        ### PROBLEM: this will fail: _e_attr can't be symbolic getattr.
        ## Q: should expr be a true expr, or an Instance representing an expr in a more first-class way? Or can those be the same thing?
        # A, I hope: those can be the same thing -- exprs (when not symbolic) can be sufficiently first-class for that.
        # This might require tracking just how symbolic each expr is... actually I guess getattr_Expr always is, since otherwise
        # it is not formed from getattr. So maybe it won't require that.

    want_decls = filter_Expr( lambda decl: (not attrs) or (decl.attr in attrs),
                                  ###IMPLEM (if review ok): not -> not_Expr, or -> or_Expr, in -> in_Expr --
                                      # BUT review will say no, if I use them in programming, e.g. not exprvar means it's None.
                                      #k Can it differ for symbolic case or not?? (All OpExprs would be symbolic, I guess...)
                                  ### PROBLEM: attrs won't get replaced with _self.attrs since it's inside a lambda body --
                                  # unless filter_Expr is smart enough to tease apart the lambda for that purpose.
                                  # (Or to eval it on a symbolic arg?? And *then* replace in it using scanner? To eval during scanner?)
                              decls )
        ###BUG: those should be in the order in the list, not the order in decls, I think
        # (unless there are issues about a partial order of definining them due to types referring to others' vals...
        #  but i doubt that should be allowed to cause a restriction on order in a file record or PM -- tho I'm not sure ##e)
    def _C_extended_expr(self):
        res = self.expr
        for decl in self.want_decls:
            kws = {decl.attr : State( decl.type, decl.dflt )} ###IMPLEM this executable form of State
            res = res._e_extend(**kws)
        return res
    ###e now, what do we do with that so that our owner can use it? Do we let it act as our "value"??? (a kind of delegate i guess)
    #e (or maybe more like a forwarding value, a val we forward to)

    pass # end of class

#e now make a command for creating a Stateful(Cylinder) in the model -- i guess we pass Stateful(Cylinder) as expr arg to another thing
# which makes a standard creator command for that expr, extracting state decls from it, and which makes a std PM too

class StandardSketchEntityCreatorCommand(InstanceOrExpr):
    "a standard creator command for a sketch entity of the type described by our arg expr"
    # note, this is useful even if it doesn't define enough and you have to subclass it (i e delegate to it) in practice,
    # eg for the mouse behavior part. or maybe you have to pass in some fancier exprs that help it implem that part.
    expr = ArgExpr(Anything, doc = "an expr for a stateful object of a certain kind...") #doc
    ##e customizations = Option(Customizations) ###IMPLEM that type, and whatever we do about it in here... see customization below
    #
    fields = expr._e_state_fields ### seems wrong -- how would it know? instead, get the types, let env make them into fields ####e
        # [besides the problem with making a getattr_Expr due to the _e_] 
    field_editor_group = StandardFieldEditorGroup(fields) ###IMPLEM
    property_manager_groups = [field_editor_group] #e more? btw, don't we want to subdivide the fields into groups?
        ###e what we *really* want is to be able to apply user (or developer) customization data
        # to this very object to get a fancier one. Then to develop a type, start with this thing
        # and edit it using the app's customization features!
        # This might work by letting customizations be edit commands on the UI we make here,
        # since the developer might create them by seeing that UI in a first class way and editing it.
    ###e lots more
    pass

####  PROBLEMS   #####

# biggest uncomfortablenesses so far:
# - expr prickliness about getattr_Expr from ._e_xxx -- and for that matter the _e_ in the name --
#   if we first-classed them into UnderstoodExpr instances or so, we could use regular attrnames on them
# - some of those things should be functions anyway, I mean methods with args

from somewhere import Cylinder, Sphere, Rect, Line, Circle, Polygon, Polyline # etc
for shapeclass in (Cylinder, Sphere, Rect, Line, Circle): #e and more
    register_command( StandardSketchEntityCreatorCommand( Stateful( shapeclass)))
    #e hmm, can it really be that simple at the end??
    # what about things like their topic, organization into UI, other metainfo...
    # maybe all that can be added by interactive customization??
    # if so, it really can be that simple!
    # in fact, even simpler -- this would be a rule to apply to every "shape class" that gets registered.
    # there'd be lots of rules for lots of different kinds of classes... and lots of customization-interference-points...
    # of course you also want other registered classes to provide customization (like the ones in the same module as the main class)...

# ==

# let's think about how, in practice, we extract the arg decls from an expr...
# [continued in new edits to "Arg advice" in attr_decl_macros.py. Search for that phrase or "update 070323".]

# ==

###   TODO   ###   (besides the entire file)

# Let's do one of these entirely by hand. Problem: above won't import. Well, nevermind that for now. (The below won't either!)

from dna_ribbon_view import Cylinder, LineSegment, Nanometers

class StatefulCylinder(DelegatingInstanceOrExpr):
    axis = State(LineSegment, (ORIGIN, ORIGIN + DX)) ###e really we want StateArg, etc
        #e note: for this guy's default value, I was going to say
        ## Cylinder._e_default_attr_value('axis'), but that's as hard as impleming those Arg decl objects!
    radius = State( Nanometers, 1.0)
    color = State( Color, gray)
    capped = State( bool, True)
    delegate = Cylinder(axis, radius, color, capped = capped)
    pass

TextEditField ###IMPLEM (like run py code)

class MakeCylinder_PM(xxx):
    delegate = SimpleColumn(
        ###e what for the axis? need a PM for picking/finding/making a LineSegment. In real life it'll be by relations / ref geom, not coords...
        #e for radius, a float lineedit widget, with units, or an ability to go find a length dimension to define it from...
        #e for color, a color edit field... (shows color, lets you give it by name, or stylename, or formula, or use colorchooser, or see recent colors...)
        #e for capped, a checkbox
        # [notice how all this totally depends on the type? i think none of these egs depended on anything *but* the type!
        #  and maybe, the extent of fanciness of relations you want for it... but ideally that depends on the type too.
        #  and by this point should be encoded literally into the State type, anyway.]
     )
    pass

# ==

# end