signsandsymbols.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. #Copyright ReportLab Europe Ltd. 2000-2017
  2. #see license.txt for license details
  3. #history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/graphics/widgets/signsandsymbols.py
  4. # signsandsymbols.py
  5. # A collection of new widgets
  6. # author: John Precedo (johnp@reportlab.com)
  7. __version__='3.3.0'
  8. __doc__="""This file is a collection of widgets to produce some common signs and symbols.
  9. Widgets include:
  10. - ETriangle (an equilateral triangle),
  11. - RTriangle (a right angled triangle),
  12. - Octagon,
  13. - Crossbox,
  14. - Tickbox,
  15. - SmileyFace,
  16. - StopSign,
  17. - NoEntry,
  18. - NotAllowed (the red roundel from 'no smoking' signs),
  19. - NoSmoking,
  20. - DangerSign (a black exclamation point in a yellow triangle),
  21. - YesNo (returns a tickbox or a crossbox depending on a testvalue),
  22. - FloppyDisk,
  23. - ArrowOne, and
  24. - ArrowTwo
  25. - CrossHair
  26. """
  27. from reportlab.lib import colors
  28. from reportlab.lib.validators import *
  29. from reportlab.lib.attrmap import *
  30. from reportlab.lib.utils import isStr, asUnicode
  31. from reportlab.graphics import shapes
  32. from reportlab.graphics.widgetbase import Widget
  33. from reportlab.graphics import renderPDF
  34. class _Symbol(Widget):
  35. """Abstract base widget
  36. possible attributes:
  37. 'x', 'y', 'size', 'fillColor', 'strokeColor'
  38. """
  39. _nodoc = 1
  40. _attrMap = AttrMap(
  41. x = AttrMapValue(isNumber,desc='symbol x coordinate'),
  42. y = AttrMapValue(isNumber,desc='symbol y coordinate'),
  43. dx = AttrMapValue(isNumber,desc='symbol x coordinate adjustment'),
  44. dy = AttrMapValue(isNumber,desc='symbol x coordinate adjustment'),
  45. size = AttrMapValue(isNumber),
  46. fillColor = AttrMapValue(isColorOrNone),
  47. strokeColor = AttrMapValue(isColorOrNone),
  48. strokeWidth = AttrMapValue(isNumber),
  49. )
  50. def __init__(self):
  51. assert self.__class__.__name__!='_Symbol', 'Abstract class _Symbol instantiated'
  52. self.x = self.y = self.dx = self.dy = 0
  53. self.size = 100
  54. self.fillColor = colors.red
  55. self.strokeColor = None
  56. self.strokeWidth = 0.1
  57. def demo(self):
  58. D = shapes.Drawing(200, 100)
  59. s = float(self.size)
  60. ob = self.__class__()
  61. ob.x=50
  62. ob.y=0
  63. ob.draw()
  64. D.add(ob)
  65. D.add(shapes.String(ob.x+(s/2),(ob.y-12),
  66. ob.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  67. fontSize=10))
  68. return D
  69. class ETriangle(_Symbol):
  70. """This draws an equilateral triangle."""
  71. def __init__(self):
  72. _Symbol.__init__(self)
  73. def draw(self):
  74. # general widget bits
  75. s = float(self.size) # abbreviate as we will use this a lot
  76. g = shapes.Group()
  77. # Triangle specific bits
  78. ae = s*0.125 #(ae = 'an eighth')
  79. triangle = shapes.Polygon(points = [
  80. self.x, self.y,
  81. self.x+s, self.y,
  82. self.x+(s/2),self.y+s],
  83. fillColor = self.fillColor,
  84. strokeColor = self.strokeColor,
  85. strokeWidth=s/50.)
  86. g.add(triangle)
  87. return g
  88. class RTriangle(_Symbol):
  89. """This draws a right-angled triangle.
  90. possible attributes:
  91. 'x', 'y', 'size', 'fillColor', 'strokeColor'
  92. """
  93. def __init__(self):
  94. self.x = 0
  95. self.y = 0
  96. self.size = 100
  97. self.fillColor = colors.green
  98. self.strokeColor = None
  99. def draw(self):
  100. # general widget bits
  101. s = float(self.size) # abbreviate as we will use this a lot
  102. g = shapes.Group()
  103. # Triangle specific bits
  104. ae = s*0.125 #(ae = 'an eighth')
  105. triangle = shapes.Polygon(points = [
  106. self.x, self.y,
  107. self.x+s, self.y,
  108. self.x,self.y+s],
  109. fillColor = self.fillColor,
  110. strokeColor = self.strokeColor,
  111. strokeWidth=s/50.)
  112. g.add(triangle)
  113. return g
  114. class Octagon(_Symbol):
  115. """This widget draws an Octagon.
  116. possible attributes:
  117. 'x', 'y', 'size', 'fillColor', 'strokeColor'
  118. """
  119. def __init__(self):
  120. self.x = 0
  121. self.y = 0
  122. self.size = 100
  123. self.fillColor = colors.yellow
  124. self.strokeColor = None
  125. def draw(self):
  126. # general widget bits
  127. s = float(self.size) # abbreviate as we will use this a lot
  128. g = shapes.Group()
  129. # Octagon specific bits
  130. athird=s/3
  131. octagon = shapes.Polygon(points=[self.x+athird, self.y,
  132. self.x, self.y+athird,
  133. self.x, self.y+(athird*2),
  134. self.x+athird, self.y+s,
  135. self.x+(athird*2), self.y+s,
  136. self.x+s, self.y+(athird*2),
  137. self.x+s, self.y+athird,
  138. self.x+(athird*2), self.y],
  139. strokeColor = self.strokeColor,
  140. fillColor = self.fillColor,
  141. strokeWidth=10)
  142. g.add(octagon)
  143. return g
  144. class Crossbox(_Symbol):
  145. """This draws a black box with a red cross in it - a 'checkbox'.
  146. possible attributes:
  147. 'x', 'y', 'size', 'crossColor', 'strokeColor', 'crosswidth'
  148. """
  149. _attrMap = AttrMap(BASE=_Symbol,
  150. crossColor = AttrMapValue(isColorOrNone),
  151. crosswidth = AttrMapValue(isNumber),
  152. )
  153. def __init__(self):
  154. self.x = 0
  155. self.y = 0
  156. self.size = 100
  157. self.fillColor = colors.white
  158. self.crossColor = colors.red
  159. self.strokeColor = colors.black
  160. self.crosswidth = 10
  161. def draw(self):
  162. # general widget bits
  163. s = float(self.size) # abbreviate as we will use this a lot
  164. g = shapes.Group()
  165. # crossbox specific bits
  166. box = shapes.Rect(self.x+1, self.y+1, s-2, s-2,
  167. fillColor = self.fillColor,
  168. strokeColor = self.strokeColor,
  169. strokeWidth=2)
  170. g.add(box)
  171. crossLine1 = shapes.Line(self.x+(s*0.15), self.y+(s*0.15), self.x+(s*0.85), self.y+(s*0.85),
  172. fillColor = self.crossColor,
  173. strokeColor = self.crossColor,
  174. strokeWidth = self.crosswidth)
  175. g.add(crossLine1)
  176. crossLine2 = shapes.Line(self.x+(s*0.15), self.y+(s*0.85), self.x+(s*0.85) ,self.y+(s*0.15),
  177. fillColor = self.crossColor,
  178. strokeColor = self.crossColor,
  179. strokeWidth = self.crosswidth)
  180. g.add(crossLine2)
  181. return g
  182. class Tickbox(_Symbol):
  183. """This draws a black box with a red tick in it - another 'checkbox'.
  184. possible attributes:
  185. 'x', 'y', 'size', 'tickColor', 'strokeColor', 'tickwidth'
  186. """
  187. _attrMap = AttrMap(BASE=_Symbol,
  188. tickColor = AttrMapValue(isColorOrNone),
  189. tickwidth = AttrMapValue(isNumber),
  190. )
  191. def __init__(self):
  192. self.x = 0
  193. self.y = 0
  194. self.size = 100
  195. self.tickColor = colors.red
  196. self.strokeColor = colors.black
  197. self.fillColor = colors.white
  198. self.tickwidth = 10
  199. def draw(self):
  200. # general widget bits
  201. s = float(self.size) # abbreviate as we will use this a lot
  202. g = shapes.Group()
  203. # tickbox specific bits
  204. box = shapes.Rect(self.x+1, self.y+1, s-2, s-2,
  205. fillColor = self.fillColor,
  206. strokeColor = self.strokeColor,
  207. strokeWidth=2)
  208. g.add(box)
  209. tickLine = shapes.PolyLine(points = [self.x+(s*0.15), self.y+(s*0.35), self.x+(s*0.35), self.y+(s*0.15),
  210. self.x+(s*0.35), self.y+(s*0.15), self.x+(s*0.85) ,self.y+(s*0.85)],
  211. fillColor = self.tickColor,
  212. strokeColor = self.tickColor,
  213. strokeWidth = self.tickwidth)
  214. g.add(tickLine)
  215. return g
  216. class SmileyFace(_Symbol):
  217. """This draws a classic smiley face.
  218. possible attributes:
  219. 'x', 'y', 'size', 'fillColor'
  220. """
  221. def __init__(self):
  222. _Symbol.__init__(self)
  223. self.x = 0
  224. self.y = 0
  225. self.size = 100
  226. self.fillColor = colors.yellow
  227. self.strokeColor = colors.black
  228. def draw(self):
  229. # general widget bits
  230. s = float(self.size) # abbreviate as we will use this a lot
  231. g = shapes.Group()
  232. # SmileyFace specific bits
  233. g.add(shapes.Circle(cx=self.x+(s/2), cy=self.y+(s/2), r=s/2,
  234. fillColor=self.fillColor, strokeColor=self.strokeColor,
  235. strokeWidth=max(s/38.,self.strokeWidth)))
  236. for i in (1,2):
  237. g.add(shapes.Ellipse(self.x+(s/3)*i,self.y+(s/3)*2, s/30, s/10,
  238. fillColor=self.strokeColor, strokeColor = self.strokeColor,
  239. strokeWidth=max(s/38.,self.strokeWidth)))
  240. # calculate a pointslist for the mouth
  241. # THIS IS A HACK! - don't use if there is a 'shapes.Arc'
  242. centerx=self.x+(s/2)
  243. centery=self.y+(s/2)
  244. radius=s/3
  245. yradius = radius
  246. xradius = radius
  247. startangledegrees=200
  248. endangledegrees=340
  249. degreedelta = 1
  250. pointslist = []
  251. a = pointslist.append
  252. from math import sin, cos, pi
  253. degreestoradians = pi/180.0
  254. radiansdelta = degreedelta*degreestoradians
  255. startangle = startangledegrees*degreestoradians
  256. endangle = endangledegrees*degreestoradians
  257. while endangle<startangle:
  258. endangle = endangle+2*pi
  259. angle = startangle
  260. while angle<endangle:
  261. x = centerx + cos(angle)*radius
  262. y = centery + sin(angle)*yradius
  263. a(x); a(y)
  264. angle = angle+radiansdelta
  265. # make the mouth
  266. smile = shapes.PolyLine(pointslist,
  267. fillColor = self.strokeColor,
  268. strokeColor = self.strokeColor,
  269. strokeWidth = max(s/38.,self.strokeWidth))
  270. g.add(smile)
  271. return g
  272. class StopSign(_Symbol):
  273. """This draws a (British) stop sign.
  274. possible attributes:
  275. 'x', 'y', 'size'
  276. """
  277. _attrMap = AttrMap(BASE=_Symbol,
  278. stopColor = AttrMapValue(isColorOrNone,desc='color of the word stop'),
  279. )
  280. def __init__(self):
  281. self.x = 0
  282. self.y = 0
  283. self.size = 100
  284. self.strokeColor = colors.black
  285. self.fillColor = colors.orangered
  286. self.stopColor = colors.ghostwhite
  287. def draw(self):
  288. # general widget bits
  289. s = float(self.size) # abbreviate as we will use this a lot
  290. g = shapes.Group()
  291. # stop-sign specific bits
  292. athird=s/3
  293. outerOctagon = shapes.Polygon(points=[self.x+athird, self.y,
  294. self.x, self.y+athird,
  295. self.x, self.y+(athird*2),
  296. self.x+athird, self.y+s,
  297. self.x+(athird*2), self.y+s,
  298. self.x+s, self.y+(athird*2),
  299. self.x+s, self.y+athird,
  300. self.x+(athird*2), self.y],
  301. strokeColor = self.strokeColor,
  302. fillColor = None,
  303. strokeWidth=1)
  304. g.add(outerOctagon)
  305. innerOctagon = shapes.Polygon(points=[self.x+athird+(s/75), self.y+(s/75),
  306. self.x+(s/75), self.y+athird+(s/75),
  307. self.x+(s/75), self.y+(athird*2)-(s/75),
  308. self.x+athird+(s/75), self.y+s-(s/75),
  309. self.x+(athird*2)-(s/75), (self.y+s)-(s/75),
  310. (self.x+s)-(s/75), self.y+(athird*2)-(s/75),
  311. (self.x+s)-(s/75), self.y+athird+(s/75),
  312. self.x+(athird*2)-(s/75), self.y+(s/75)],
  313. strokeColor = None,
  314. fillColor = self.fillColor,
  315. strokeWidth=0)
  316. g.add(innerOctagon)
  317. if self.stopColor:
  318. g.add(shapes.String(self.x+(s*0.5),self.y+(s*0.4),
  319. 'STOP', fillColor=self.stopColor, textAnchor='middle',
  320. fontSize=s/3, fontName="Helvetica-Bold"))
  321. return g
  322. class NoEntry(_Symbol):
  323. """This draws a (British) No Entry sign - a red circle with a white line on it.
  324. possible attributes:
  325. 'x', 'y', 'size'
  326. """
  327. _attrMap = AttrMap(BASE=_Symbol,
  328. innerBarColor = AttrMapValue(isColorOrNone,desc='color of the inner bar'),
  329. )
  330. def __init__(self):
  331. self.x = 0
  332. self.y = 0
  333. self.size = 100
  334. self.strokeColor = colors.black
  335. self.fillColor = colors.orangered
  336. self.innerBarColor = colors.ghostwhite
  337. def draw(self):
  338. # general widget bits
  339. s = float(self.size) # abbreviate as we will use this a lot
  340. g = shapes.Group()
  341. # no-entry-sign specific bits
  342. if self.strokeColor:
  343. g.add(shapes.Circle(cx = (self.x+(s/2)), cy = (self.y+(s/2)), r = s/2, fillColor = None, strokeColor = self.strokeColor, strokeWidth=1))
  344. if self.fillColor:
  345. g.add(shapes.Circle(cx = (self.x+(s/2)), cy =(self.y+(s/2)), r = ((s/2)-(s/50)), fillColor = self.fillColor, strokeColor = None, strokeWidth=0))
  346. innerBarColor = self.innerBarColor
  347. if innerBarColor:
  348. g.add(shapes.Rect(self.x+(s*0.1), self.y+(s*0.4), width=s*0.8, height=s*0.2, fillColor = innerBarColor, strokeColor = innerBarColor, strokeLineCap = 1, strokeWidth = 0))
  349. return g
  350. class NotAllowed(_Symbol):
  351. """This draws a 'forbidden' roundel (as used in the no-smoking sign).
  352. possible attributes:
  353. 'x', 'y', 'size'
  354. """
  355. _attrMap = AttrMap(BASE=_Symbol,
  356. )
  357. def __init__(self):
  358. self.x = 0
  359. self.y = 0
  360. self.size = 100
  361. self.strokeColor = colors.red
  362. self.fillColor = colors.white
  363. def draw(self):
  364. # general widget bits
  365. s = float(self.size) # abbreviate as we will use this a lot
  366. g = shapes.Group()
  367. strokeColor = self.strokeColor
  368. # not=allowed specific bits
  369. outerCircle = shapes.Circle(cx = (self.x+(s/2)), cy = (self.y+(s/2)), r = (s/2)-(s/10), fillColor = self.fillColor, strokeColor = strokeColor, strokeWidth=s/10.)
  370. g.add(outerCircle)
  371. centerx=self.x+s
  372. centery=self.y+(s/2)-(s/6)
  373. radius=s-(s/6)
  374. yradius = radius/2
  375. xradius = radius/2
  376. startangledegrees=100
  377. endangledegrees=-80
  378. degreedelta = 90
  379. pointslist = []
  380. a = pointslist.append
  381. from math import sin, cos, pi
  382. degreestoradians = pi/180.0
  383. radiansdelta = degreedelta*degreestoradians
  384. startangle = startangledegrees*degreestoradians
  385. endangle = endangledegrees*degreestoradians
  386. while endangle<startangle:
  387. endangle = endangle+2*pi
  388. angle = startangle
  389. while angle<endangle:
  390. x = centerx + cos(angle)*radius
  391. y = centery + sin(angle)*yradius
  392. a(x); a(y)
  393. angle = angle+radiansdelta
  394. crossbar = shapes.PolyLine(pointslist, fillColor = strokeColor, strokeColor = strokeColor, strokeWidth = s/10.)
  395. g.add(crossbar)
  396. return g
  397. class NoSmoking(NotAllowed):
  398. """This draws a no-smoking sign.
  399. possible attributes:
  400. 'x', 'y', 'size'
  401. """
  402. def __init__(self):
  403. NotAllowed.__init__(self)
  404. def draw(self):
  405. # general widget bits
  406. s = float(self.size) # abbreviate as we will use this a lot
  407. g = NotAllowed.draw(self)
  408. # no-smoking-sign specific bits
  409. newx = self.x+(s/2)-(s/3.5)
  410. newy = self.y+(s/2)-(s/32)
  411. cigarrette1 = shapes.Rect(x = newx, y = newy, width = (s/2), height =(s/16),
  412. fillColor = colors.ghostwhite, strokeColor = colors.gray, strokeWidth=0)
  413. newx=newx+(s/2)+(s/64)
  414. g.insert(-1,cigarrette1)
  415. cigarrette2 = shapes.Rect(x = newx, y = newy, width = (s/80), height =(s/16),
  416. fillColor = colors.orangered, strokeColor = None, strokeWidth=0)
  417. newx= newx+(s/35)
  418. g.insert(-1,cigarrette2)
  419. cigarrette3 = shapes.Rect(x = newx, y = newy, width = (s/80), height =(s/16),
  420. fillColor = colors.orangered, strokeColor = None, strokeWidth=0)
  421. newx= newx+(s/35)
  422. g.insert(-1,cigarrette3)
  423. cigarrette4 = shapes.Rect(x = newx, y = newy, width = (s/80), height =(s/16),
  424. fillColor = colors.orangered, strokeColor = None, strokeWidth=0)
  425. newx= newx+(s/35)
  426. g.insert(-1,cigarrette4)
  427. return g
  428. class DangerSign(_Symbol):
  429. """This draws a 'danger' sign: a yellow box with a black exclamation point.
  430. possible attributes:
  431. 'x', 'y', 'size', 'strokeColor', 'fillColor', 'strokeWidth'
  432. """
  433. def __init__(self):
  434. self.x = 0
  435. self.y = 0
  436. self.size = 100
  437. self.strokeColor = colors.black
  438. self.fillColor = colors.gold
  439. self.strokeWidth = self.size*0.125
  440. def draw(self):
  441. # general widget bits
  442. s = float(self.size) # abbreviate as we will use this a lot
  443. g = shapes.Group()
  444. ew = self.strokeWidth
  445. ae = s*0.125 #(ae = 'an eighth')
  446. # danger sign specific bits
  447. ew = self.strokeWidth
  448. ae = s*0.125 #(ae = 'an eighth')
  449. outerTriangle = shapes.Polygon(points = [
  450. self.x, self.y,
  451. self.x+s, self.y,
  452. self.x+(s/2),self.y+s],
  453. fillColor = None,
  454. strokeColor = self.strokeColor,
  455. strokeWidth=0)
  456. g.add(outerTriangle)
  457. innerTriangle = shapes.Polygon(points = [
  458. self.x+(s/50), self.y+(s/75),
  459. (self.x+s)-(s/50), self.y+(s/75),
  460. self.x+(s/2),(self.y+s)-(s/50)],
  461. fillColor = self.fillColor,
  462. strokeColor = None,
  463. strokeWidth=0)
  464. g.add(innerTriangle)
  465. exmark = shapes.Polygon(points=[
  466. ((self.x+s/2)-ew/2), self.y+ae*2.5,
  467. ((self.x+s/2)+ew/2), self.y+ae*2.5,
  468. ((self.x+s/2)+((ew/2))+(ew/6)), self.y+ae*5.5,
  469. ((self.x+s/2)-((ew/2))-(ew/6)), self.y+ae*5.5],
  470. fillColor = self.strokeColor,
  471. strokeColor = None)
  472. g.add(exmark)
  473. exdot = shapes.Polygon(points=[
  474. ((self.x+s/2)-ew/2), self.y+ae,
  475. ((self.x+s/2)+ew/2), self.y+ae,
  476. ((self.x+s/2)+ew/2), self.y+ae*2,
  477. ((self.x+s/2)-ew/2), self.y+ae*2],
  478. fillColor = self.strokeColor,
  479. strokeColor = None)
  480. g.add(exdot)
  481. return g
  482. class YesNo(_Symbol):
  483. """This widget draw a tickbox or crossbox depending on 'testValue'.
  484. If this widget is supplied with a 'True' or 1 as a value for
  485. testValue, it will use the tickbox widget. Otherwise, it will
  486. produce a crossbox.
  487. possible attributes:
  488. 'x', 'y', 'size', 'tickcolor', 'crosscolor', 'testValue'
  489. """
  490. _attrMap = AttrMap(BASE=_Symbol,
  491. tickcolor = AttrMapValue(isColor),
  492. crosscolor = AttrMapValue(isColor),
  493. testValue = AttrMapValue(isBoolean),
  494. )
  495. def __init__(self):
  496. self.x = 0
  497. self.y = 0
  498. self.size = 100
  499. self.tickcolor = colors.green
  500. self.crosscolor = colors.red
  501. self.testValue = 1
  502. def draw(self):
  503. if self.testValue:
  504. yn=Tickbox()
  505. yn.tickColor=self.tickcolor
  506. else:
  507. yn=Crossbox()
  508. yn.crossColor=self.crosscolor
  509. yn.x=self.x
  510. yn.y=self.y
  511. yn.size=self.size
  512. yn.draw()
  513. return yn
  514. def demo(self):
  515. D = shapes.Drawing(200, 100)
  516. yn = YesNo()
  517. yn.x = 15
  518. yn.y = 25
  519. yn.size = 70
  520. yn.testValue = 0
  521. yn.draw()
  522. D.add(yn)
  523. yn2 = YesNo()
  524. yn2.x = 120
  525. yn2.y = 25
  526. yn2.size = 70
  527. yn2.testValue = 1
  528. yn2.draw()
  529. D.add(yn2)
  530. labelFontSize = 8
  531. D.add(shapes.String(yn.x+(yn.size/2),(yn.y-(1.2*labelFontSize)),
  532. 'testValue=0', fillColor=colors.black, textAnchor='middle',
  533. fontSize=labelFontSize))
  534. D.add(shapes.String(yn2.x+(yn2.size/2),(yn2.y-(1.2*labelFontSize)),
  535. 'testValue=1', fillColor=colors.black, textAnchor='middle',
  536. fontSize=labelFontSize))
  537. labelFontSize = 10
  538. D.add(shapes.String(yn.x+85,(yn.y-20),
  539. self.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  540. fontSize=labelFontSize))
  541. return D
  542. class FloppyDisk(_Symbol):
  543. """This widget draws an icon of a floppy disk.
  544. possible attributes:
  545. 'x', 'y', 'size', 'diskcolor'
  546. """
  547. _attrMap = AttrMap(BASE=_Symbol,
  548. diskColor = AttrMapValue(isColor),
  549. )
  550. def __init__(self):
  551. self.x = 0
  552. self.y = 0
  553. self.size = 100
  554. self.diskColor = colors.black
  555. def draw(self):
  556. # general widget bits
  557. s = float(self.size) # abbreviate as we will use this a lot
  558. g = shapes.Group()
  559. # floppy disk specific bits
  560. diskBody = shapes.Rect(x=self.x, y=self.y+(s/100), width=s, height=s-(s/100),
  561. fillColor = self.diskColor,
  562. strokeColor = None,
  563. strokeWidth=0)
  564. g.add(diskBody)
  565. label = shapes.Rect(x=self.x+(s*0.1), y=(self.y+s)-(s*0.5), width=s*0.8, height=s*0.48,
  566. fillColor = colors.whitesmoke,
  567. strokeColor = None,
  568. strokeWidth=0)
  569. g.add(label)
  570. labelsplash = shapes.Rect(x=self.x+(s*0.1), y=(self.y+s)-(s*0.1), width=s*0.8, height=s*0.08,
  571. fillColor = colors.royalblue,
  572. strokeColor = None,
  573. strokeWidth=0)
  574. g.add(labelsplash)
  575. line1 = shapes.Line(x1=self.x+(s*0.15), y1=self.y+(0.6*s), x2=self.x+(s*0.85), y2=self.y+(0.6*s),
  576. fillColor = colors.black,
  577. strokeColor = colors.black,
  578. strokeWidth=0)
  579. g.add(line1)
  580. line2 = shapes.Line(x1=self.x+(s*0.15), y1=self.y+(0.7*s), x2=self.x+(s*0.85), y2=self.y+(0.7*s),
  581. fillColor = colors.black,
  582. strokeColor = colors.black,
  583. strokeWidth=0)
  584. g.add(line2)
  585. line3 = shapes.Line(x1=self.x+(s*0.15), y1=self.y+(0.8*s), x2=self.x+(s*0.85), y2=self.y+(0.8*s),
  586. fillColor = colors.black,
  587. strokeColor = colors.black,
  588. strokeWidth=0)
  589. g.add(line3)
  590. metalcover = shapes.Rect(x=self.x+(s*0.2), y=(self.y), width=s*0.5, height=s*0.35,
  591. fillColor = colors.silver,
  592. strokeColor = None,
  593. strokeWidth=0)
  594. g.add(metalcover)
  595. coverslot = shapes.Rect(x=self.x+(s*0.28), y=(self.y)+(s*0.035), width=s*0.12, height=s*0.28,
  596. fillColor = self.diskColor,
  597. strokeColor = None,
  598. strokeWidth=0)
  599. g.add(coverslot)
  600. return g
  601. class ArrowOne(_Symbol):
  602. """This widget draws an arrow (style one).
  603. possible attributes:
  604. 'x', 'y', 'size', 'fillColor'
  605. """
  606. def __init__(self):
  607. self.x = 0
  608. self.y = 0
  609. self.size = 100
  610. self.fillColor = colors.red
  611. self.strokeWidth = 0
  612. self.strokeColor = None
  613. def draw(self):
  614. # general widget bits
  615. s = float(self.size) # abbreviate as we will use this a lot
  616. g = shapes.Group()
  617. x = self.x
  618. y = self.y
  619. s2 = s/2
  620. s3 = s/3
  621. s5 = s/5
  622. g.add(shapes.Polygon(points = [
  623. x,y+s3,
  624. x,y+2*s3,
  625. x+s2,y+2*s3,
  626. x+s2,y+4*s5,
  627. x+s,y+s2,
  628. x+s2,y+s5,
  629. x+s2,y+s3,
  630. ],
  631. fillColor = self.fillColor,
  632. strokeColor = self.strokeColor,
  633. strokeWidth = self.strokeWidth,
  634. )
  635. )
  636. return g
  637. class ArrowTwo(ArrowOne):
  638. """This widget draws an arrow (style two).
  639. possible attributes:
  640. 'x', 'y', 'size', 'fillColor'
  641. """
  642. def __init__(self):
  643. self.x = 0
  644. self.y = 0
  645. self.size = 100
  646. self.fillColor = colors.blue
  647. self.strokeWidth = 0
  648. self.strokeColor = None
  649. def draw(self):
  650. # general widget bits
  651. s = float(self.size) # abbreviate as we will use this a lot
  652. g = shapes.Group()
  653. # arrow specific bits
  654. x = self.x
  655. y = self.y
  656. s2 = s/2
  657. s3 = s/3
  658. s5 = s/5
  659. s24 = s/24
  660. g.add(shapes.Polygon(
  661. points = [
  662. x,y+11*s24,
  663. x,y+13*s24,
  664. x+18.75*s24, y+13*s24,
  665. x+2*s3, y+2*s3,
  666. x+s, y+s2,
  667. x+2*s3, y+s3,
  668. x+18.75*s24, y+11*s24,
  669. ],
  670. fillColor = self.fillColor,
  671. strokeColor = self.strokeColor,
  672. strokeWidth = self.strokeWidth)
  673. )
  674. return g
  675. class CrossHair(_Symbol):
  676. """This draws an equilateral triangle."""
  677. _attrMap = AttrMap(BASE=_Symbol,
  678. innerGap = AttrMapValue(EitherOr((isString,isNumberOrNone)),desc=' gap at centre as "x%" or points or None'),
  679. )
  680. def __init__(self):
  681. self.x = self.y = self.dx = self.dy = 0
  682. self.size = 10
  683. self.fillColor = None
  684. self.strokeColor = colors.black
  685. self.strokeWidth = 0.5
  686. self.innerGap = '20%'
  687. def draw(self):
  688. # general widget bits
  689. s = float(self.size) # abbreviate as we will use this a lot
  690. g = shapes.Group()
  691. ig = self.innerGap
  692. x = self.x+self.dx
  693. y = self.y+self.dy
  694. hsize = 0.5*self.size
  695. if not ig:
  696. L = [(x-hsize,y,x+hsize,y), (x,y-hsize,x,y+hsize)]
  697. else:
  698. if isStr(ig):
  699. ig = asUnicode(ig)
  700. if ig.endswith(u'%'):
  701. gs = hsize*float(ig[:-1])/100.0
  702. else:
  703. gs = float(ig)*0.5
  704. else:
  705. gs = ig*0.5
  706. L = [(x-hsize,y,x-gs,y), (x+gs,y,x+hsize,y), (x,y-hsize,x,y-gs), (x,y+gs,x,y+hsize)]
  707. P = shapes.Path(strokeWidth=self.strokeWidth,strokeColor=self.strokeColor)
  708. for x0,y0,x1,y1 in L:
  709. P.moveTo(x0,y0)
  710. P.lineTo(x1,y1)
  711. g.add(P)
  712. return g
  713. def test():
  714. """This function produces a pdf with examples of all the signs and symbols from this file.
  715. """
  716. labelFontSize = 10
  717. D = shapes.Drawing(450,650)
  718. cb = Crossbox()
  719. cb.x = 20
  720. cb.y = 530
  721. D.add(cb)
  722. D.add(shapes.String(cb.x+(cb.size/2),(cb.y-(1.2*labelFontSize)),
  723. cb.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  724. fontSize=labelFontSize))
  725. tb = Tickbox()
  726. tb.x = 170
  727. tb.y = 530
  728. D.add(tb)
  729. D.add(shapes.String(tb.x+(tb.size/2),(tb.y-(1.2*labelFontSize)),
  730. tb.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  731. fontSize=labelFontSize))
  732. yn = YesNo()
  733. yn.x = 320
  734. yn.y = 530
  735. D.add(yn)
  736. tempstring = yn.__class__.__name__ + '*'
  737. D.add(shapes.String(yn.x+(tb.size/2),(yn.y-(1.2*labelFontSize)),
  738. tempstring, fillColor=colors.black, textAnchor='middle',
  739. fontSize=labelFontSize))
  740. D.add(shapes.String(130,6,
  741. "(The 'YesNo' widget returns a tickbox if testvalue=1, and a crossbox if testvalue=0)", fillColor=colors.black, textAnchor='middle',
  742. fontSize=labelFontSize*0.75))
  743. ss = StopSign()
  744. ss.x = 20
  745. ss.y = 400
  746. D.add(ss)
  747. D.add(shapes.String(ss.x+(ss.size/2), ss.y-(1.2*labelFontSize),
  748. ss.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  749. fontSize=labelFontSize))
  750. ne = NoEntry()
  751. ne.x = 170
  752. ne.y = 400
  753. D.add(ne)
  754. D.add(shapes.String(ne.x+(ne.size/2),(ne.y-(1.2*labelFontSize)),
  755. ne.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  756. fontSize=labelFontSize))
  757. sf = SmileyFace()
  758. sf.x = 320
  759. sf.y = 400
  760. D.add(sf)
  761. D.add(shapes.String(sf.x+(sf.size/2),(sf.y-(1.2*labelFontSize)),
  762. sf.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  763. fontSize=labelFontSize))
  764. ds = DangerSign()
  765. ds.x = 20
  766. ds.y = 270
  767. D.add(ds)
  768. D.add(shapes.String(ds.x+(ds.size/2),(ds.y-(1.2*labelFontSize)),
  769. ds.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  770. fontSize=labelFontSize))
  771. na = NotAllowed()
  772. na.x = 170
  773. na.y = 270
  774. D.add(na)
  775. D.add(shapes.String(na.x+(na.size/2),(na.y-(1.2*labelFontSize)),
  776. na.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  777. fontSize=labelFontSize))
  778. ns = NoSmoking()
  779. ns.x = 320
  780. ns.y = 270
  781. D.add(ns)
  782. D.add(shapes.String(ns.x+(ns.size/2),(ns.y-(1.2*labelFontSize)),
  783. ns.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  784. fontSize=labelFontSize))
  785. a1 = ArrowOne()
  786. a1.x = 20
  787. a1.y = 140
  788. D.add(a1)
  789. D.add(shapes.String(a1.x+(a1.size/2),(a1.y-(1.2*labelFontSize)),
  790. a1.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  791. fontSize=labelFontSize))
  792. a2 = ArrowTwo()
  793. a2.x = 170
  794. a2.y = 140
  795. D.add(a2)
  796. D.add(shapes.String(a2.x+(a2.size/2),(a2.y-(1.2*labelFontSize)),
  797. a2.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  798. fontSize=labelFontSize))
  799. fd = FloppyDisk()
  800. fd.x = 320
  801. fd.y = 140
  802. D.add(fd)
  803. D.add(shapes.String(fd.x+(fd.size/2),(fd.y-(1.2*labelFontSize)),
  804. fd.__class__.__name__, fillColor=colors.black, textAnchor='middle',
  805. fontSize=labelFontSize))
  806. renderPDF.drawToFile(D, 'signsandsymbols.pdf', 'signsandsymbols.py')
  807. print('wrote file: signsandsymbols.pdf')
  808. if __name__=='__main__':
  809. test()