Document Viewer Commands

DocumentViewer uses the commands 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).

Why Use Commands

DocumentViewer contains many parts that must be kept in sync. These parts uses public LEADTOOLS classes and controls such as ImageViewer or AnnAutomation and all actions is performed using the public and documented properties and methods of the classes.

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

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

  1. The application updates 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 set to Pan/Zoom, then the element must be disabled (or checked and should not be invoked), but disabled will be used for this example.

    The above can be performed using this code snippet:

    void UpdatePanZoomUIState() { 
       // First test 
       panZoomElement.Enabled = documentViewer.HasDocument; 
       if(panZoomElement.Enabled) { 
          // Find the Pan/Zoom interactive mode, see if it is already enabled 
          var panZoom = documentViewer.View.ImageViewer.InteractiveModes.FindById(ImageViewerInteractiveMode.PanZoomMode); 
          // Second test, see if the mode is already enabled 
          panZoomElement.Enabled = !panZoom.IsEnabled; 
       } 
    } 

    This will take care of the state of the element.

  2. When the user clicks the Pan/Zoom menu item, the application must perform the following:

    • Not just calling ImageViewerInteractiveModes.EnableById since this will disable all the other interactive modes. Annotations and Page Links modes should be kept enabled because they can be used along Pan/Zoom.

      When the user clicks an annotation object, it gets automated. When the user clicks on a page links, it must run and panning and zoom only happens when the user clicks outside these objects. So the process must loop through all the modes, disable all but Pan/Zoom, Annotations and Page Links.

    • If annotations is used, then any current designers must be canceled (For example, if the process run in the middle of a multi-click operation to draw a new polyline) and the current object ID in the toolbar back must set to Select.

    • Finally, call UpdatePanZoomUIState again to disable the menu item.

    The above can be performed using this code snippet:

    void SetPanZoom() { 
       // First action 
       foreach (var mode in documentViewer.View.ImageViewer.InteractiveModes) { 
          mode.IsEnabled = 
             mode.Id == ImageViewerInteractiveMode.PanZoomMode ||  
             mode.Id == DocumentViewer.AnnotationsInteractiveModeId || 
             mode.Id == 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 = AnnObject.SelectObjectId; 
       } 
       // Third action 
       UpdatePanZoomUIState(); 
    } 

Running Commands

The above code must be exactly right to get all the parts of the document viewer in sync and this is only for a single simple action: Setting the current interactive mode.

DocumentViewer comes with a built-in command that sets the pan/zoom interactive mode. The name of the command is %"Interactive.PanZoom":F:Leadtools.Documents.UI.DocumentViewerCommands.InteractivePanZoom%. The commands system can be used to shortened the above two methods code into one line as the following:

void UpdatePanZoomUIState() { 
   panZoomElement.Enabled = documentViewer.Commands.CanRun(DocumentViewerCommands.InteractivePanZoom, null); 
} 
void SetPanZoom() { 
   documentViewer.Commands.Run(DocumentViewerCommands.InteractivePanZoom, null); 
} 

The built-in commands handle more complex actions cleanly and ensure all parts of the document viewer are kept in sync. Any command can be identified by a unique simple constant string, and thus, binding commands with the user interface can be achieved easily.

Command Parameters and Results

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

// Goto page number 10 in the viewer 
documentViewer.Commands.Run(DocumentViewerCommands.PageGoto, 10); 

The parameters of a command is a generic object type. The command will perform the necessary conversion if required - to an integer value in the case of PageGoto.

CanRun will also take a parameter for these commands:

value = documentViewer.Commands.CanRun(DocumentViewerCommands.PageGoto, 10);

And "value" will be true if a document contains at least 10 pages or more and the current page number is not 10 already. Otherwise; false.

Run always return the result from running the command and this result is also a generic object. The commands discussed above all return null since they do not return any results. Some commands like TextExport will return the text of a page (or the document) as a string object. Note that TextExport also accepts the page number as a parameter, or if null or 0 passed, will return the text for all the pages:

// Get the text for page number 10 as a string 
string text = (string) documentViewer.Commands.Run(DocumentViewerCommands.TextExport, 10); 

State Commands

In addition to CanRun and Run, some commands contain a boolean state. For example, the InteractiveAutoPan can be used to enable/disable auto-panning that is used along the other interactive modes. The user interface element these commands usually uses a check mark to indicate the state. The application can use this command as follows:

void UpdateAutoPanUItate() { 
   // Can we run the command? 
   autoPanElement.Enabled = documentViewer.Commands.CanRun(DocumentViewerCommands.InteractiveAutoPan, null); 
   // Get the command 
   var command = documentViewer.Commands.GetCommand(DocumentViewerCommands.InteractiveAutoPan); 
   // Use its current state 
   autoPan.Checked = command.State; 
} 
void 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(DocumentViewerCommands.InteractiveAutoPan, null); 
} 

Slow Commands

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

For example, the TextExport command discussed above 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 caches the DocumentPageText objects for the pages internally once they are obtained. The first time the text of a page might be slow, but subsequent requests are instant.

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

  1. Checks if Text has a DocumentPageText object for the requested page cached, if so, it will parse the text and return the result and exits - this operation is instant.

  2. Next, it will check the value Text.AutoGetText, if this value is false, then the application requested that DocumentPage.GetText not to be invoked instantly. Thus the method returns an empty string - this operation is instant.

  3. If the value of Text.AutoGetText is true, then DocumentPage.GetText is invoked and if the original document does not support SVG (such as a TIFF or raster PDF document), then the operation will use OCR and might take a few seconds to return. Text will wait for this to finish, caches the DocumentPageText before parses the data from it and returning - this operation is slow.

  4. The next time TextExport is called on this same page, and as described in the first step, the text is parsed from the cached data and the result is returned. DocumentPage.GetText is not called - this operation is instant.

From the above, calling Run with TextExport may not return control to the application immediately. If this command is to be performed from a user interface element directly then the UI thread of the application will freeze and not be responsive till the method return.

One solution is to perform the following when the user select 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 have the negative effect of showing/hiding this busy dialog always, even if the command will be instant (as in most of the cases described above). In most applications this will result in the undesirable action of the screen flickering for a moment.

The other option is to use the DocumentViewerCommands.IsSlow method. Each command will return true or false based on its internal current state and calculation. As described above in the case of TextExport. Here is the solution described above to handle Text Export UI element but with using IsSlow:

  1. Call documentCommands.IsSlow(DocumentViewerCommands.TextExport, 10)

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

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

This will eliminate the flickering problem described above but not showing the busy dialog unless required.

Running Commands Asynchronously

In addition to DocumentViewerCommands.Run, the DocumentViewerCommands.RunAsync method can be used to run a command asynchronously. This is useful for especially for slow commands and will perform the action of creating a thread to run the command, handle errors and clean up easily.

Using the same TextExport command from before, here's how to run it asynchronously:

// Create a new DocumentViewerAsyncOperation object 
var async = new DocumentViewerAsyncOperation(); 
// Set the delegate to be called if an error occurs 
async.Error = (DocumentViewerAsyncOperation operation, Exception error) => { 
   HandleError(error); 
}; 
// Set the delegate to be called after the run, successfully or when an error occurs 
async.Always = (DocumentViewerAsyncOperation operation) => { 
   // Hide the busy dialog 
   HideBusyDialog(); 
}; 
// Show the busy dialog 
// Run the command asynchronously in a worker thread 
documentViewer.Commands.RunAsync(async, DocumentViewerCommands.TextCopy, 10); 

Or with using IsSlow:

var isSlow = _documentViewer.Commands.IsSlow(DocumentViewerCommands.TextExport, 10); 
if (isSlow) { 
   // Command is slow, run asynchronously 
   // Create a new DocumentViewerAsyncOperation object 
   var async = new DocumentViewerAsyncOperation(); 
   // Set the delegate to be called if an error occurs 
   async.Error = (DocumentViewerAsyncOperation operation, Exception error) => { 
      HandleError(error); 
   }; 
   // Set the delegate to be called after the run, successfully or when an error occurs 
   async.Always = (DocumentViewerAsyncOperation operation) => { 
      // Hide the busy dialog 
      HideBusyDialog(); 
   }; 
   // Show the busy dialog 
   // Run the command asynchronously in a worker thread 
   _documentViewer.Commands.RunAsync(async, DocumentViewerCommands.TextCopy, 10); 
} else { 
   // Command is not slow, run directly 
   _documentViewer.Commands.Run(DocumentViewerCommands.TextCopy, 10); 
} 

DocumentViewerCommand Class

DocumentViewerCommand 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 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 run using a value.
Value Current value of the command.
HasState Indicates whether this command uses a state.
State Current state value of the command.

All the built-in commands are instance of DocumentViewerCommand objects that are initialized and ready to use. The callbacks are what gets used with DocumentViewerCommands.Run, DocumentViewerCommands.CanRun and DocumentViewerCommands.IsSlow are called.

DocumentViewerCommands Class

DocumentViewerCommands 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 document viewer. The key is the command 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 a 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

DocumentViewer 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 DocumentViewerView and its ImageViewer

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

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

Interactive Commands

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

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 Enable/Disable auto pan interactive mode.

Text Commands

These commands use methods from DocumentViewerText.

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 DocumentViewerAnnotations and AnnAutomation. These commands provides 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 LeadPoint 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.
Products | Support | Contact Us | Copyright Notices
© 1991-2017 LEAD Technologies, Inc. All Rights Reserved.
LEADTOOLS Imaging, Medical, and Document
Click or drag to resize