The CodeCentral™ Expert for Delphi and C++ Builder
by John Kaster
This article describes the CodeCentral expert Jeff Overcash (of
TeamB fame) and I wrote.
This expert uses the Open Tools API to install itself
into the Delphi and C++ Builder IDE menu so the Borland
CodeCentral™
repository can be searched from within the IDEs.
A little bit of conference magic goes a long way
Like every year, this year's Borland Conference was a frenetic few days
spent visiting old acquaintances, making new ones, catching up on the latest technology,
having fun, and brainstorming on cool geek things to do.
As with many developers, I've got development plans that would require years to fulfill. Many times,
I find that talking with other developers will change the order of my development priorities. This
conference was no exception. During an informal (and private) meeting we had with some of our Delphi
field testers, one of them wished (very strongly) for the ability to search an on-line knowledge
base for source code examples from within the Delphi IDE. While I'm no genie, I decided as I left
the meeting that the conference was the perfect place to fulfill his wish.
An IDE-based interface for CodeCentral
was always part of the plan. I just never expected it to take a year. Sometimes the "have-to-do" things
get in the way of the "want-to-do" things on your list. This was one of those times. I had talks to prepare
(I usually do "bleeding edge" topics, so conference time is sleep deprivation time for me) and present for
the conference. My first wedding anniversary was also during the conference (in case you were wondering why
no one saw me on Monday night). I also wanted to present something brand new
for the community site
at the closing session. It looked like once again my plans would have to be postponed, unless I could
find some help.
Who you gonna call?
Jeff Overcash has done a great job of living the TeamB motto (We'll do anything as long as you don't
pay us), donating a lot of his time and expertise to help me upgrade the interface and functionality of
CodeCentral before the conference.
Jeff wasn't speaking at the conference (I haven't been able to talk him into it yet), and once
again he volunteered his time to help me get something done for the community site. I told him what
I wanted, and he got a demonstrable version of it done before the closing session of the conference.
It's great the way that works!
The CodeCentral Expert
(CCExpert) is an IDE expert for searching
the Borland CodeCentral web site, using the search conditions you enter on the search
form. After you enter your search request and hit the Search button, your
browser window will be opened and the CodeCentral search results will be
displayed.
This search expert is an IDE interface to the CodeCentral
web search form.
You can also go directly to the search form without having to use the CodeCentral expert.
Installing CCExpert
Just a disclaimer: you are using this IDE expert at your own risk. Jeff and I will
only provide support for this expert through comments attached to this upload on CodeCentral, or
the
CodeCentral newsgroup. If you have suggestions for enhancing it, plesae attach them to
this article, or put them in the CodeCentral newsgroup.
You can download the complete source code for CCExpert (CodeCentral ID 15111)
here.
To install CCExpert into your Delphi IDE, open CCExpert.dpk, compile it, and
click the Install button. To install CCExpert into your C++ Builder IDE, open
CCCExpert.bpk, compile it and click the Install button.
Once it is successfully installed, you will have a new menu item in the Help
menu called CodeCentral.
Using CCExpert
I have many plans for enhancing this expert, and also for releasing the JBuilder version
that was demonstrated at the conference, but most
of that will have to wait until the new Windows-based client is released.
The Help|CodeCentral menu
When you install CodeCentral, it inserts a submenu item in the Help menu of the IDE.
Here's the code that inserts the menu item.
procedure TdmCodeCentral.DataModuleCreate(Sender: TObject);
const
SMainMenu = 'HelpMenu';
{$ifdef VER130} // Delphi 5 or C++ Builder 5 specific
{$ifdef BCB}
SSubMenu = 'HelpCommunityPage';
{$else}
SSubMenu = 'HelpBorlandCommunityPage';
{$endif}
{$else} // This should be for Delphi 6 and beyond
{$ifdef VER140}
SSubMenu = 'HelpCommunityPage';
{$else} // Previous versions of Delphi or C++ Builder
SSubMenu = 'HelpWinSDKItem';
{$endif}
{$endif}
var
Main : TMenuItem;
Item : TMenuItem;
MainMenu : TMainMenu;
i : Integer;
{
You can use the conditonal LIST_MENUS code to find out what the menu
item names are for the help menu. Simply define LIST_MENUS by removing
the space in front of the $define (below), and try to install the menu.
You will be provided with a list of the Help Menu names when you
try to install this package in the IDE.
}
{ $define LIST_MENUS}
{$ifdef LIST_MENUS}
Menus : string;
{$endif}
begin
Main := nil;
MainMenu := (BorlandIDEServices as INTAServices).GetMainMenu;
for i := 0 to MainMenu.Items.Count - 1 do
begin
if MainMenu.Items[i].Name = SMainMenu then
begin
Main := MainMenu.Items[i];
break;
end;
end;
if Main <> nil then
begin
Item := mnuCodeCentral.Items[0];
mnuCodeCentral.Items.Delete(0);
{$ifdef LIST_MENUS}
Menus := '';
for i := 0 to Main.Count - 1 do
Menus := Menus + Main.Items[i].Name + #13;
Raise Exception.Create( Menus );
{$endif}
i := 0;
while (i < Main.Count) and (Main.Items[i].Name <> SSubMenu) do
Inc(i);
Main.Insert(i + 1, Item);
end;
end;
In Delphi 5, the Help menu item names are (in order):
- HelpContentsItem
- HelpDelphiToolsItem
- HelpWinSDKItem
- HelpInprisePage
- HelpBorlandCommunityPage
- HelpDelphiPage
- HelpProgramsPage
- DirectItem
- HelpProgGuideSeparator
- HelpCustomizeItem
- HelpAboutSeparator
- HelpAboutItem
As you can see by looking at the source code above, the CCExpert menu item is inserted under the
HelpBorlandCommunityPage menu item. If you want to change its location, simply change the
SSubMenu constant to the name of the other menu component.
Note!
If you examine the
$ifdefs above, you will notice that the community page menu item named changed from
"HelpBorlandCommunityPage" to "HelpCommunityPage" between Delphi 5 and C++ Builder 5. I am guessing
that it will keep its latest name for Delphi 6 and C++ Builder 6, but this is not guaranteed. Borland
does not document the names of the IDE menu items because they change so much in each version of Delphi
and C++ Builder. Jeff Overcash has a complete IDE menu item explorer/shortcut modifier he has written that is quite handy for this purpose
as well. I'm hoping to convince him to find the time to write an article about it in the near future.
For now, if the menu name does change, you can find out what the new menu names are in the help menu by
$defining LIST_MENUS and attempting to install the expert in the IDE again.
IDE Sensitivity
If you highlight one or more components on a form before starting CCExpert,
the names of those components will automatically be entered as the keywords to
find in the CodeCentral repository. The expert will also attempt to
automatically detect which IDE you are using, and default the product for the
search to that IDE. To do this, the CodeCentral Expert uses the Open Tools API. The following code
illustrates.
procedure TdmCodeCentral.miCodeCentralClick(Sender: TObject);
var
FormIntf: TIFormInterface;
CompIntf: TIComponentInterface;
CurrentFile, FileExt, UnitName, ComponentName : String;
ModIntf: TIModuleInterface;
i : Integer;
SList : TStringList;
begin
ModIntf := nil;
if not Assigned(frmCodeCentral) then
frmCodeCentral := TfrmCodeCentral.Create(Application);
with frmCodeCentral do
begin
CurrentFile := ToolServices.GetCurrentFile;
FileExt := ExtractFileExt(CurrentFile);
{ Get the module interface to determine the Product IDE }
i := Pos(FileExt, CurrentFile);
if i > 0 then
begin
UnitName := Copy(CurrentFile, 1, i) + 'PAS';
ModIntf := ToolServices.GetModuleInterface(UnitName);
Product := 'Delphi';
if ModIntf = nil then
begin
UnitName := Copy(CurrentFile, 1, i) + 'CPP';
ModIntf := ToolServices.GetModuleInterface(UnitName);
Product := 'C++ Builder';
end;
if ModIntf = nil then
Product := SAnyProduct;
end;
{ Attempt to fill in the keyword entry based on the components that
are currently selected on the form }
if ModIntf <> nil then
begin
FormIntf := ModIntf.GetFormInterface;
if FormIntf <> nil then
begin
SList := TStringList.Create;
try
SList.Sorted := true;
SList.Duplicates := dupIgnore;
for i := 0 to FormIntf.GetSelCount - 1 do
begin
CompIntf := FormIntf.GetSelComponent(i);
try
if CompIntF <> nil then
begin
ComponentName := CompIntf.GetComponentType;
if Trim(ComponentName) <> '' then
SList.Add(ComponentName);
end;
finally
CompIntf.Free;
end;
end;
for i := 0 to SList.Count - 1 do
edtKeywords.Text := edtKeywords.Text + '+' + SList[i] + ' ';
finally
SList.Free;
end;
end;
end;
Show;
end;
end;
Using an Action for User Responsiveness
Simply fill in the values on the form the CodeCentral expert displays, and click the
Search button. Any values you specify beyond the default values help to restrict
the search to a smaller selection list. The search button will only be enabled if you have specified
the required values for the search. The following code enforces this behavior. The Search button
is assigned the actSearch action, which gets updated whenever a user interface event occurs.
procedure TfrmCodeCentral.actSearchUpdate(Sender: TObject);
var
LowVer,
HighVer,
ShowMe : Extended;
function GetNum( Control : TCustomEdit ) : extended;
begin
Result := -1;
if Trim( Control.Text ) <> '' then
try
Result := StrToFloat( Control.Text );
except
end;
end;
begin
LowVer := GetNum( edtLowVersion );
HighVer := GetNum( edtHighVersion );
ShowMe := GetNum( edtShowMe );
actSearch.Enabled := ( Trim( edtKeywords.Text + edtSubmitter.Text ) <> '' )
and ( LowVer >= 0 ) and ( HighVer >= 0 ) and ( ShowMe > 0 )
and ( HighVer >= LowVer );
end;
Opening the search results page
This version of the expert simply fills in the search values for the CodeCentral
web-based search and opens that URL in your browser registered for handling HTTP requests.
It does that by using the BrowseTo()
procedure that will open a URL.
procedure TfrmCodeCentral.BrowseTo(URL: string);
begin
ShellExecute(0, 'Open', PChar(URL), '', '', SW_SHOWDEFAULT );
end;
You can click the Home button to go to the CodeCentral
Home page, and the Close button to close the expert.
Search Form Values
You can use several different criteria to search the CodeCentral repository.
Product
If CCExpert can determine what IDE is running, it will default the product search value to that
IDE. The following code helps to keep the product combobox synchronized with the value determined by
the TdmCodeCentral.miCodeCentralClick() procedure listed above.
The values you can select for searching submissions for a specific product are:
Any product, which will search across all products
Delphi
C++ Builder
JBuilder
MIDAS
Interbase
BDE
Turbo Pascal
Borland C++
Keywords
The keywords for every submission are determined by extracting the unique
"words" from the title and description of the entry. These "words" can be
alphanumeric, since this is a technical database. You can require words in
your search by using a plus (+) sign in front of the word. You can exclude
entries containing specific words in your search by using a minus (-) sign
in front of the word. The or (|) sign is optional, indicating words that may
appear in the search but are not required. You can put any number of keywords
you want in the keyword field. Keyword matching is case-insensitive. Any
keywords you submit are converted to lowercase first.
Wildcards are also supported for searching. The asterisk (*) is the wildcard
for one or more characters in the pattern match. The question mark (?) is
the wildcard for a single character. The "*" and "?" get translated to the equivalent
SQL LIKE command characters, so putting them at the start of a word pattern will slow
down your search, as no SQL index can be used for them.
The keyword list for every entry in CodeCentral is automatically generated from its
title, long description, and short description. All the unique words (other than the really common
ones like "a", "the" and so on) are saved in a separate table that can be used for indexed SQL select
statements. This solution provides a little bit more performance and flexibility than doing a text
search on the blob fields. I'll publish the components and code that does this at a later date.
Author
All entries are submitted by a specific CodeCentral user. If you want to search
for entries uploaded by a specific person, you can enter their name or email
address in this field.
You can enter:
first name followed by last name (like "Frank Borland")
last name, first name (like "Borland, Frank")
email address (like "fborland@borland.com")
CodeCentral will attempt to match the value you put in this field with a
CodeCentral user, and give you only submissions uploaded by that user.
Low Version and High Version
All entries are submitted for a range of versions. If you want to search for
only one version of the product, enter it as both the low and high value for
the version. If you want to search for a range of versions, enter the low
value as the low version and the high value as the high version, and all
submissions that fall between those two versions will appear in your
search results. If you want to search for all versions of a product, use
zero (0) and zero (0) respectively.
Show Me
Because you may find many entries matching your search values (there are thousands of submissions
in CodeCentral), you can use this entry to limit the number of results the search engine returns
to you.
Configuring CCExpert
If you want to modify the location of the CodeCentral web server for any reason,
create a file in your package directory called ccexpert.ini. It should
look like this:
[CodeCentral]
Server=http://codecentral.borland.com/codecentral/ccweb.exe
Where the value for Server is the new location for the CodeCentral web server.
More to come
There should be new features coming to CCExpert, like zipping up the current project you're working on and
uploading it to CodeCentral, and the reincarnation of the GUI client executable. If you have suggestions for
things you'd like to see, please comment on this article, or use the
CodeCentral Newsgroup to let me know what you'd like to see.
If you're a Java developer, we really need Java-based submissions so the CodeCentral expert for JBuilder
(which I should be able to put out soon) will have lots of things to find when people start searching
CodeCentral from within the JBuilder IDE.
Connect with Us