DocumentViewer Commands

Summary

The DocumentViewer uses a command system to perform actions. Each command is a data structure that contains the unique name of the command, whether it can run at the current state of the Document Viewer, optional arguments and results. DocumentViewerCommands manages the commands of the DocumentViewer and can be accessed by the DocumentViewer.Commands property.

Commands are generally tied to a user interface element in the application. The command properties can be used to enable or disable the element (if the command cannot be run at this time), set its state (for example, a checked box), and run the action when the user select the element (such as clicking on a button or a menu item).

Purpose of Using Commands

The DocumentViewer contains many parts that must be kept synchronized. These parts use public LEADTOOLS classes and controls such as the ImageViewer class or the AnnAutomation class, and all actions are performed using the public and documented properties and methods of the classes.

For example, the application has a menu item that sets the current interactive mode of the view to Pan/Zoom.

Pan/Zoom is one of the interactive modes added to the DocumentViewer by default. Its ID is ImageViewerInteractiveMode.PanZoomModeId. Here are the steps required:

How to Implement a Low-Level Command System

First, the application should update the enabled/disabled state of the element as follows:

  • If the document viewer does not have a document set, then the element must be disabled
  • If the current interactive mode is already Pan/Zoom, then the element must be disabled or checked and should not be invoked. This example will disable the element

The above can be performed using this code snippet:

JavaScript Example
function updatePanZoomUIState() { 
   // First test 
   $("#panZoomElement").prop("disabled", !documentViewer.hasDocument); 
   if (documentViewer.hasDocument) { 
      // Find the Pan/Zoom interactive mode, see if it is already enabled 
      var panZoom = documentViewer.view.imageViewer.interactiveModes.findById(lt.Controls.ImageViewerInteractiveMode.pPanZoomMode); 
      // Second test, see if the mode is already enabled 
      $("#panZoomElement").prop("disabled", panZoom.isEnabled); 
   } 
} 

Next, when the user clicks the Pan/Zoom menu item, the application must perform the following:

  • One cannot just call ImageViewerInteractiveModes.EnableById since this will disable all the other interactive modes. The developer has to keep Annotations and Page Links modes enabled because those can be enabled with Pan/Zoom. When the user clicks an annotation object, it should be automated. When the user clicks on a page link, it must run. Pan and zoom should only happen when the user clicks outside those objects. To accomplish this, enumerate all of the modes to disable all except Pan/Zoom, Annotations, and Page Links

  • If the annotations mode is used, then cancel any current designers (for example, if the user is in the middle of a multi-click operation to draw a new polyline) and set the current object ID in the toolbar back to Select.

  • Finally, call UpdatePanZoomUIState again to disable the menu item

The above can be performed using this code snippet:

JavaScript Example
function setPanZoom() { 
   // First action 
   for (var i = 0; i < documentViewer.view.imageViewer.count; i++) { 
      var mode = documentViewer.view.imageViewer.interactiveModes[i]; { 
      mode.isEnabled = 
         mode.id == lt.Controls.ImageViewerInteractiveMode.panZoomMode || 
         mode.id == lt.Documents.UI.DocumentViewer.annotationsInteractiveModeId || 
         mode.id == lt.Documents.UI.DocumentViewer.pageLinksInteractiveModeId; 
   } 
   // Second action 
   // We cannot just call .automation, the annotations might not be loaded yet, so we must check for that 
   if(documentViewer.annotations != null && documentViewer.annotations.automation != null) { 
      documentViewer.annotations.automation.cancel(); 
      documentViewer.annotations.automationManager.currentObjectId = lt.Annotations.Core.AnnObject.selectObjectId; 
   } 
   // Third action 
   updatePanZoomUIState(); 
} 

How to Implement a High-Level Command System

The main advantage of implementing a high-level command system is that LEADTOOLS handles the command "plumbing". LEADTOOLS provides several built-in commands that can simplify code and reduce development time. The built-in commands handle more complex actions cleanly and ensure that all parts of the DocumentViewer are kept in sync. All commands are identified by unique simple string constants, so binding built-in commands to the user interface is easy.

The DocumentViewer comes with a built-in command that sets the pan/zoom interactive mode. The name of the command is lt.Documents.UI.DocumentViewerCommands.interactivePanZoom. We can use the command system to replace the code in the two methods "Low-Level Implementation" by using one line of code:

JavaScript Example
function updatePanZoomUIState() { 
   $("#panZoomElement").prop("disabled", !documentViewer.commands.canRun(lt.Documents.UI.DocumentViewerCommands.interactivePanZoom, null)); 
} 
function setPanZoom() { 
   documentViewer.commands.run(lt.Documents.UI.DocumentViewerCommands.interactivePanZoom, null); 
} 

Command Parameters and Results

The value null is passed to the CanRun and Run methods because InteractivePanZoom does not take any parameters. Some commands such PageGoto require a parameter (the page number) and must be invoked like this:

JavaScript Example
// Go to page number 10 
documentViewer.commands.run(lt.Documents.UI.DocumentViewerCommands.pageGoto, 10); 

The parameters of a command are a generic object type. The command will perform the necessary conversion, if required. In the case of PageGoto, the parameter will be converted to an integer.

CanRun will also take a parameter for these commands:

value = documentViewer.commands.canRun(lt.Documents.UI.DocumentViewerCommands.pageGoto, 10);

If we have a document, the document has at least 10 pages, and the current page number is not 10 already, value will be true; otherwise, value will befalse`.

The Run method always returns the result of running the command as a generic object. Some commands such as TextExport return the text of a page or the document as a string object. Note that TextExport also accepts the page number as a parameter. If null or 0 is passed, it will return the text for all the pages:

JavaScript Example
// Get the text for page number 10 as a string 
var text = documentViewer.commands.run(lt.Documents.UI.DocumentViewerCommands.textExport, 10); 

State Commands

In addition to CanRun and Run, some commands contain a boolean state property. For example, the InteractiveAutoPan command is used to enable/disable auto-panning. These commands usually uses a check mark as a user interface element to indicate the state. For example:

JavaScript Example
function updateAutoPanUIState() { 
   // Can we run the command? 
   $("#autoPanElement").prop("disabled", !documentViewer.commands.canRun(lt.Documents.UI.DocumentViewerCommands.interactiveAutoPan, null)); 
   // Get the command 
   var command = documentViewer.commands.getCommand(lt.Documents.UI.DocumentViewerCommands.interactiveAutoPan); 
   // Use its current state 
   $("#autoPanElement").prop("checked", command.state); 
} 
function flipAutoPan() { 
   // Just call Run, the command knows it has a state and will flip it automatically, enabling or disabling auto-pan accordingly 
   documentViewer.commands.run(lt.Documents.UI.DocumentViewerCommands.interactiveAutoPan, null); 
} 

Long Running Commands

Although most of the actions performed on the DocumentViewer are instant, some operations can take a considerable amount of time depending on the viewer state and the data requested.

For example, the TextExport command parses the text from the DocumentPageText object of a page obtained using DocumentPage.GetText. This method parses the text from the page using either SVG or OCR technologies and, especially in the latter case, can take seconds to return. DocumentViewerText internally caches the DocumentPageText objects once they are obtained. The first request for page text will take longer than subsequent requests, which are relatively instant.

TextExport performs the following (simplified and ignoring the DocumentViewer.Operation events involved):

  1. Checks if Text has a DocumentPageText object cached for the requested page. If so, it will parse the text and return the result; this operation is instant. If not, continue to the next step.

  2. Checks the value of Text.AutoGetText.

    • If this value is false, then the application has requested that DocumentPage.GetText not to be automatically invoked. This method returns an empty string; this operation is instant.
    • If this value is true, then DocumentPage.GetText is invoked. If the original document does not support SVG (such as a TIFF or raster PDF document), then the operation will use OCR. Text will wait for this to finish, cache the DocumentPageText before parsing the data and returning; this operation is long running.

Based on the steps above, calling Run with TextExport may not immediately return control to the application. If this command is to be performed directly from a user interface element, then the UI thread of the application will be unresponsive until the method returns.

One solution is to perform the following when the user selects the Text Export UI element:

  1. Show a busy dialog

  2. Run the command in a separate thread

  3. When the command returns, hide the busy dialog

This will work, but will have the negative effect of always showing/hiding a busy dialog, even if the command is instant. In most applications, this will result in an undesirable screen flicker.

Another option is to use the DocumentViewerCommands.IsSlow method. Each command will return true or false based on its internal current state and calculations. The following a solution to handle the Text Export UI element using the IsSlow method:

  1. Call documentCommands.isSlow(DocumentViewerCommands.textExport, 10)

  2. If the result is true, show a busy dialog, run the command in a separate thread, then hide the busy dialog on completion

  3. If the result is false, run the command in the UI thread

This will eliminate the screen-flicker problem described above by only showing the busy dialog when required.

DocumentViewerCommand Class

The DocumentViewerCommand class holds the data for each command. This class contains the following members:

Member Description
Name

Unique name of the command

CanRunHandler

Callback to use when checking that this command can run using a value

RunHandler

Callback to use to run the command with a value

IsSlowHandler

Callback to use to check if the command will be slow when using a value

Value

Current value of the command

HasState

Indicates if this is a state command

State

Current state value of the command

All of the built-in commands are instances of DocumentViewerCommand objects that are initialized and ready to use. The callbacks are called when DocumentViewerCommands.Run, DocumentViewerCommands.CanRun, and DocumentViewerCommands.IsSlow are called, respectively.

DocumentViewerCommands Class

The DocumentViewerCommands class manages the commands of the DocumentViewer and can be accessed by the DocumentViewer.Commands property. Internally, it stores a dictionary of all the commands of the DocumentViewer. The key is the command's unique name, and the value is the corresponding DocumentViewerCommand object. It has the following members:

Member Description
GetCommand

Gets the DocumentViewerCommand with the specified name

CanRun

Checks if a command can run with the specified value

Run

Runs a command with the specified value

IsSlow

Checks if running a command will be slow with the specified value

Built-in Commands

The DocumentViewer class comes with the following built-in commands that can used right away. All the commands are initialized when DocumentViewer is created and stored in the DocumentViewerCommands class.

Page Commands

These commands use DocumentViewer.GotoPage.

Command Value parameter Returns Description
Page.First None None Go to the first page in the document
Page.Next None None Go to the next page in the document
Page.Previous None None Go to the previous page in the document
Page.Last None None Go to the last page in the document
Page.Goto int pageNumber None Go to the specified page number

View Commands

These commands use the DocumentViewerView and its ImageViewer control.

Command Value parameter Returns Description
View.ZoomIn None None Zooms the view in by DocumentViewerView.ZoomRatio
View.ZoomOut None None Zooms the view out by ZoomRatio
View.ZoomPercentage double percentage None Zooms the view by the specified percentage
View.FitWidth None None Fits the page width in the view
View.FitPage None None Fits the page in the view
View.ActualSize None None Show the actual size of the page in the view
View.RotateClockwise None None Rotates the view 90 degrees clockwise
View.RotateCounterClockwise None None Rotates the view 90 degrees counter-clockwise
View.ItemType DocumentViewerItemType value None Sets the view item type to the value

Layout Commands

These commands use pre-defined ImageViewerViewLayout objects to set in the view's ImageViewer control.

Command Value parameter Returns Description
Layout.Single None None Sets the layout as single in the view
Layout.Vertical None None Sets the layout as vertical in the view
Layout.Double None None Sets the layout as double in the view
Layout.Horizontal None None Sets the layout as horizontal in the view

Interactive Commands

These commands use pre-defined ImageViewerInteractiveMode objects to set in the view's ImageViewer control.

Command Value parameter Returns Description
Interactive.PanZoom None None Sets pan/zoom as the current interactive mode
Interactive.Pan None None Sets pan as the current interactive mode
Interactive.Zoom None None Sets zoom as the current interactive mode
Interactive.ZoomTo None None Sets zoom-to as the current interactive mode
Interactive.MagnifyGlass None None Sets magnify glass as the current interactive mode
Interactive.RubberBand None None Sets the generic rubber band as the current interactive mode
Interactive.SelectText None None Sets select text as the current interactive mode
Interactive.AutoPan None None Enables/Disables the auto pan interactive mode

Text Commands

These commands use methods from the DocumentViewerText object.

Command Value parameter Returns Description
Text.Copy int pageNumber None Calls DocumentViewerText.Copy(pageNumber)
Text.SelectAll None None Calls DocumentViewerText.SelectAll
Text.ClearSelection None None Calls DocumentViewerText.ClearSelection
Text.Export int pageNumber string Calls DocumentViewerText.ExportText(pageNumber)
Text.FindNext None List of DocumentViewerTextItem or null Calls DocumentViewerText.Find(DocumentViewerText.LastFindText, false, true)
Text.FindPrevious None List of DocumentViewerTextItem or null Calls DocumentViewerText.Find(DocumentViewerText.LastFindText, false, false)
Text.Get int pageNumber None Calls DocumentViewerText.GetDocumentPageText(pageNumber) or DocumentViewerText.GetAllDocumentPageText, if pageNumber is 0

Annotation Commands

These commands use methods from the DocumentViewerAnnotations and AnnAutomation objects. These commands provide the necessary checks to make sure the methods can be called without errors.

Command Value parameter Returns Description
Annotations.Undo None None

Calls AnnAutomation.Undo

Annotations.Redo None None

Calls AnnAutomation.Redo

Annotations.Cut None None

Calls AnnAutomation.Copy and AnnAutomation.DeleteSelectedObjects

Annotations.Copy None None

Calls AnnAutomation.Copy

Annotations.Paste LeadPointD position None

Calls AnnAutomation.Paste(position)

Annotations.Delete None None

Calls AnnAutomation.DeleteSelectedObjects

Annotations.SelectAll int pageNumber None

Calls AnnAutomation.SelectObjects((all objects of the container in page number)

Annotations.ClearSelection None None

Calls AnnAutomation.SelectObjects(null)

Annotations.UserModeDesign None None

Sets AnnAutomationManager.UserMode to AnnUserMode.Design

Annotations.UserModeRun None None

Sets AnnAutomationManager.UserMode to AnnUserMode.Run

Annotations.UserModeRender None None

Sets AnnAutomationManager.UserMode to AnnUserMode.Render

Annotations.BringToFront None None

Calls AnnAutomation.BringToFront(false)

Annotations.SendToBack None None

Calls AnnAutomation.SendToBack(false)

Annotations.BringToFirst None None

Calls AnnAutomation.BringToFrong(true)

Annotations.SendToLast None None

Calls AnnAutomation.SendToBack(true)

Annotations.Flip None None

Calls AnnAutomation.Flip(false)

Annotations.Reverse None None

Calls AnnAutomation.Flip(true)

Annotations.Group string groupName None

Calls DocumentViewerAnnotations.GroupSelectedObjects(groupName)

Annotations.Ungroup None None

Calls DocumentViewerAnnotations.UngroupSelectedObjects

Annotations.Lock None None

Calls AnnAutomation.Lock

Annotations.Unlock None None

Calls AnnAutomation.Unlock

Annotations.ResetRotatePoints None None

Calls AnnAutomation.ResetRotatePoints

Annotations.AntiAlias None None

Flips the state of IAnnAutomationControl.AutomationAntiAlias

Annotations.Properties None None

Calls AnnAutomation.ShowObjectProperties

Annotations.UseRotateThumbs None None

Flips the state of DocumentViewerAnnotations.UseRotateThumbs

Annotations.EnableToolTips None None

Flips the state of AnnAutomationManager.EnableToolTip

Annotations.RenderOnThumbnails None None

Flips the state of DocumentViewerAnnotations.RenderOnThumbnails

Help Version 20.0.2018.3.5
Products | Support | Contact Us | Copyright Notices
© 1991-2018 LEAD Technologies, Inc. All Rights Reserved.
LEADTOOLS HTML5 JavaScript