PageRenderTime 32ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/dt_base.go

https://bitbucket.org/EScottDaniels/drawingthings
Go | 458 lines | 199 code | 60 blank | 199 comment | 45 complexity | aa6bc1847477cbb9028da70f64ddbb88 MD5 | raw file
  1. /*
  2. Mnemonic: dt_base.go
  3. Abstract: The base for all drawing things. Any dt should include an unnamed field wth the
  4. dt_base tpe in it's struct as the first element to pull common fields from the
  5. definition here. This module implements dummy functions for anything that is
  6. not possible with the base struct, but may be implemented by other drawing things.
  7. For example, Set_endpt() does nothing for Dt_rect, but is implemented by Dt_line.
  8. Date: 20 Apr 2018 (HBD CR)
  9. Author: Scott Daniels
  10. */
  11. package drawingthings
  12. import (
  13. "fmt"
  14. "encoding/json"
  15. "bitbucket.org/EScottDaniels/data_mgr"
  16. "bitbucket.org/EScottDaniels/sketch"
  17. )
  18. /*
  19. Field names must be public as we need to support json (un)packing.
  20. */
  21. type Dt_base struct {
  22. Id string // creator assigned id
  23. Kind int // one of the DT_* consts that identifies the type
  24. Colour string // colur name or rgb string
  25. Xo float64 // 'origin' point; upper left x,y or center x,y depending on thing
  26. Yo float64
  27. Scale float64 // Different things need scale info for different reasons; it's kept here
  28. Rot_angle float64 // rotation, degrees anti-clock with "3:00" being 0
  29. Rot_vertex float64 // the vertex around which rotation happens
  30. Visible bool
  31. Vis_threshold float64 // scale value below which the thing isn't painted
  32. updated bool // internal housekeeping that can't be set via json load etc.
  33. preserved_id string // default values preserved during an update
  34. preserved_kind int
  35. }
  36. /*
  37. Generic (dt) make funciton
  38. */
  39. func Mk_drawingthing(id string, kind dt_kind, xo float64, yo float64) (dt *Dt_base) {
  40. return &Dt_base{
  41. Kind: DT_BASE,
  42. Id: id,
  43. Xo: xo,
  44. Yo: yo,
  45. Colour: "#909090", // default to grey
  46. Rot_angle: 0, // no rotaion
  47. Scale: 1.0,
  48. }
  49. }
  50. // -----------------------------------------------------------------------------
  51. /*
  52. These are generic functions which fall into one of two categories:
  53. 1) dummy function that returns a nil/empty/zero value and are
  54. implemented such that they only need to be implemented in
  55. a drawingthing module if that type of thing supports the
  56. concept (e.g. Get_data() is only supported by graphs and
  57. data oriented things).
  58. 2) Functions which support management of the base class fields
  59. (e.g. setting/getting the drawingthing ID).
  60. Drawingthing modules are able to easily implement the interface
  61. by including this base structure as an unnamed field at which
  62. point they suppy only the interface functions that are needed
  63. to provide support for the thing; others are covered by the
  64. functions supplied here.
  65. */
  66. /*
  67. Contains returns true if the x,y coord passed in is within the bounding
  68. box of the thing. As a generic function, likely not suitable for many things,
  69. true is returned if the point is +/- 5 px in each direction. We expect
  70. that most things will override this.
  71. */
  72. func ( dt *Dt_base ) Contains( x float64, y float64 ) ( bool ) {
  73. if dt != nil {
  74. if x < dt.Xo - 5 || x > dt.Xo + 5 {
  75. return false
  76. }
  77. if y < dt.Yo - 5 || y > dt.Yo + 5 {
  78. return false
  79. }
  80. return true
  81. }
  82. return false
  83. }
  84. /*
  85. Get_data returns the data group associated with the drawing thing or nil
  86. if the drawing thing does not support/use data.
  87. */
  88. func (dt *Dt_base ) Get_data() ( *data_mgr.Data_group ) {
  89. return nil
  90. }
  91. /*
  92. Get_id returns the drawingthing's ID.
  93. */
  94. func (dt *Dt_base ) Get_id() ( string ) {
  95. if dt == nil {
  96. return "unknown-id"
  97. }
  98. return dt.Id
  99. }
  100. /*
  101. Get_text returns the text string associated with the drawing thing or ""
  102. if the drawing thing does not support/use data. This is a specialised
  103. form of Get_data() which relieves the caller from getting an interface
  104. and needing to sort out the type.
  105. */
  106. func (dt *Dt_base ) Get_text() ( string ) {
  107. return ""
  108. }
  109. /*
  110. Is_kind returns true if the kind passed in (DT_* const) is the same kind as the struct.
  111. */
  112. func (dt *Dt_base) Is_kind(kind int) bool {
  113. if dt == nil {
  114. return false
  115. }
  116. return dt.Kind == kind
  117. }
  118. /*
  119. Is_visible returns true if the thing's visible setting is true and the current
  120. value of scale is >= the vis_threshold value.
  121. */
  122. func (dt *Dt_base) Is_visible( scale float64 ) bool {
  123. if dt == nil {
  124. return false
  125. }
  126. return dt.Visible && ( scale >= dt.Vis_threshold )
  127. }
  128. /*
  129. Nuke will do any cleanup that is necessary.
  130. */
  131. func ( dt *Dt_base ) Nuke( sketch.Graphics_api ) {
  132. return
  133. }
  134. /*
  135. Paint causes the drawingthing to be rendered using the sketch graphics context
  136. which is passed in. Scale is used by drawing things only to determine visibility
  137. based on current display scale, and does NOT affect the rendering of the thing.
  138. */
  139. func ( dt *Dt_base ) Paint( gc sketch.Graphics_api, scale float64 ) {
  140. return
  141. }
  142. /*
  143. Rotate captures the information needed to rotate the triangle when painted.
  144. The rotation point is given as a vertex number (1, 2, 3 etc.); rotation is
  145. then computed using the coordinates of the vertex. For some drawingthings,
  146. the vertex 0 indicates the center, and for some the vertex is ignored as
  147. the thing has a single definition of rotation.
  148. */
  149. func ( dt *Dt_base ) Rotate( vertex float64, angle float64 ) {
  150. if dt == nil {
  151. return
  152. }
  153. dt.Rot_angle = angle
  154. dt.Rot_vertex = vertex
  155. dt.updated = true
  156. }
  157. /*
  158. Preserve allows the drawingthing to stash away information that it wants to
  159. ensure does not change during an update. By default we save/restore just the
  160. ID and kind. Each object may decide to do more and implement their own
  161. version of this function.
  162. */
  163. func (dt *Dt_base) Preserve() {
  164. if dt == nil {
  165. return
  166. }
  167. dt.preserved_id = dt.Id
  168. dt.preserved_kind = dt.Kind
  169. }
  170. /*
  171. Restore allows the drawing thing to restore anything preserved, and/or to force
  172. additional computations on the next paint assuming that something affecting
  173. the paint (size, location, etc.) has changed. As a default, the ID will be
  174. restored and the updated boolean will be marked true.
  175. */
  176. func (dt *Dt_base) Restore() {
  177. if dt == nil {
  178. return
  179. }
  180. dt.Id = dt.preserved_id
  181. dt.Kind = dt.preserved_kind
  182. dt.updated = true
  183. }
  184. /*
  185. Set_colur allows the drawingthing colur to be changed. For most drawingthings this is
  186. the outline or stroke colour, and for some drawing things (e.g. graphs) setting the
  187. colour likely has no effect. Cname (colouor name) can be a recognised name (e.g. green,
  188. red, or orange) or a hex rgb value in the form of either #rrggbb or 0xrrggbb.
  189. */
  190. func (dt *Dt_base) Set_colour(cname string) {
  191. if dt == nil {
  192. return
  193. }
  194. dt.Colour = cname
  195. }
  196. /*
  197. Set_data allows a new piece of data to be added to the drawing thing.
  198. Data is different for each drawing thing. For a graph data will be a data group
  199. or possibly a data set, but for a text thing, the data will likely be a string.
  200. This is a dummy function for things that don't support/use data.
  201. */
  202. func (dt *Dt_base) Set_data( data_thing interface{} ) {
  203. return
  204. }
  205. /*
  206. Set_endpt allows an x,y coordinate to be passed to the drawingthing to set/adjust
  207. the thing's concept of an endpoint. For a line, this is the second point and
  208. for multi-pointed things this probably has no effect.
  209. */
  210. func (dt *Dt_base) Set_endpt(x1 float64, y1 float64) {
  211. return
  212. }
  213. /*
  214. Set_fill allows the fill property (boolean) to be turned on or off.
  215. Passing true, sets the property and if the drawingthing has a concept
  216. of being filled, it will be filled when painted.
  217. */
  218. func (dt *Dt_base) Set_fill(state bool) {
  219. return
  220. }
  221. /*
  222. Set_fill_colour allows the fill colour to be adjusted. If the fill property is
  223. enabled (true) and the drawingthing supports the concept of being filled, the
  224. colour given will be used.
  225. */
  226. func (dt *Dt_base) Set_fill_colour(cname string) {
  227. return
  228. }
  229. /*
  230. Set_line_style allows the line style (e.g. solid, dashed) to be set for those
  231. drawingthings which support it.
  232. */
  233. func (dt *Dt_base) Set_line_style( style int ) {
  234. return
  235. }
  236. /*
  237. Set_origin allows the origin point to be changed effectively moving the object
  238. in the drawing plane. The internal updated flag is set as for some drawing things
  239. the change to the origin may cause a recomputation of other vertices.
  240. */
  241. func (dt *Dt_base) Set_origin(new_xo float64, new_yo float64) {
  242. if dt == nil {
  243. return
  244. }
  245. dt.updated = true
  246. dt.Xo = new_xo
  247. dt.Yo = new_yo
  248. }
  249. /*
  250. Set_delta_hw allows the height and width of a datathing to be changed by relative
  251. value. If the drawing thing supporst the concept of height and width, each are
  252. adjusted by adding the delta values passed to this funciton to the current height
  253. and width of the thing.
  254. */
  255. func (dt *Dt_base) Set_delta_hw( dheight float64, dwidth float64 ) {
  256. return
  257. }
  258. /*
  259. Set_delta_length allows the length of a drawing thing to be changed by a
  260. relative value. If the drawingthing supports the concept of length, it is
  261. adjusted by adding the value passed to this function.
  262. */
  263. func (dt *Dt_base) Set_delta_length( length float64 ) {
  264. return
  265. }
  266. /*
  267. Set_hw allows the absolute height and width of the drawing thing to be set
  268. provided the drawing thing supports the concept of height and width.
  269. */
  270. func (dt *Dt_base) Set_hw( height float64, width float64 ) {
  271. return
  272. }
  273. /*
  274. Set_hw allows the absolute length of the drawing thing to be set
  275. provided the drawing thing supports the concept of length.
  276. */
  277. func (dt *Dt_base) Set_length( length float64 ) {
  278. return
  279. }
  280. /*
  281. Set_rel_origin changes the origin for the DT by adding the delta values
  282. to the current origin values.
  283. */
  284. func (dt *Dt_base) Set_rel_origin(delta_xo float64, delta_yo float64) {
  285. if dt == nil {
  286. return
  287. }
  288. dt.Xo += delta_xo
  289. dt.Yo += delta_yo
  290. }
  291. /*
  292. Set_iscale sets the painting scale for the drawingthing. The value passed is
  293. added to the current setting rather than used as an absolute. Some things, like graphs,
  294. might need to reset themselves if the scale is changed.
  295. See note about scale in drawingthing.go.
  296. */
  297. func ( dt *Dt_base ) Set_iscale( increment float64 ) {
  298. if dt != nil {
  299. dt.Scale += increment
  300. dt.updated = true
  301. }
  302. }
  303. /*
  304. Set_scale sets the painting scale for the drawingthing. Some things, like graphs,
  305. might need to reset themselves if the scale is changed.
  306. See note about scale in drawingthing.go.
  307. */
  308. func ( dt *Dt_base ) Set_scale( new_scale float64 ) {
  309. if dt != nil {
  310. dt.Scale = new_scale
  311. dt.updated = true
  312. }
  313. }
  314. /*
  315. Set_vis_threshold sets the scale threshold below which a drawing
  316. thing will not be painted. If the threshold is set to 2.0, then
  317. when the current scale is < 2.0 the effect will be to hide the thing.
  318. */
  319. func ( dt *Dt_base ) Set_vis_threshold( new_t float64 ) {
  320. if dt != nil {
  321. dt.Vis_threshold = new_t
  322. }
  323. }
  324. /*
  325. Set_updated toggles the internal updated flag.
  326. */
  327. func (dt *Dt_base) Set_updated(state bool) {
  328. if dt == nil {
  329. return
  330. }
  331. dt.updated = true
  332. }
  333. /*
  334. Set_visibility allows the visible flag to be toggled. If the thing isn't visible
  335. it shouldn't paint.
  336. */
  337. func (dt *Dt_base) Set_visibility(state bool) {
  338. if dt == nil {
  339. return
  340. }
  341. dt.Visible = state
  342. }
  343. /*
  344. String implements the stringer interface allowing the object to be passed to
  345. fmt.*() functions etc. We get lazy and just bang the struct into json.
  346. */
  347. func (dt *Dt_base) String() string {
  348. if dt == nil {
  349. return "<nil>"
  350. }
  351. jb, err := json.Marshal( dt )
  352. if err == nil {
  353. return string( jb )
  354. }
  355. return fmt.Sprintf( "dt: error converting to string: %s", err )
  356. }
  357. /*
  358. Find the value in the map, and if it's there return it, else return the default.
  359. func (dt *Dt_base) update_value(data map[string]string, field string, def_val interface{}) interface{} {
  360. if dt == nil {
  361. return def_val
  362. }
  363. dv, ok := data[field] // pull data value if there
  364. if !ok {
  365. return def_val
  366. }
  367. dt.updated = true
  368. return str2value(dv, def_val)
  369. }
  370. */
  371. /*
  372. A tickle from the outside world. data contains needed information in a format
  373. that is unique to the underlying thing.
  374. */
  375. func ( dt *Dt_base ) Tickle( data interface{} ) {
  376. return
  377. }
  378. /*
  379. To_json converts the underlying drawing thing into a json blob in a string, and retruns it
  380. */
  381. func ( dt *Dt_base ) To_json( ) ( string, error ) {
  382. if dt == nil {
  383. return "{}", nil
  384. }
  385. jbytes, err := json.Marshal( dt )
  386. if err == nil {
  387. return string( jbytes ), nil
  388. } else {
  389. return "", err
  390. }
  391. }