線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1757
推到 Plurk!
推到 Facebook!

Using the Open Tools API in Kylix

 
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-01-14 11:12:17 IP:61.218.xxx.xxx 未訂閱

Using the Open Tools API in Kylix

How to extend and customize the Kylix IDE. By Ray Lischner, Tempest Software 資料來源: http://bdn.borland.com/article/0,1410,27205,00.html I have good news and bad news concerning the Open Tools API in Kylix. The good news is that the Tools API has not changed since Delphi 5. The bad news is that the Tools API has not changed since Delphi 5. This article introduces the Tools API -- in case it is new to some of you -- and then examines how the Tools API works in Kylix, and how it doesn't work. I'll turn on the Fasten Seat Belts sign because we're in for a bumpy ride. OVERVIEW OF THE TOOLS API If you have never worked with the Open Tools API in Delphi or C Builder, this section briefly describes what you've been missing. If you are already familiar with the Tools API, skip ahead to the section, Tools API in Kylix. The Open Tools API, or just Tools API for short, is the programming interface for extending and customizing the IDE. Kylix lets you add menu items to the main menu bar, add buttons to tool bars, create new design windows, and more. The Tools API is not documented, but information abounds on the web, at the annual Borland Conference, in magazine articles, and in newsgroups. The first place to look, though, is in the source code. The sourcetoolsapi directory contains several files, but the important one is ToolsAPI.pas. This unit contains all the declarations for the Tools API. You probably don't have Kylix sitting in front of you right now, but the file is almost exactly the same as it is in Delphi 5, so if you can, take a peek at Delphi 5's ToolsAPI.pas. The ToolsAPI unit contains a few constants, some record and related declarations, but mostly interface declarations. The bulk of the Tools API is a set of interfaces that describe some of the capabilities of the IDE. The interfaces come in two varieties: those implemented by Borland and those implemented by the programmer. The first kind provide information and permit your code to perform actions in the IDE. The second kind are used for notifications and to provide information to the IDE. You must write a class to implement the interface, and the Tools API calls your methods at appropriate times. The following sections describe this and other details of the Tools API in more depth. SERVICES Several of the interfaces are called services. These are the primary entry points for working with the Tools API. Different kinds of services perform different kinds of actions. For example, IOTAModuleServices (OTA stands for Open Tools API) provides services for dealing with modules--open files. IOTADebuggerServices lets you interact with the debugger: examine processes and threads, set breakpoints, and so on. To use a service, cast the BorlandIDEServices variable to the desired service. You can do this inline, or save the result in a variable. Because you are working with interfaces, you don't need to concern yourself with memory management. Kylix will automatically clean up the interface's memory when that memory is no longer needed. For example, you can obtain the module interface for an open file by calling the FindModule method. With a module interface, you have full access to the files for that module. You can save them, edit them, show them in their respective editors (source files in the source editor, form files in the form editor or as text in the source editor), and so on.
var
  Module: IOTAModule;
begin
  Module := (BorlandIDEServices as IOTAModuleServices).FindModule(FileName);
Most of the services are at least partially commented in ToolsAPI.pas, so you can read more about them there. Look for the interfaces that have Services in their names. WIZARDS To write an IDE extension, you usually implement one or more wizard interfaces. These interfaces inherit from IOTAWizard. You have four choices, as described in the following table.
Interface           Description
 
IOTAWizard          Base wizard interface; every wizard must implement this. 
IOTAMenuWizard      Wizard adds a menu item to the Help menu. Useful for tests and prototypes. 
IOTARepositoryWizard Base interface for project and form wizards. You must also implement one of the following interfaces: 
IOTAFormWizard       Wizard to create a new unit, form, or other file. 
IOTAProjectWizard    Wizard to create a new project. 
The base interface, IOTAWizard has four methods that you must implement. Only two are important, though: Execute procedure: Basic wizards never call this method, only menu, form, and projects wizards do. They call Execute when the user invokes the wizard (by choosing the menu item, or selecting the form or project to be created). GetIDString function: Returns a unique identifier string. You can ensure uniqueness by using your company or organization name, and a unique name for this wizard. By convention, these are separated by a dot. GetName function: Returns a user-friendly name for your wizard. GetState function: Only menu wizards call GetState--to learn the state of the menu item (enabled or not, checked or not). Menu wizards require one additional method, GetMenuText, which is the menu item caption. The GetState method in IOTAWizard returns the state of the menu item. Form and project wizards require an author's name, a one sentence comment, and an icon handle, which the IDE displays in the New Items dialog box. Choose View Details in the context menu to see examples of the comment and author. If the page name is an empty string, the default page name is Wizards. The IDE will also choose a default icon if your wizard returns 0 from GetGlyph. The difference between a form and a project wizard is that the user can choose a form wizard to be the default form when creating a new form or when creating the main form of a default project. The user can choose a project wizard to be the default application. What the wizards actually do is up to you--you don't need to create a form in a form wizard, but it would be confusing if you don't. Notice that the basic wizard, one that implements only the IOTAWizard interface, has no means of invocation. The means of invoking the wizard is entirely up to you: you can add a button to the IDE's tool bars, add a menu item to the menu bar, create modal or modeless windows, or hide in the background. In fact, any wizard can do any of the above. To create a wizard class, derive a class from TNotifierObject and implement IOTAWizard and any of the other wizard interfaces you need. For example:
type
  TAutoSaveWizard = class(TNotifierObject, IOTAWizard)
  public
    constructor Create;
    destructor Destroy; override;        // IOTAWizard
    procedure Execute;    // Called only for Menu, Form, and Project wizards
    function GetIDString: string;     // return a unique string, e.g., 'Tempest Software.My wizard name'
    function GetName: string;         // return a user-friendly string
    function GetState: TWizardState;  // state of the menu item for IOTAMenuWizard; other wizards don't use
                                      // the state.
  end;
NOTIFIERS Another kind of interface that you must implement is a notifier. Kylix uses notifiers to inform your wizard of an interesting event. For example, you can define an IDE notifier to learn when the user opens files, starts compiling, and so on. You can attach a module notifier to a specific module to learn when the user edits that module, saves the files, and so on. Most of the notifier interfaces have names that end with Notifier. To use a notifier, you must first write a class that implements the notifier, then you register an instance of your class with the Tools API. When you register the notifier, the Tools API returns an integer that uniquely identifies that notifier. You can unregister the notifier at any time by supplying the integer. You can register and unregister notifiers in any order. Remember that you are using interfaces, so Kylix manages the memory automatically. Once you create your notifier object and register it, you can forget it. The object will be freed when it is no longer needed. If you try to free it yourself, all kinds of problems will ensure, most likely ending up by crashing the IDE. The easiest way to implement a notifier is to derive your class from TNotifierObject. It implements the base notifier interface, IOTANotifier, with stub methods. Not all notifiers uses all four base methods, so having the stubs is convenient. Note that the methods are not virtual. If you need to override one of the methods, just write a method of the same name, and be sure to include IOTANotifier in the list of interfaces that your class implements. The methods' "virtuality" are managed by the interfaces, so it doesn't matter that the methods are not virtual in the class. The four common notifier methods are described below. AfterSave procedure: Editor notifiers call this method after the user saves the associated file. BeforeSave procedure: Editor notifiers call this method when the user saves a file, but before the file is actually written. Destroyed procedure: This method is called when the associated interface is about to be destroyed, and you should unregister the notifier. For example, if the user closes a file, the module interface will be destroyed, but first it calls the Destroyed procedure for all module notifiers registered with that module. Modified procedure: Editor notifiers call this method when the user modifies the file. Note that source editor notifiers call this method for every keystroke. WHAT NEXT? This brief article can only touch on the most superficial aspects of the Tools API. For a more in-depth look, I encourage you to read ToolsAPI.pas and try some experiments on your own. Join me at the 2001 Borland Conference, where I will be speaking at more length on the Tools API. The next section discusses how the Tools API works in Kylix. Tools API in Kylix Other articles on the Community web site bring you the good news about CLX, the Kylix IDE and all the wonderful features you have available. In particular, you should read about Kylix packages. Shared objects in Linux are similar to DLLs in Windows, but they have some differences, too. These differences might affect how you work with Tools API packages. The Tools API in Kylix is almost exactly the same as it is in Delphi 5. If you have a lot of existing Tools API code, it might seem to be a blessing, but if you think about the ramifications, you might change your mind. For example, the Tools API uses the VCL, not CLX. "Wait a minute!" you cry. "Isn't Kylix all about cross-platform development? A brand-new component hierarchy? What's the VCL doing on Linux?" The Kylix IDE is largely a port of the Delphi 5 IDE from Windows to Linux. Borland did not have enough time to rewrite the IDE from scratch in CLX, so they ported the existing VCL-based IDE. It's not running under a Windows emulator, but there is a library that provides some of the Windows API and maps the Windows API calls to native Linux functions and system calls. The VCL sits on top of this library. It's all part of the vcl package. (Yes, that's vcl not vcl60. Linux has its own way to support version numbers for shared objects, so the numbers don't have to be encoded in the file names. That means you don't need to rewrite all your package source files for every new release of Kylix.) Because the VCL and CLX maintain separate event queues, running in separate threads, you must not try to create a CLX form from the VCL thread or vice versa. In other words, don't use CLX in your Tools API wizard. You can use the VCL, but the IDE lets you edit only CLX forms. If you want to use the VCL, therefore, you can design your forms in Delphi 5, then recompile the files in Kylix. You will need to maintain separate package source files, though. The required packages are different for Kylix than for Delphi for Windows, and Borland does not support conditional compilation directives in packages. (More specifically, the IDEs don't understand conditional compilation directives, so you cannot use the package managers on Windows or Linux.) The designide package contains the ToolsAPI unit. You can write a wizard that uses only CLX and the ToolsAPI unit, but you cannot create any visual forms. You might use baseclx, for example. If you do any visual work, remember to use the VCL, not VisualCLX, in which case you need the vcl package, too. Register your wizard in the usual way: declare a procedure named Register (case is important!), and have the Register procedure call RegisterPackageWizard for each wizard instance you want to register. EXAMPLE: SORTING TEXT Take a look at a specific example. This wizard sorts text in the source editor. The user highlights a block of text in the usual manner, then invokes the wizard with a keyboard shortcut or a menu item. The wizard reads the selected text into a string list, sorts the text, and writes the sorted text back to the source editor. The main wizard class is in the SortWiz unit. The wizard adds a menu item to the IDE's menu bar (Edit > Sort). It also registers a key binding for Ctrl K, S. The menu item brings up the sort parameters dialog box, but the key binding sorts using the current parameters. I think this is a convenience for the user, but you are free to change this if you disagree. The SortReg unit registers the wizard. I always like to put the registration code in a separate unit, which lets me work with the wizard and its code without stumbling over the registration code. SortSel does the main work of sorting the selection. There are two possibilities when selecting text: columnar selection or linear selection. In columnar selection, the user identifies two corners of a text rectangle in the editor. Selected lines are not contiguous. What make columnar selections tricky is the possibility of having tabs in the selection or before the selection on one or more lines. After sorting, the wizard tries to ensure the text lines up nicely. It does so by keeping track of the text position of the start of each line fragment. It inserts the sorted text at the same position on each line. In linear selection, the user picks two endpoints, and all characters in between are part of the selection. The exact endpoints might include or exclude the character after the end of the selection. The distinction isn't important because the wizard sorts entire lines of text, so the selection is extended to include the entire line. After sorting, the editor buffer is modified by deleting the old text and inserting the newly sorted text. Finally, the sorted text is selected and scrolled into view. The status bar message informs the user that the text has been sorted. (Sometimes, the text starts out sorted, so the message tells the user that something happened, even if the result is identical to the starting text.) SortParms lets the user adjust some sorting parameters. If the user chooses the Edit>Sort menu item, the sort parameters dialog box is shown. The user can sort in ascending or descending order, choose case sensitivity, and decide whether to ignore Pascal keywords. The latter option lets the user sort methods in a class declaration without putting all functions before all procedures. The sort parameters dialog box is shown below. I originally wrote this wizard in Delphi for Windows, and it ported to Kylix with almost no changes. I had to edit the package source file, but the rest of the code compiled with almost no changes. You can download the code from CodeCentral by clicking here. ABOUT THE AUTHOR Ray Lischner is the author of Shakespeare for Dummies, but don't let that fool you. His day job is teaching computer programming at Oregon State University and writing about computers and programming. He is the author of Delphi in a Nutshell, and other books about Delphi. His articles appear in a variety of magazines and journals, and he speaks at user group meetings and conferences across the country. 聯盟----Visita網站http://www.vista.org.tw ---[ 發問前請先找找舊文章 ]---
系統時間:2024-11-23 20:34:51
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!