window_manager.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:23k
- /*
- * ===========================================================================
- * PRODUCTION $Log: window_manager.cpp,v $
- * PRODUCTION Revision 1000.1 2004/06/01 21:14:47 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: window_manager.cpp,v 1000.1 2004/06/01 21:14:47 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Andrey Yazhuk
- *
- * File Description:
- *
- */
- #include <ncbi_pch.hpp>
- #include <gui/widgets/workspace/window_manager.hpp>
- #include <gui/widgets/workspace/wm_tab_control.hpp>
- #include <gui/widgets/workspace/wm_frame_window.hpp>
- #include <algorithm>
- BEGIN_NCBI_SCOPE
- DEFINE_MENU(BaseMenu)
- SUBMENU("Window")
- MENU_ITEM(eCmdInsHorzSplitter, "Insert Horz Splitter")
- MENU_ITEM(eCmdInsVertSplitter, "Insert Vert Splitter")
- MENU_ITEM(eCmdIns2x2Splitter, "Insert 2x2 Splitter")
- MENU_ITEM(eCmdInsTabControl, "Insert Tab Control")
- END_SUBMENU()
- END_MENU()
- BEGIN_CMD_MAP(CWindowManager, CCommandTarget)
- ON_COMMAND_RANGE(eCmdInsHorzSplitter, eCmdInsTabControl, &CWindowManager::OnInsertSplitter)
- END_CMD_MAP()
- ///////////////////////////////////////////////////////////////////////////////
- /// CWindowManager::SClientRec
- CWindowManager::SClientRec::SClientRec()
- : m_pClient(NULL),
- m_pContainer(NULL),
- m_bFrame(false)
- {
- }
- ///////////////////////////////////////////////////////////////////////////////
- /// CWindowManager
- CWindowManager::CWindowManager()
- : Fl_Group(0, 0, 1, 1),
- m_MenuRoot(NULL),
- m_pRootCont(NULL),
- m_PosIncr(40),
- m_pObserver(NULL),
- m_FrameWindow(NULL),
- m_PrevFocus(NULL),
- m_ActiveClient(NULL)
- {
- end();
- m_FrameX = Fl::x();
- m_FrameY = Fl::y();
- m_DefFrameW = Fl::w() * 3 / 5;
- m_DefFrameH = Fl::h() * 3 / 5;
-
- static int ar_size[] = { 200, 200, -1 };
- if(m_pRootCont == NULL) {
- CWMTabControl* tab = new CWMTabControl(0, 0, 1, 1);
- tab->SetResizePolicies(CTabControl::fShrink);
- tab->SetManager(this);
- m_pRootCont = tab;
- add(tab);
- resizable(tab);
- }
- m_MenuRoot = CreateMenuItems(BaseMenu);
- }
- CWindowManager::~CWindowManager()
- {
- RemoveAllClients();
- delete m_pRootCont;
- /*ITERATE(TClientToRecMap, it, m_ClientToRec) {
- delete it->second;
- }*/
- delete m_MenuRoot;
- }
- void CWindowManager::SetObserver(IWindowManagerObserver* observer)
- {
- m_pObserver = observer;
- }
- Fl_Group* CWindowManager::GetRootWMContainer()
- {
- return dynamic_cast<Fl_Group*>(m_pRootCont);
- }
- bool CWindowManager::AddClientInFrame(IWMClient* client)
- {
- return x_AddClient(client, true);
- }
- bool CWindowManager::AddClientInTab(IWMClient* client)
- {
- return x_AddClient(client, false);
- }
- bool CWindowManager::x_AddClient(IWMClient* client, bool b_frame)
- {
- Fl_Widget* widget = dynamic_cast<Fl_Widget*>(client);
- if(widget) {
- if(x_RegisterClient(client)) {
- // menus
- const CMenuItem* root = client->GetMenu();
- if(root) { // merge Client's menu into Manager's menu
- m_MenuRoot->Merge(*root);
- }
- if(m_FrameWindow) { // merge Client's menu into Frame's menu
- m_FrameWindow->MergeMenu(*root);
- }
- // add to command routing
- CCommandTarget* target = dynamic_cast<CCommandTarget*>(client);
- if(target) {
- AddChildCmdTarget(target);
- }
-
- if(b_frame) {
- x_PutClientInFrame(client);
- } else {
- x_PutClientInTab(client);
- }
- return true;
- }
- }
- _ASSERT(false);
- return false;
- }
- bool CWindowManager::MoveClientToFrame(IWMClient* client)
- {
- if(client && GetClientState(client) != eFloating) {
- x_RemoveClient(client);
- x_PutClientInFrame(client);
- x_UpdateObserver(client);
- return true;
- }
- return false;
- }
- bool CWindowManager::MoveClientToTab(IWMClient* client)
- {
- if(client && GetClientState(client) != eDocked) {
- x_RemoveClient(client);
- x_PutClientInTab(client);
- x_UpdateObserver(client);
- return true;
- }
- return false;
- }
- bool CWindowManager::FrameCommand(IWMClient* client, EFrameCmd cmd)
- {
- const SClientRec* p_rec = x_GetClientRec(client);
- if(p_rec) {
- CWMFrameWindow* p_frame =
- dynamic_cast<CWMFrameWindow*>(p_rec->m_pContainer);
- if(p_frame) {
- switch(cmd) {
- case eActivate: p_frame->show(); break;
- case eMaximize: {
- //if(p_frame->IsMinimized())
- // p_frame->show();
- p_frame->fullscreen();
- }; break;
- case eMinimize: p_frame->iconize(); break;
- case eRestore: {
- p_frame->show();
- //p_frame->fullscreen_off();
- }; break;
- };
- }
- }
- return false;
- }
- void CWindowManager::GetPopupItems(IWMContainer* container, const IWMPosition& pos,
- vector<CMenuItem*>& items)
- {
- m_PseudoCmdCount = 0;
- m_PseudoCmdMap.clear();
- if(container) {
- /*if(container != m_pRootCont) {
- items.push_back(new CMenuItem("Delete Container", eCmdDelContainer));
- items.push_back(new CMenuItem()); // separator
- }*/
- if(container->IsVacant(pos)) {
- items.push_back(new CMenuItem("Insert Horz Splitter", eCmdInsHorzSplitter));
- items.push_back(new CMenuItem("Insert Vert Splitter", eCmdInsVertSplitter));
- items.push_back(new CMenuItem("Insert 2x2 Splitter", eCmdIns2x2Splitter));
- items.push_back(new CMenuItem("Insert Tab Control", eCmdInsTabControl));
-
- // eCmdMoveFromFrame submenu
- CMenuItem* submenu = x_GetMoveFromFrameMenu(container, pos);
- if(submenu) {
- items.push_back(new CMenuItem()); // separator
- items.push_back(submenu);
- }
- // eCmdMoveHere submenu
- submenu = x_GetMoveHereMenu(container, pos);
- if(submenu) {
- items.push_back(new CMenuItem()); // separator
- items.push_back(submenu);
- }
- } else {
- if(items.size())
- items.push_back(new CMenuItem());
-
- if(dynamic_cast<const CWMTabPos*>(&pos)) {
- items.push_back(new CMenuItem("Delete Tab", eCmdDelTabPane));
- }
- items.push_back(new CMenuItem("Move to Frame", eCmdMoveToFrame));
- }
- }
- }
- /// generates a pseudo-command for popup menus. PSeudo command encodes both the
- /// real command and the client this command should be applied to.
- int CWindowManager::x_GeneratePseudoCommand(IWMClient* client, int cmd)
- {
- int pseudo_cmd = eCmdClientXXXX + m_PseudoCmdCount;
- m_PseudoCmdMap[pseudo_cmd] = make_pair(client, cmd);
- m_PseudoCmdCount++;
- return pseudo_cmd;
- }
- CMenuItem* CWindowManager::x_GetMoveFromFrameMenu(IWMContainer* container,
- const IWMPosition& pos)
- {
- CMenuItem* p_submenu = NULL;
- if(container->IsVacant(pos)) {
- int i = 0;
- ITERATE(TClientToRecMap, it, m_ClientToRec) {
- SClientRec* p_rec = it->second;
- if(p_rec->m_pContainer && p_rec->m_bFrame) {
- if(! p_submenu)
- p_submenu = new CMenuItem("Dock Here");
-
- int pcmd = x_GeneratePseudoCommand(p_rec->m_pClient, eCmdMoveFromFrame);
- p_submenu->AddSubItem(p_rec->m_pClient->GetLabel(), pcmd);
- }
- }
- }
- return p_submenu;
- }
- CMenuItem* CWindowManager::x_GetMoveHereMenu(IWMContainer* container,
- const IWMPosition& pos)
- {
- CMenuItem* p_submenu = NULL;
- if(container->IsVacant(pos)) {
- int i = 0;
- ITERATE(TClientToRecMap, it, m_ClientToRec) {
- SClientRec* p_rec = it->second;
- if(! (p_rec->m_pContainer && p_rec->m_bFrame)) {
- if(! p_submenu)
- p_submenu = new CMenuItem("Move Here");
-
- int pcmd = x_GeneratePseudoCommand(p_rec->m_pClient, eCmdMoveToPos);
- p_submenu->AddSubItem(p_rec->m_pClient->GetLabel(), pcmd);
- }
- }
- }
- return p_submenu;
- }
- bool CWindowManager::OnContainerCommand(IWMContainer* container, const IWMPosition& pos,
- TCmdID cmd)
- {
- if(container) {
- switch(cmd) {
- case eCmdInsHorzSplitter: {
- x_InsertSplitter(container, pos, CSplitter::eHorizontal);
- return true;
- };
- case eCmdInsVertSplitter: {
- x_InsertSplitter(container, pos, CSplitter::eVertical);
- return true;
- };
- case eCmdIns2x2Splitter: {
- x_InsertSplitter(container, pos, CSplitter::eGrid);
- return true;
- };
- case eCmdInsTabControl: {
- CWMTabControl* tab = new CWMTabControl(0, 0, 200, 200);
- tab->SetManager(this);
- container->Insert(tab, pos);
- return true;
- }; break;
- case eCmdDelContainer: x_RemoveContainer(container);
- case eCmdDelTabPane: x_Remove(container, pos); return true;
- case eCmdMoveToFrame: OnMoveToFrame(container, pos); return true;
- default:
- if(cmd >= eCmdClientXXXX && cmd < eCmdClientLast) {
- return x_OnPseudoCommand(container, pos, cmd);
- }
- }
- }
- return false;
- }
- bool CWindowManager::x_OnPseudoCommand(IWMContainer* container, const IWMPosition& pos,
- TCmdID cmd)
- {
- TPseudoCmdMap::iterator it = m_PseudoCmdMap.find(cmd);
- if(it != m_PseudoCmdMap.end()) {
- IWMClient* p_client = it->second.first;
- int orig_cmd = it->second.second;
-
- switch(orig_cmd) {
- case eCmdMoveToPos: {
- x_RemoveClient(p_client);
- x_InsertClient(p_client, container, pos);
- x_UpdateObserver(p_client);
- return true;
- }; break;
- case eCmdMoveFromFrame: {
- x_RemoveClient(p_client);
- x_InsertClient(p_client, container, pos);
- x_UpdateObserver(p_client);
- return true;
- }; break;
- default: break;
- }; //switch
- } else _ASSERT(false);
- return false;
- }
- void CWindowManager::OnMoveToFrame(IWMContainer* container, const IWMPosition& pos)
- {
- _ASSERT(pos.IsValid());
-
- Fl_Widget* widget = container->GetChild(pos);
- IWMClient* p_client = dynamic_cast<IWMClient*>(widget);
- if(p_client) {
- x_RemoveClient(p_client);
- x_PutClientInFrame(p_client);
- x_UpdateObserver(p_client);
- }
- }
- void CWindowManager::x_InsertClient(IWMClient* client, IWMContainer* container,
- const IWMPosition& pos)
- {
- SClientRec* p_rec = x_GetClientRec(client);
- _ASSERT(p_rec->m_pContainer == NULL);
- p_rec->m_pContainer = container;
- Fl_Widget* widget = dynamic_cast<Fl_Widget*>(client);
- _ASSERT(widget);
- container->Insert(widget, pos);
- }
- /// removes Client or container from specified position
- void CWindowManager::x_Remove(IWMContainer* container, const IWMPosition& pos)
- {
- Fl_Widget* child = container->GetChild(pos);
- x_CascadeRemove(container, child);
- }
- /// removes widgets from it's container and recursiveli removes all its children
- void CWindowManager::x_CascadeRemove(IWMContainer* container, Fl_Widget* child)
- {
- IWMClient* p_client = dynamic_cast<IWMClient*>(child);
- if(p_client) {
- x_RemoveClient(p_client);
- } else {
- IWMContainer* p_cont = dynamic_cast<IWMContainer*>(child);
- if(p_cont) {
- container->Remove(child);
- // remove child's children
- vector<Fl_Widget*> children;
- p_cont->GetChildren(children);
- for( size_t i = 0; i < children.size(); i++ ) {
- Fl_Widget* child = children[i];
- x_CascadeRemove(p_cont, child);
- }
- delete p_cont;
- } else _ASSERT(false); // unexpected
- }
- }
- void CWindowManager::x_RemoveContainer(IWMContainer* container)
- {
- if(container != m_pRootCont) {
- Fl_Widget* widget = dynamic_cast<Fl_Widget*>(container);
- _ASSERT(widget);
- IWMContainer* parent_cont = dynamic_cast<IWMContainer*>(widget->parent());
-
- x_CascadeRemove(parent_cont, widget);
- }
- }
- void CWindowManager::x_RemoveClient(IWMClient* client)
- {
- SClientRec* p_rec = x_GetClientRec(client);
- if(p_rec)
- x_RemoveClient(p_rec);
- }
- // removes client from its current container, but does not unregister it
- void CWindowManager::x_RemoveClient(SClientRec* rec)
- {
- _ASSERT(rec);
- if(rec->m_pClient == m_ActiveClient) { // reset active client
- m_ActiveClient = NULL;
- m_PrevFocus = NULL;
- }
-
- CCommandTarget* target = dynamic_cast<CCommandTarget*>(rec->m_pClient);
- if(target) { // disconnect from command routing
- RemoveChildCmdTarget(target);
- }
- // remove from the container
- Fl_Widget* widget = dynamic_cast<Fl_Widget*>(rec->m_pClient);
- if(rec->m_pContainer) {
- rec->m_pContainer->Remove(widget);
-
- CWMFrameWindow* p_frame = dynamic_cast<CWMFrameWindow*>(rec->m_pContainer);
- if(p_frame) { // if container - frame, destroy it
- delete p_frame;
- }
- rec->m_pContainer = NULL;
- rec->m_bFrame = false;
- }
- }
- bool CWindowManager::RemoveClient(IWMClient* client)
- {
- TClientToRecMap::iterator it = m_ClientToRec.find(client);
- if(it != m_ClientToRec.end()) {
- SClientRec* p_rec = it->second;
- x_RemoveClient(p_rec);
- x_UnRegisterClient(client);
- x_ResetMenu();
- return true;
- }
- return false;
- }
- void CWindowManager::RemoveAllClients()
- {
- while(m_ClientToRec.size()) {
- SClientRec* p_rec = m_ClientToRec.begin()->second;
- x_RemoveClient(p_rec);
- x_UnRegisterClient(p_rec->m_pClient);
- }
- x_ResetMenu();
- }
- IWMClient* CWindowManager::GetActiveClient()
- {
- return m_ActiveClient;
- }
- /// Regenerate Window Manager's menu and request Frame Window to reset it's menu.
- void CWindowManager::x_ResetMenu()
- {
- if(m_FrameWindow) {
- m_MenuRoot = CreateMenuItems(BaseMenu);
- ITERATE(TClientToRecMap, it, m_ClientToRec) {
- SClientRec* p_rec = it->second;
- if(p_rec->m_pContainer) { ///###
- const CMenuItem* root = p_rec->m_pClient->GetMenu();
- if(root) { // merge Client's menu into Manager's menu
- m_MenuRoot->Merge(*root);
- }
- }
- }
-
- // Reseting Frame Window's will automatically request the new menu from Window Manager
- // so that our changes to it will take effect
- m_FrameWindow->ResetMenu();
- }
- }
- // creates entry in m_ClientToRec table if it does not exist
- bool CWindowManager::x_RegisterClient(IWMClient* client)
- {
- if(client && m_ClientToRec.find(client) == m_ClientToRec.end()) {
- SClientRec* p_rec = new SClientRec;
- p_rec->m_pClient = client;
- p_rec->m_pContainer = NULL;
- p_rec->m_bFrame = false;
-
- m_ClientToRec[client] = p_rec;
- return true;
- }
- return false;
- }
- // deletes m_ClientToRec entry corresponding to the client
- bool CWindowManager::x_UnRegisterClient(IWMClient* client)
- {
- TClientToRecMap::iterator it = m_ClientToRec.find(client);
- if(it != m_ClientToRec.end()) {
- delete it->second;
- m_ClientToRec.erase(it);
- return true;
- }
- return false;
- }
- CWindowManager::EClientState CWindowManager::GetClientState(IWMClient* client)
- {
- SClientRec* p_rec = x_GetClientRec(client);
- if(p_rec) {
- if(p_rec->m_pContainer) {
- return p_rec->m_bFrame ? eFloating : eDocked;
- } else return eHidden;
- }
- return eInvalid;
- }
- CWindowManager::SClientRec* CWindowManager::x_GetClientRec(IWMClient* client)
- {
- TClientToRecMap::iterator it = m_ClientToRec.find(client);
- return (it == m_ClientToRec.end()) ? NULL : it->second;
- }
- /// Creates new CWMFrameWindow and inserts client into it.
- void CWindowManager::x_PutClientInFrame(IWMClient* client)
- {
- Fl_Widget* widget = dynamic_cast<Fl_Widget*>(client);
- SClientRec* p_rec = m_ClientToRec[client];
- _ASSERT(widget);
-
- CWMFrameWindow* p_frame =
- new CWMFrameWindow(m_FrameX, m_FrameY, m_DefFrameW, m_DefFrameH,
- widget->label());
- m_FrameX += m_PosIncr;
- if(m_FrameX + m_DefFrameW > Fl::x() + Fl::w()) {
- m_FrameX = Fl::x();
- }
- m_FrameY += m_PosIncr;
- if(m_FrameY + m_DefFrameH > Fl::y() + Fl::h()) {
- m_FrameY = Fl::y();
- }
-
- CWMFrameWndPos* p_pos = new CWMFrameWndPos(true);
- bool b_ok = p_frame->Insert(widget, *p_pos);
- _ASSERT(b_ok);
- // filling SClientRec
- p_rec->m_pContainer = static_cast<IWMContainer*>(p_frame);
- p_rec->m_bFrame = true;
- p_frame->show();
- }
- void CWindowManager::x_PutClientInTab(IWMClient* client)
- {
- CWMTabControl* p_tab = dynamic_cast<CWMTabControl*>(m_pRootCont);
- _ASSERT(p_tab);
- int index = p_tab->GetTabsCount();
- CWMTabPos pos(index);
-
- x_InsertClient(client, m_pRootCont, pos);
- }
- void CWindowManager::x_GetFramedClients(TClients& clients)
- {
- clients.clear();
- ITERATE(TClientToRecMap, it, m_ClientToRec) {
- SClientRec* p_rec = it->second;
- if(p_rec->m_bFrame) {
- clients.push_back(it->first);
- }
- }
- }
- static int s_iColor = 0;
- const static int kColors = 4;
- static Fl_Color GetRandomColor()
- {
- s_iColor = (s_iColor + 1) % kColors;
- switch(s_iColor) {
- case 0: return fl_rgb_color(192, 192, 255);
- case 1: return fl_rgb_color(255, 192, 192);
- case 2: return fl_rgb_color(192, 255, 192);
- case 3: return fl_rgb_color(255, 192, 255);
- }
- return FL_MAGENTA;
- }
- void CWindowManager::x_InsertSplitter(IWMContainer* container, const IWMPosition& pos,
- CSplitter::EMode mode)
- {
- CWMSplitter* splitter = new CWMSplitter();
- splitter->SetManager(this);
- splitter->color(GetRandomColor());
- container->Insert(splitter, pos);
-
- switch(mode) {
- case CSplitter::eHorizontal: splitter->Create(2, 1); break;
- case CSplitter::eVertical: splitter->Create(1, 2); break;
- case CSplitter::eGrid: splitter->Create(2, 2); break;
- }
- }
- void CWindowManager::x_UpdateObserver(IWMClient* client)
- {
- if(m_pObserver)
- m_pObserver->OnClientChanged(client);
- }
- const CMenuItem* CWindowManager::GetMenu() const
- {
- return m_MenuRoot;
- }
- void CWindowManager::SetFrameWindow(CFrameWindow* frame)
- {
- m_FrameWindow = frame;
- }
- bool CWindowManager::x_ChildrenHandleCommand(const TCmdID cmd)
- {
- // update pointer to active client
- Fl_Widget* focused = Fl::focus();
- if(focused != m_PrevFocus) {
- m_PrevFocus = focused;
- m_ActiveClient = NULL;
- //check is focused widget is our client or a child of our client
- for( Fl_Widget* wid = focused; wid != NULL; wid = wid->parent()) {
- IWMClient* client = dynamic_cast<IWMClient*>(wid);
- if(client && x_GetClientRec(client)) { // this our client
- m_ActiveClient = client;
- break;
- }
- }
- }
- bool b_handled = false;
- ///### overhead
- CCommandTarget* target = dynamic_cast<CCommandTarget*>(m_ActiveClient);
- if(target) {
- b_handled = target->OnCommand(cmd);
- }
- if(! b_handled) {
- NON_CONST_ITERATE(TChildTargets, it, m_ChildTargets) {
- if(*it != target && (*it)->OnCommand(cmd))
- return true;
- }
- }
- return b_handled;
- }
- bool CWindowManager::x_ChildrenUpdateCommand(const TCmdID cmd, ICmdUI* pCmdUI)
- {
- // update pointer to active client
- Fl_Widget* focused = Fl::focus();
- if(focused != m_PrevFocus) {
- m_PrevFocus = focused;
- m_ActiveClient = NULL;
- //check is focused widget is our client or a child of our client
- for( Fl_Widget* wid = focused; wid != NULL; wid = wid->parent()) {
- IWMClient* client = dynamic_cast<IWMClient*>(wid);
- if(client && x_GetClientRec(client)) { // this our client
- m_ActiveClient = client;
- break;
- }
- }
- }
- bool b_handled = false;
- ///### overhead
- CCommandTarget* target = dynamic_cast<CCommandTarget*>(m_ActiveClient);
- if(target) {
- b_handled = target->OnUpdateCommand(cmd, pCmdUI);
- }
- if(! b_handled) {
- NON_CONST_ITERATE(TChildTargets, it, m_ChildTargets) {
- if(*it != target && (*it)->OnUpdateCommand(cmd, pCmdUI))
- return true;
- }
- }
- return b_handled;
- }
- void CWindowManager::OnInsertSplitter(TCmdID cmd)
- {
- CWMTabPos pos(m_pRootCont->GetTabsCount());
- OnContainerCommand(m_pRootCont, pos, cmd);
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: window_manager.cpp,v $
- * Revision 1000.1 2004/06/01 21:14:47 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
- *
- * Revision 1.3 2004/05/21 22:27:56 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.2 2004/05/07 14:26:58 yazhuk
- * Inherited CWindowManager from Fl_Group, CCommandTarget; implemented IFrameWindowClient
- *
- * Revision 1.1 2004/02/04 19:41:55 yazhuk
- * Initial revision
- *
- * ===========================================================================
- */