OtherTool.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  1. using PaintDotNet.SystemLayer;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using System.Windows.Forms;
  11. namespace PaintDotNet.Annotation.Other
  12. {
  13. /// <summary>
  14. /// 没用到,先放着
  15. /// </summary>
  16. public class OtherTool : IDisposable
  17. {
  18. private ImageResource toolBarImage;
  19. private Cursor cursor;
  20. private int mouseDown = 0; // incremented for every MouseDown, decremented for every MouseUp
  21. private int ignoreMouseMove = 0; // when >0, MouseMove is ignored and then this is decremented
  22. protected Cursor handCursor;
  23. protected Cursor handCursorMouseDown;
  24. protected Cursor handCursorInvalid;
  25. private Cursor panOldCursor;
  26. private Point lastMouseXY;
  27. private Point lastPanMouseXY;
  28. private bool panMode = false; // 'true' when the user is holding down the spacebar
  29. private bool panTracking = false; // 'true' when panMode is true, and when the mouse is down (which is when MouseMove should do panning)
  30. private ISurfaceBox documentWorkspace;
  31. private bool active = false;
  32. protected bool autoScroll = true;
  33. private Hashtable keysThatAreDown = new Hashtable();
  34. private MouseButtons lastButton = MouseButtons.None;
  35. private int mouseEnter; // increments on MouseEnter, decrements on MouseLeave. The MouseLeave event is ONLY raised when this value decrements to 0, and MouseEnter is ONLY raised when this value increments to 1
  36. public ISurfaceBox DocumentWorkspace
  37. {
  38. get
  39. {
  40. return this.documentWorkspace;
  41. }
  42. }
  43. private sealed class KeyTimeInfo
  44. {
  45. public DateTime KeyDownTime;
  46. public DateTime LastKeyPressPulse;
  47. private int repeats = 0;
  48. public int Repeats
  49. {
  50. get
  51. {
  52. return repeats;
  53. }
  54. set
  55. {
  56. repeats = value;
  57. }
  58. }
  59. public KeyTimeInfo()
  60. {
  61. KeyDownTime = DateTime.Now;
  62. LastKeyPressPulse = KeyDownTime;
  63. }
  64. }
  65. /// <summary>
  66. /// Tells you whether the tool is "active" or not. If the tool is not active
  67. /// it is not safe to call any other method besides PerformActivate. All
  68. /// properties are safe to get values from.
  69. /// </summary>
  70. public bool Active
  71. {
  72. get
  73. {
  74. return this.active;
  75. }
  76. }
  77. public bool IsMouseDown
  78. {
  79. get
  80. {
  81. return this.mouseDown > 0;
  82. }
  83. }
  84. /// <summary>
  85. /// Gets a flag that determines whether the Tool is deactivated while the current
  86. /// layer is changing, and then reactivated afterwards.
  87. /// </summary>
  88. /// <remarks>
  89. /// This property is queried every time the ActiveLayer property of DocumentWorkspace
  90. /// is changed. If false is returned, then the tool is not deactivated during the
  91. /// layer change and must manually maintain coherency.
  92. /// </remarks>
  93. public virtual bool DeactivateOnLayerChange
  94. {
  95. get
  96. {
  97. return true;
  98. }
  99. }
  100. /// <summary>
  101. /// Tells you which keys are pressed
  102. /// </summary>
  103. public Keys ModifierKeys
  104. {
  105. get
  106. {
  107. return Control.ModifierKeys;
  108. }
  109. }
  110. /// <summary>
  111. /// Represents the Image that is displayed in the toolbar.
  112. /// </summary>
  113. public ImageResource Image
  114. {
  115. get
  116. {
  117. return this.toolBarImage;
  118. }
  119. }
  120. public event EventHandler CursorChanging;
  121. protected virtual void OnCursorChanging()
  122. {
  123. if (CursorChanging != null)
  124. {
  125. CursorChanging(this, EventArgs.Empty);
  126. }
  127. }
  128. public event EventHandler CursorChanged;
  129. protected virtual void OnCursorChanged()
  130. {
  131. if (CursorChanged != null)
  132. {
  133. CursorChanged(this, EventArgs.Empty);
  134. }
  135. }
  136. /// <summary>
  137. /// The Cursor that is displayed when this Tool is active and the
  138. /// mouse cursor is inside the document view.
  139. /// </summary>
  140. public Cursor Cursor
  141. {
  142. get
  143. {
  144. return this.cursor;
  145. }
  146. set
  147. {
  148. OnCursorChanging();
  149. this.cursor = value;
  150. OnCursorChanged();
  151. }
  152. }
  153. /// <summary>
  154. /// Specifies whether or not an inherited tool should take Ink commands
  155. /// </summary>
  156. protected virtual bool SupportsInk
  157. {
  158. get
  159. {
  160. return false;
  161. }
  162. }
  163. // Methods to send messages to this class
  164. public void PerformActivate()
  165. {
  166. Activate();
  167. }
  168. public void PerformDeactivate()
  169. {
  170. Deactivate();
  171. }
  172. private bool IsOverflow(MouseEventArgs e)
  173. {
  174. PointF clientPt = DocumentWorkspace.DocumentToClient(new PointF(e.X, e.Y));
  175. return clientPt.X < -16384 || clientPt.Y < -16384;
  176. }
  177. public bool IsMouseEntered
  178. {
  179. get
  180. {
  181. return this.mouseEnter > 0;
  182. }
  183. }
  184. public void PerformMouseEnter()
  185. {
  186. MouseEnter();
  187. }
  188. private void MouseEnter()
  189. {
  190. ++this.mouseEnter;
  191. if (this.mouseEnter == 1)
  192. {
  193. OnMouseEnter();
  194. }
  195. }
  196. protected virtual void OnMouseEnter()
  197. {
  198. }
  199. public void PerformMouseLeave()
  200. {
  201. MouseLeave();
  202. }
  203. private void MouseLeave()
  204. {
  205. if (this.mouseEnter == 1)
  206. {
  207. this.mouseEnter = 0;
  208. OnMouseLeave();
  209. }
  210. else
  211. {
  212. this.mouseEnter = Math.Max(0, this.mouseEnter - 1);
  213. }
  214. }
  215. protected virtual void OnMouseLeave()
  216. {
  217. }
  218. public void PerformMouseMove(MouseEventArgs e)
  219. {
  220. if (IsOverflow(e))
  221. {
  222. return;
  223. }
  224. MouseMove(e);
  225. }
  226. public void PerformMouseDown(MouseEventArgs e)
  227. {
  228. if (IsOverflow(e))
  229. {
  230. return;
  231. }
  232. MouseDown(e);
  233. }
  234. public void PerformMouseUp(MouseEventArgs e)
  235. {
  236. if (IsOverflow(e))
  237. {
  238. return;
  239. }
  240. MouseUp(e);
  241. }
  242. public void PerformKeyUp(KeyEventArgs e)
  243. {
  244. KeyUp(e);
  245. }
  246. public void PerformKeyDown(KeyEventArgs e)
  247. {
  248. KeyDown(e);
  249. }
  250. public void PerformClick()
  251. {
  252. Click();
  253. }
  254. public void PerformPulse()
  255. {
  256. Pulse();
  257. }
  258. public void PerformPaste(IDataObject data, out bool handled)
  259. {
  260. Paste(data, out handled);
  261. }
  262. public void PerformPasteQuery(IDataObject data, out bool canHandle)
  263. {
  264. PasteQuery(data, out canHandle);
  265. }
  266. private void Activate()
  267. {
  268. Debug.Assert(this.active != true, "already active!");
  269. this.active = true;
  270. this.handCursor = new Cursor(PdnResources.GetResourceStream("Cursors.PanToolCursor.cur"));
  271. this.handCursorMouseDown = new Cursor(PdnResources.GetResourceStream("Cursors.PanToolCursorMouseDown.cur"));
  272. this.handCursorInvalid = new Cursor(PdnResources.GetResourceStream("Cursors.PanToolCursorInvalid.cur"));
  273. this.panTracking = false;
  274. this.panMode = false;
  275. this.mouseDown = 0;
  276. OnActivate();
  277. }
  278. void FinishedHistoryStepGroup(object sender, EventArgs e)
  279. {
  280. OnFinishedHistoryStepGroup();
  281. }
  282. protected virtual void OnFinishedHistoryStepGroup()
  283. {
  284. }
  285. /// <summary>
  286. /// This method is called when the tool is being activated; that is, when the
  287. /// user has chosen to use this tool by clicking on it on a toolbar.
  288. /// </summary>
  289. protected virtual void OnActivate()
  290. {
  291. }
  292. private void Deactivate()
  293. {
  294. this.active = false;
  295. OnDeactivate();
  296. if (this.handCursor != null)
  297. {
  298. this.handCursor.Dispose();
  299. this.handCursor = null;
  300. }
  301. if (this.handCursorMouseDown != null)
  302. {
  303. this.handCursorMouseDown.Dispose();
  304. this.handCursorMouseDown = null;
  305. }
  306. if (this.handCursorInvalid != null)
  307. {
  308. this.handCursorInvalid.Dispose();
  309. this.handCursorInvalid = null;
  310. }
  311. }
  312. /// <summary>
  313. /// This method is called when the tool is being deactivated; that is, when the
  314. /// user has chosen to use another tool by clicking on another tool on a
  315. /// toolbar.
  316. /// </summary>
  317. protected virtual void OnDeactivate()
  318. {
  319. }
  320. private void MouseMove(MouseEventArgs e)
  321. {
  322. if (this.ignoreMouseMove > 0)
  323. {
  324. --this.ignoreMouseMove;
  325. }
  326. else if (this.panTracking && e.Button == MouseButtons.Left)
  327. {
  328. // Pan the document, using Stylus coordinates. This is done in
  329. // MouseMove instead of StylusMove because StylusMove is
  330. // asynchronous, and would not 'feel' right (pan motions would
  331. // stack up)
  332. Point position = new Point(e.X, e.Y);
  333. RectangleF visibleRect = DocumentWorkspace.GetVisibleDocumentRectangleF();
  334. PointF visibleCenterPt = new PointF((visibleRect.Left + visibleRect.Right) / 2, (visibleRect.Top + visibleRect.Bottom) / 2);
  335. PointF delta = new PointF(e.X - lastPanMouseXY.X, e.Y - lastPanMouseXY.Y);
  336. PointF newScroll = DocumentWorkspace.GetDocumentScrollPositionF();
  337. if (delta.X != 0 || delta.Y != 0)
  338. {
  339. newScroll.X -= delta.X;
  340. newScroll.Y -= delta.Y;
  341. lastPanMouseXY = new Point(e.X, e.Y);
  342. lastPanMouseXY.X -= (int)Math.Truncate(delta.X);
  343. lastPanMouseXY.Y -= (int)Math.Truncate(delta.Y);
  344. ++this.ignoreMouseMove; // setting DocumentScrollPosition incurs a MouseMove event. ignore it prevents 'jittering' at non-integral zoom levels (like, say, 743%)
  345. DocumentWorkspace.SetDocumentScrollPositionF(newScroll);
  346. Update();
  347. }
  348. }
  349. else if (!this.panMode)
  350. {
  351. OnMouseMove(e);
  352. }
  353. this.lastMouseXY = new Point(e.X, e.Y);
  354. this.lastButton = e.Button;
  355. }
  356. /// <summary>
  357. /// This method is called when the Tool is active and the mouse is moving within
  358. /// the document canvas area.
  359. /// </summary>
  360. /// <param name="e">Contains information about where the mouse cursor is, in document coordinates.</param>
  361. public virtual void OnMouseMove(MouseEventArgs e)
  362. {
  363. if (this.panMode || this.mouseDown > 0)
  364. {
  365. ScrollIfNecessary(new PointF(e.X, e.Y));
  366. }
  367. }
  368. private void MouseDown(MouseEventArgs e)
  369. {
  370. ++this.mouseDown;
  371. if (this.panMode)
  372. {
  373. this.panTracking = true;
  374. this.lastPanMouseXY = new Point(e.X, e.Y);
  375. if (this.CanPan())
  376. {
  377. this.Cursor = this.handCursorMouseDown;
  378. }
  379. }
  380. else
  381. {
  382. OnMouseDown(e);
  383. }
  384. this.lastMouseXY = new Point(e.X, e.Y);
  385. }
  386. /// <summary>
  387. /// This method is called when the Tool is active and a mouse button has been
  388. /// pressed within the document area.
  389. /// </summary>
  390. /// <param name="e">Contains information about where the mouse cursor is, in document coordinates, and which mouse buttons were pressed.</param>
  391. public virtual void OnMouseDown(MouseEventArgs e)
  392. {
  393. this.lastButton = e.Button;
  394. }
  395. public void MouseUp(MouseEventArgs e)
  396. {
  397. --this.mouseDown;
  398. if (!this.panMode)
  399. {
  400. OnMouseUp(e);
  401. }
  402. this.lastMouseXY = new Point(e.X, e.Y);
  403. }
  404. /// <summary>
  405. /// This method is called when the Tool is active and a mouse button has been
  406. /// released within the document area.
  407. /// </summary>
  408. /// <param name="e">Contains information about where the mouse cursor is, in document coordinates, and which mouse buttons were released.</param>
  409. public virtual void OnMouseUp(MouseEventArgs e)
  410. {
  411. this.lastButton = e.Button;
  412. }
  413. private void Click()
  414. {
  415. OnClick();
  416. }
  417. /// <summary>
  418. /// This method is called when the Tool is active and a mouse button has been
  419. /// clicked within the document area. If you need more specific information,
  420. /// such as where the mouse was clicked and which button was used, respond to
  421. /// the MouseDown/MouseUp events.
  422. /// </summary>
  423. protected virtual void OnClick()
  424. {
  425. }
  426. private static DateTime lastToolSwitch = DateTime.MinValue;
  427. // if we are pressing 'S' to switch to the selection tools, then consecutive
  428. // presses of 'S' should switch to the next selection tol in the list. however,
  429. // if we wait awhile then pressing 'S' should go to the *first* selection
  430. // tool. 'awhile' is defined by this variable.
  431. private static readonly TimeSpan toolSwitchReset = new TimeSpan(0, 0, 0, 2, 0);
  432. private const char decPenSizeShortcut = '[';
  433. private const char decPenSizeBy5Shortcut = (char)27; // Ctrl [ but must also test that Ctrl is down
  434. private const char incPenSizeShortcut = ']';
  435. private const char incPenSizeBy5Shortcut = (char)29; // Ctrl ] but must also test that Ctrl is down
  436. private const char swapColorsShortcut = 'x';
  437. private const char swapPrimarySecondaryChoice = 'c';
  438. private char[] wildShortcuts = new char[] { ',', '.', '/' };
  439. // Return true if the key is handled, false if not.
  440. protected virtual bool OnWildShortcutKey(int ordinal)
  441. {
  442. return false;
  443. }
  444. private DateTime lastKeyboardMove = DateTime.MinValue;
  445. private void KeyPress(Keys key)
  446. {
  447. OnKeyPress(key);
  448. }
  449. /// <summary>
  450. /// This method is called when the tool is active and a keyboard key is pressed
  451. /// and released that is not representable with a regular Unicode chararacter.
  452. /// An example would be the arrow keys.
  453. /// </summary>
  454. protected virtual void OnKeyPress(Keys key)
  455. {
  456. /**
  457. Point dir = Point.Empty;
  458. if (key != lastKey)
  459. {
  460. lastKeyboardMove = DateTime.MinValue;
  461. }
  462. lastKey = key;
  463. switch (key)
  464. {
  465. case Keys.Left:
  466. --dir.X;
  467. break;
  468. case Keys.Right:
  469. ++dir.X;
  470. break;
  471. case Keys.Up:
  472. --dir.Y;
  473. break;
  474. case Keys.Down:
  475. ++dir.Y;
  476. break;
  477. }
  478. if (!dir.Equals(Point.Empty))
  479. {
  480. long span = DateTime.Now.Ticks - lastKeyboardMove.Ticks;
  481. if ((span * 4) > TimeSpan.TicksPerSecond)
  482. {
  483. keyboardMoveRepeats = 0;
  484. keyboardMoveSpeed = 1;
  485. }
  486. else
  487. {
  488. keyboardMoveRepeats++;
  489. if (keyboardMoveRepeats > 15 && (keyboardMoveRepeats % 4) == 0)
  490. {
  491. keyboardMoveSpeed++;
  492. }
  493. }
  494. lastKeyboardMove = DateTime.Now;
  495. int offset = (int)(Math.Ceiling(DocumentWorkspace.GetRatio()) * (double)keyboardMoveSpeed);//ScaleFactor.
  496. Cursor.Position = new Point(Cursor.Position.X + offset * dir.X, Cursor.Position.Y + offset * dir.Y);
  497. Point location = DocumentWorkspace.PointToScreenFromTool(Point.Truncate(DocumentWorkspace.DocumentToClient(PointF.Empty)));
  498. PointF stylusLocF = new PointF((float)Cursor.Position.X - (float)location.X, (float)Cursor.Position.Y - (float)location.Y);
  499. Point stylusLoc = new Point(Cursor.Position.X - location.X, Cursor.Position.Y - location.Y);
  500. stylusLoc = DocumentWorkspace.UnscalePoint(stylusLoc);
  501. stylusLocF = DocumentWorkspace.UnscalePoint(stylusLocF);
  502. DocumentWorkspace.PerformDocumentMouseMove(new MouseEventArgs(lastButton, 1, stylusLoc.X, stylusLoc.Y, 0));
  503. }**/
  504. }
  505. public static Rectangle RoundRectangle(RectangleF rectF)
  506. {
  507. float left = (float)Math.Floor(rectF.Left);
  508. float top = (float)Math.Floor(rectF.Top);
  509. float right = (float)Math.Ceiling(rectF.Right);
  510. float bottom = (float)Math.Ceiling(rectF.Bottom);
  511. return Rectangle.Truncate(RectangleF.FromLTRB(left, top, right, bottom));
  512. }
  513. private bool CanPan()
  514. {
  515. //Rectangle vis = RoundRectangle(DocumentWorkspace.GetVisibleDocumentRectangleF());
  516. //vis.Intersect(Document.Bounds);
  517. //if (vis == Document.Bounds)
  518. //{
  519. // return false;
  520. //}
  521. //else
  522. {
  523. return true;
  524. }
  525. }
  526. private void KeyUp(KeyEventArgs e)
  527. {
  528. if (this.panMode)
  529. {
  530. this.panMode = false;
  531. this.panTracking = false;
  532. this.Cursor = this.panOldCursor;
  533. this.panOldCursor = null;
  534. e.Handled = true;
  535. }
  536. OnKeyUp(e);
  537. }
  538. /// <summary>
  539. /// This method is called when the tool is active and a keyboard key is pressed.
  540. /// If you respond to the keyboard key, set e.Handled to true.
  541. /// </summary>
  542. protected virtual void OnKeyUp(KeyEventArgs e)
  543. {
  544. keysThatAreDown.Clear();
  545. }
  546. private void KeyDown(KeyEventArgs e)
  547. {
  548. OnKeyDown(e);
  549. }
  550. /// <summary>
  551. /// This method is called when the tool is active and a keyboard key is released
  552. /// Before responding, check that e.Handled is false, and if you then respond to
  553. /// the keyboard key, set e.Handled to true.
  554. /// </summary>
  555. protected virtual void OnKeyDown(KeyEventArgs e)
  556. {
  557. if (!e.Handled)
  558. {
  559. if (!keysThatAreDown.Contains(e.KeyData))
  560. {
  561. keysThatAreDown.Add(e.KeyData, new KeyTimeInfo());
  562. }
  563. if (!this.IsMouseDown &&
  564. !this.panMode &&
  565. e.KeyCode == Keys.Space)
  566. {
  567. this.panMode = true;
  568. this.panOldCursor = this.Cursor;
  569. if (CanPan())
  570. {
  571. this.Cursor = this.handCursor;
  572. }
  573. else
  574. {
  575. this.Cursor = this.handCursorInvalid;
  576. }
  577. }
  578. // arrow keys are processed in another way
  579. // we get their KeyDown but no KeyUp, so they can not be handled
  580. // by our normal methods
  581. OnKeyPress(e.KeyData);
  582. }
  583. }
  584. private void SelectionChanging()
  585. {
  586. OnSelectionChanging();
  587. }
  588. /// <summary>
  589. /// This method is called when the Tool is active and the selection area is
  590. /// about to be changed.
  591. /// </summary>
  592. protected virtual void OnSelectionChanging()
  593. {
  594. }
  595. private void SelectionChanged()
  596. {
  597. OnSelectionChanged();
  598. }
  599. /// <summary>
  600. /// This method is called when the Tool is active and the selection area has
  601. /// been changed.
  602. /// </summary>
  603. protected virtual void OnSelectionChanged()
  604. {
  605. }
  606. private void PasteQuery(IDataObject data, out bool canHandle)
  607. {
  608. OnPasteQuery(data, out canHandle);
  609. }
  610. /// <summary>
  611. /// This method is called when the system is querying a tool as to whether
  612. /// it can handle a pasted object.
  613. /// </summary>
  614. /// <param name="data">
  615. /// The clipboard data that was pasted by the user that should be inspected.
  616. /// </param>
  617. /// <param name="canHandle">
  618. /// <b>true</b> if the data can be handled by the tool, <b>false</b> if not.
  619. /// </param>
  620. /// <remarks>
  621. /// If you do not set canHandle to <b>true</b> then the tool will not be
  622. /// able to respond to the Edit menu's Paste item.
  623. /// </remarks>
  624. protected virtual void OnPasteQuery(IDataObject data, out bool canHandle)
  625. {
  626. canHandle = false;
  627. }
  628. private void Paste(IDataObject data, out bool handled)
  629. {
  630. OnPaste(data, out handled);
  631. }
  632. /// <summary>
  633. /// This method is called when the user invokes a paste operation. Tools get
  634. /// the first chance to handle this data.
  635. /// </summary>
  636. /// <param name="data">
  637. /// The data that was pasted by the user.
  638. /// </param>
  639. /// <param name="handled">
  640. /// <b>true</b> if the data was handled and pasted, <b>false</b> if not.
  641. /// </param>
  642. /// <remarks>
  643. /// If you do not set handled to <b>true</b> the event will be passed to the
  644. /// global paste handler.
  645. /// </remarks>
  646. protected virtual void OnPaste(IDataObject data, out bool handled)
  647. {
  648. handled = false;
  649. }
  650. private void Pulse()
  651. {
  652. OnPulse();
  653. }
  654. /// <summary>
  655. /// This method is called many times per second, called by the DocumentWorkspace.
  656. /// </summary>
  657. protected virtual void OnPulse()
  658. {
  659. if (this.panTracking && this.lastButton == MouseButtons.Right)
  660. {
  661. /**
  662. Point position = this.lastMouseXY;
  663. RectangleF visibleRect = DocumentWorkspace.GetVisibleDocumentRectangleF();
  664. PointF visibleCenterPt = new PointF((visibleRect.Left + visibleRect.Right) / 2, (visibleRect.Top + visibleRect.Bottom) / 2);
  665. PointF delta = new PointF(position.X - visibleCenterPt.X, position.Y - visibleCenterPt.Y);
  666. PointF newScroll = DocumentWorkspace.GetDocumentScrollPositionF();
  667. if (delta.X != 0 || delta.Y != 0)
  668. {
  669. newScroll.X += delta.X;
  670. newScroll.Y += delta.Y;
  671. ++this.ignoreMouseMove; // setting DocumentScrollPosition incurs a MouseMove event. ignore it prevents 'jittering' at non-integral zoom levels (like, say, 743%)
  672. UI.SuspendControlPainting(DocumentWorkspace.GetThis());
  673. DocumentWorkspace.SetDocumentScrollPositionF(newScroll);
  674. this.trackingNub.Location = Utility.GetRectangleCenter(DocumentWorkspace.GetVisibleDocumentRectangleF());
  675. UI.ResumeControlPainting(DocumentWorkspace.GetThis());
  676. DocumentWorkspace.InvalidateFromTool(true);
  677. Update();
  678. }**/
  679. }
  680. }
  681. protected bool ScrollIfNecessary(PointF position)
  682. {
  683. if (!autoScroll || !CanPan())
  684. {
  685. return false;
  686. }
  687. RectangleF visible = DocumentWorkspace.GetVisibleDocumentRectangleF();
  688. PointF lastScrollPosition = DocumentWorkspace.GetDocumentScrollPositionF();
  689. PointF delta = PointF.Empty;
  690. PointF zoomedPoint = PointF.Empty;
  691. zoomedPoint.X = ((visible.Left + visible.Right) / 2.0f + 1.02f * (position.X - (visible.Left + visible.Right) / 2.0f));
  692. zoomedPoint.Y = ((visible.Top + visible.Bottom) / 2.0f + 1.02f * (position.Y - (visible.Top + visible.Bottom) / 2.0f));
  693. if (zoomedPoint.X < visible.Left)
  694. {
  695. delta.X = zoomedPoint.X - visible.Left;
  696. }
  697. else if (zoomedPoint.X > visible.Right)
  698. {
  699. delta.X = zoomedPoint.X - visible.Right;
  700. }
  701. if (zoomedPoint.Y < visible.Top)
  702. {
  703. delta.Y = zoomedPoint.Y - visible.Top;
  704. }
  705. else if (zoomedPoint.Y > visible.Bottom)
  706. {
  707. delta.Y = zoomedPoint.Y - visible.Bottom;
  708. }
  709. if (!delta.IsEmpty)
  710. {
  711. PointF newScrollPosition = new PointF(lastScrollPosition.X + delta.X, lastScrollPosition.Y + delta.Y);
  712. DocumentWorkspace.SetDocumentScrollPositionF(newScrollPosition);
  713. Update();
  714. return true;
  715. }
  716. else
  717. {
  718. return false;
  719. }
  720. }
  721. private void SelectionChangingHandler(object sender, EventArgs e)
  722. {
  723. OnSelectionChanging();
  724. }
  725. private void SelectionChangedHandler(object sender, EventArgs e)
  726. {
  727. OnSelectionChanged();
  728. }
  729. protected void Update()
  730. {
  731. DocumentWorkspace.Update();
  732. }
  733. // NOTE: Your constructor must be able to run successfully with a documentWorkspace
  734. // of null. This is sent in while the DocumentControl static constructor
  735. // class is building a list of ToolInfo instances, so that it may construct
  736. // the list without having to also construct a DocumentControl.
  737. public OtherTool(ISurfaceBox documentWorkspace,
  738. ImageResource toolBarImage,
  739. string name,
  740. string helpText,
  741. char hotKey,
  742. bool skipIfActiveOnHotKey)
  743. {
  744. this.documentWorkspace = documentWorkspace;
  745. this.toolBarImage = toolBarImage;
  746. }
  747. public event EventHandler Disposed;
  748. private void OnDisposed()
  749. {
  750. if (Disposed != null)
  751. {
  752. Disposed(this, EventArgs.Empty);
  753. }
  754. }
  755. public void Dispose()
  756. {
  757. }
  758. }
  759. }