widget.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import {
  4. Message
  5. } from 'phosphor/lib/core/messaging';
  6. import {
  7. Widget
  8. } from 'phosphor/lib/ui/widget';
  9. import {
  10. ABCWidgetFactory, DocumentRegistry
  11. } from '../docregistry';
  12. /**
  13. * The class name added to a imagewidget.
  14. */
  15. const IMAGE_CLASS = 'jp-ImageWidget';
  16. /**
  17. * A widget for images.
  18. */
  19. export
  20. class ImageWidget extends Widget {
  21. /**
  22. * Construct a new image widget.
  23. */
  24. constructor(context: DocumentRegistry.Context) {
  25. super({ node: Private.createNode() });
  26. this._context = context;
  27. this.node.tabIndex = -1;
  28. this.addClass(IMAGE_CLASS);
  29. this._onTitleChanged();
  30. context.pathChanged.connect(this._onTitleChanged, this);
  31. context.ready.then(() => {
  32. this.update();
  33. context.model.contentChanged.connect(this.update, this);
  34. context.fileChanged.connect(this.update, this);
  35. });
  36. }
  37. /**
  38. * The image widget's context.
  39. */
  40. get context(): DocumentRegistry.Context {
  41. return this._context;
  42. }
  43. /**
  44. * The scale factor for the image.
  45. */
  46. get scale(): number {
  47. return this._scale;
  48. }
  49. set scale(value: number) {
  50. if (value === this._scale) {
  51. return;
  52. }
  53. this._scale = value;
  54. let scaleNode = this.node.querySelector('div') as HTMLElement;
  55. let transform: string;
  56. transform = `scale(${value})`;
  57. scaleNode.style.transform = transform;
  58. this.update();
  59. }
  60. /**
  61. * Dispose of the resources used by the widget.
  62. */
  63. dispose(): void {
  64. if (this.isDisposed) {
  65. return;
  66. }
  67. this._context = null;
  68. super.dispose();
  69. }
  70. /**
  71. * Handle `update-request` messages for the widget.
  72. */
  73. protected onUpdateRequest(msg: Message): void {
  74. let context = this._context;
  75. if (this.isDisposed || !context.isReady) {
  76. return;
  77. }
  78. let cm = this._context.contentsModel;
  79. let content = context.model.toString();
  80. let src = `data:${cm.mimetype};${cm.format},${content}`;
  81. this.node.querySelector('img').setAttribute('src', src);
  82. }
  83. /**
  84. * Handle `'activate-request'` messages.
  85. */
  86. protected onActivateRequest(msg: Message): void {
  87. this.node.focus();
  88. }
  89. /**
  90. * Handle a change to the title.
  91. */
  92. private _onTitleChanged(): void {
  93. this.title.label = this._context.path.split('/').pop();
  94. }
  95. private _context: DocumentRegistry.Context;
  96. private _scale = 1;
  97. }
  98. /**
  99. * A widget factory for images.
  100. */
  101. export
  102. class ImageWidgetFactory extends ABCWidgetFactory<ImageWidget, DocumentRegistry.IModel> {
  103. /**
  104. * Create a new widget given a context.
  105. */
  106. protected createNewWidget(context: DocumentRegistry.IContext<DocumentRegistry.IModel>): ImageWidget {
  107. return new ImageWidget(context);
  108. }
  109. }
  110. /**
  111. * A namespace for image widget private data.
  112. */
  113. namespace Private {
  114. /**
  115. * Create the node for the image widget.
  116. */
  117. export
  118. function createNode(): HTMLElement {
  119. let node = document.createElement('div');
  120. let innerNode = document.createElement('div');
  121. let image = document.createElement('img');
  122. node.appendChild(innerNode);
  123. innerNode.appendChild(image);
  124. return node;
  125. }
  126. }