Thursday, September 23, 2010

OMB*Plus extensibility - Tk GUI in OMB*Plus

One of the important feature of OWB10g R2 is integration into design client Tcl-based scripting language (OMB*Plus) enhaced with GUI componets - OWB Expert. OWB Expert allow execution of OMB script dirrectly from design client (it is possible to add new command to context menu called from project tree). GUI components play secondary role - the main purpose of these components is setting of paramters passed to OMB script, for example there is component for choosing table from specified module (so usually GUI component perform single task). In most cases for execution of simple task we needed to compose a sequence of sevaral components (choosing module -> choosing table, etc.) - it was quite inconvenient.Maybe the most interesting component is Custom Dialog (allow create dialog windows with several items like text field, label, radio button, etc.), but it has one drawback - this window is non-interactive (there is no way to specify reply for user action, like choosing new value in list, enabling/disabling check box, etc.).

Tcl interpreter allows to write GUI application with Tk extension. And as I explored there is GUI extension for Jacl Tcl-interpreter (OMB*Plus is based on Jacl/tcljava). Name of this extension is SWANK.
Link to swank

Last jar-file of swank compiled with lates Java compiler, so the best way to experiment - use last OWB release (OWB11g R2 which use Java 6 for execution).
Configuration steps:
  • copy swank.jar file to OWB_HOME\owb\lib\ext directory;
  • add to ombinit.tcl file (OWB_HOME\owb\bin/admin directory) at the end line
    source -url resource:/com/onemoonscientific/swank/library/init.tcl.
OMB*Plus example with Tk widgets:

namespace eval ::owbland {}


OMBCC '/'
set projList [OMBLIST PROJECTS]
set ::owbland::res "a"
jcombobox .combproj -variable ::owbland::res -command "procCSEL"
foreach proj $projList {
.combproj item append $proj
}
pack .combproj -side top


listbox .projlist -height 5
pack .projlist -side bottom


wm title . "Super;) Module Viewer"
wm geometry . 400x250


proc procCSEL {} {
  #puts "selected"
  OMBCC '/$::owbland::res'
  if {[catch {set modList [OMBLIST ORACLE_MODULES]} err]} {
    puts $err
  } else {
    #puts $modList
    set lstSz [.projlist size]
    .projlist delete 0 [expr {$lstSz-1}]
    foreach mod $modList {.projlist insert end $mod}
  }
}
















Monday, September 20, 2010

OMB*Plus extensibility - commands redefinition at startup with ombinit.tcl

There is simpler solution for defining commands during OMB*Plus startup - at startup OMB*Plus executes ombinit.tcl script located in OWB_HOME\owb\bin\admin directory.
This file contains definition of several procedures and version from OWB10g R2 also contains code for correcting of multiple path in TCLLIBPATH. In previous post (part 1 of OMB*Plus extensibility) I said that it is impossible to define more than one path in TCLLIBPATH - but with this procedure in ombinit.tcl TCLLIBPATH allow multiple paths sepparated by space.

Here is another addition to previous post - how to modify auto_mkindex to work.
As I said tcljava implementation of auto_mkindex contains a bug (it exist even in last tcljava release).
auto_mkindex is a general Tcl procedure which defined in init.tcl file (in tcljava implementation this file located in jacl.jar archive).
The first we need extract init.tcl file from archive - start command line in Windows and execute commands (suppose OWB installed in c:\oracle\owb10g_r2):

C:\>cd \oracle\owb10g_R2\owb\lib\int
C:\Oracle\owb10g_R2\owb\lib\int>..\..\..\jdk\bin\jar -xf jacl.jar tcl/lang/library/init.tcl
C:\Oracle\owb10g_R2\owb\lib\int>

As result we get file C:\Oracle\owb10g_R2\owb\lib\int\tcl\lang\library\init.tcl, we need to modify it  -
find in file line
puts $f $index nonewline
and replace it with
puts -nonewline $f $index

Now from command line move modified file back to archive

C:\Oracle\owb10g_R2\owb\lib\int>..\..\..\jdk\bin\jar -uf jacl.jar tcl\lang\library\init.tcl


Now auto_mkindex works under OMB*Plus:

OMB*Plus: Release 10.2.0.3.33
Copyright (c) 2000, 2006, Oracle. All rights reserved.
OMB+> auto_mkindex c:/oracle/tcllib myprocedure.tcl
OMB+>

Sunday, September 19, 2010

OMB*Plus extensibility

OMB*Plus extensibility - defining new command automatically during startup.

There are several ways to extend features of OMB*Plus for development.
OMB*Plus is an TCL interpreter based on tcljava implementation (look at OWB_HOME\owb\lib\int directory - you will find jacl.jar and tcljava.jar files which are the core of tcljava interpreter).

It is quite simple in Tcl (and in OMB*Plus) add new command - after definition of new procedure you will get new command with the name of just created procedure:

OMB*Plus: Release 10.2.0.3.33
Copyright (c) 2000, 2006, Oracle. All rights reserved.
OMB+> proc MYCOMMAND {txt} {
>   return $txt
> }
OMB+> MYCOMMAND "Text from procedure"
Text from procecure
OMB+>

If you have a lot such procedures (and use them extensively) you can include them in single file and execute this file with source command each time you start OMB*Plus.
It is possible to automate this procedure with Tcl auto_load (search for auto_load or auto_path on wiki.tcl.tk site) feature. When Tcl interpreter cannot find called command withing standard (internal) commands or defined procedures it looks directory from auto_path variable for definitions of this command via tclIndex file (this file contains for each "external" command/procedure reference to file with it definition), run file with definition this command (via source Tcl command) and finally - run requested command.

To enable auto_load feature in OMB*Plus we should make three things:
  • create file with definition of new procedure and place this file in selected directory (say to c:\oracle\tcllib)
  • create tclIndex file in the same directory
  • guide OMB*Plus where look for definitions of new procedures
First task is clear - place our MYCOMMAND procedure in file with name MyProcedure.tcl under c:\oracle\tcllib directory.
Tcl contains standard command auto_mkindex for creation tclIndex file, but tcljava implementation contains bug which prevent using this command. So we will create tclIndex file manualy (the first line is VERY IMPORTANT!):

# Tcl autoload index file, version 2.0
set auto_index(MYCOMMAND) [list source [file join $dir MyProcedure.tcl]]

Now if we add to auto_path variable our directory (MyProcedure) we will get possibility to run commands indexed in tclIndex file:

OMB+> puts $auto_path
resource:/tcl/lang/library
OMB+> info commands MY*
OMB+> MYCOMMAND
invalid command name "MYCOMMAND"
OMB+> lappend auto_path c:/oracle/tcllib
resource:/tcl/lang/library c:/oracle/tcllib
OMB+> puts $auto_path
resource:/tcl/lang/library c:/oracle/tcllib
OMB+> info commands MY*

OMB+> MYCOMMAND "Text to display"
Text to display
OMB+> info commands MY*
MYCOMMAND
OMB+>


And last thing - to set auto_path automatically it is enogh to define new environment variable TCLLIBPATH (the only problem - it seems impossible to define more than one directory via TCLLIBPATH, general method for sepparating paths on Windows OS with semicolon doesn't work for TCLLIBPATH).