source: Scheduling/trunk/cs/bsdx0200GUISourceCode/CGDocumentManager.cs@ 1329

Last change on this file since 1329 was 1143, checked in by Sam Habiel, 14 years ago

CalendarGrid: Many changes:

  1. Dragover handler to handle auto scrolling when dragging. Also highlights destination cell in dragging.
  2. Solution for the click-right click problem by better handling of right click issues.
  3. New method OnRButtonDown()
  4. Extra comments everywhere.
  5. Fix for single column being enabled when there are multiple resources. Columns property now calls this.SetColumnInfo() to rectify that problem.

CGDocument:

  1. EditAppoitment Used to send request a refresh from the DB and update the view itself, rather than letting the view handle that. That's now changed.

CGDocumentManager:

  1. MessageBox displayed during login splash now are shown BY the splash form.

CGView:

  1. Shortcuts and some display text updated.
  2. Splash screen when updating now removed.
  3. If print appointment slip checkbox is checked when EditAppointment is chosen, now it will print the routing slip.
  4. Tiny change in appointment structure generated during drag and drop (added Patient member, as it was causing a crash)

DApptSearch:

  1. Change of name of Appointment to Slot, for better user understanding.

DSplash:

  1. RemoteMessage box methods and associated delegates for mickey mousing the form from another thread.

Updated release exes and dlls

File size: 47.9 KB
Line 
1using System;
2using System.Windows.Forms;
3using System.Collections;
4using System.Data;
5using System.Diagnostics;
6using System.Threading;
7using IndianHealthService.BMXNet;
8using Mono.Options;
9using System.Runtime.InteropServices;
10using System.Globalization;
11
12namespace IndianHealthService.ClinicalScheduling
13{
14 /// <summary>
15 /// Main Worker. Handles sub-forms.
16 /// </summary>
17 public class CGDocumentManager //: System.Windows.Forms.Form
18 {
19 #region Member Variables
20
21 private static CGDocumentManager _current;
22 private Hashtable _views = new Hashtable(); //Returns the list of currently opened documents
23 private Hashtable m_AVViews = new Hashtable(); // List of currently opened CGAVViews
24 private string m_sWindowText = "Clinical Scheduling"; //Default Window Text
25 private bool m_bSchedManager = false; // Do you have the XUPROGMODE or BSDXZMGR?
26 private bool m_bExitOK = true; // Okay to exit program? Used to control Re-logins. Default true.
27 public string m_sHandle = "0"; // Not Used
28
29 //Connection variables (tied to command line parameters /a /v /s /p /e)
30 private string m_AccessCode="";
31 private string m_VerifyCode="";
32 private string m_Server="";
33 private int m_Port=0;
34 private string m_Encoding=""; //Encoding is "" by default;
35
36 //Globalization Object (tied to command line parameter /culture)
37 private string m_CultureName = "";
38
39 //Data Access Layer
40 private DAL _dal = null;
41
42 //M Connection member variables
43 private DataSet m_dsGlobal = null; // Holds all user data
44 private BMXNetConnectInfo m_ConnectInfo = null; // Connection to VISTA object
45 private BMXNetConnectInfo.BMXNetEventDelegate CDocMgrEventDelegate; // Delegate to respond to messages from VISTA. Responds to event: BMXNetConnectInfo.BMXNetEvent
46
47 //Custom Printing
48 private Printing m_PrintingObject = null;
49 #endregion
50
51 #region Properties
52
53 /// <summary>
54 /// Returns the document manager's BMXNetConnectInfo member
55 /// </summary>
56 public BMXNetConnectInfo ConnectInfo
57 {
58 get
59 {
60 return m_ConnectInfo;
61 }
62 }
63
64 /// <summary>
65 /// True if the current user holds the BSDXZMGR or XUPROGMODE keys in RPMS
66 /// </summary>
67 public bool ScheduleManager
68 {
69 get
70 {
71 return m_bSchedManager;
72 }
73 }
74
75 /// <summary>
76 /// Holds the user and division
77 /// </summary>
78 public string WindowText
79 {
80 get
81 {
82 return m_sWindowText;
83 }
84 }
85
86 /// <summary>
87 /// This dataset contains tables used by the entire application
88 /// </summary>
89 public DataSet GlobalDataSet
90 {
91 get
92 {
93 return m_dsGlobal;
94 }
95 set
96 {
97 m_dsGlobal = value;
98 }
99 }
100
101 /// <summary>
102 /// User Preferences Auto Property
103 /// </summary>
104 public UserPreferences UserPreferences { get; private set; }
105
106 /// <summary>
107 /// Returns the single CGDocumentManager object
108 /// </summary>
109 public static CGDocumentManager Current
110 {
111 get
112 {
113 return _current;
114 }
115 }
116
117
118 /// <summary>
119 /// Returns the list of currently opened documents
120 /// </summary>
121 public Hashtable Views
122 {
123 get
124 {
125 return _views;
126 }
127 }
128
129 /// <summary>
130 /// Returns the list of currently opened CGAVViews
131 /// </summary>
132 public Hashtable AvailabilityViews
133 {
134 get
135 {
136 return this.m_AVViews;
137 }
138 }
139
140 public DAL DAL
141 {
142 get { return this._dal; }
143 }
144
145 public Printing PrintingObject
146 {
147 get
148 {
149 return this.m_PrintingObject;
150 }
151 }
152 #endregion
153
154 /// <summary>
155 /// Constructor. Does absolutely nothing at this point.
156 /// </summary>
157 public CGDocumentManager()
158 {
159 }
160
161
162#if DEBUG
163 //To write to the console
164 [DllImport("kernel32.dll")]
165 static extern bool AttachConsole(int dwProcessId);
166 private const int ATTACH_PARENT_PROCESS = -1;
167#endif
168 /// <summary>
169 /// Main Entry Point
170 /// </summary>
171 /// <param name="args">We accept the following Arguments:
172 /// /s or -s = Server ip address or name
173 /// /p or -p = port number (must be numeric)
174 /// /a or -a = Access Code
175 /// /v or -v = Verify Code
176 /// /e or -e = Encoding (name of encoding as known to windows, such as windows-1256)
177 /// /culture or -culture = Culture Name for UI Culture if you wish to override the Windows Culture
178 /// </param>
179 /// <remarks>
180 /// Encoding decision is complex. This is the order of priority:
181 /// - If the M DB runs in UTF-8, that's what we are going to use.
182 /// - If that's not so, /e sets the default encoding. If /e is a non-existent encoding, move to next step.
183 /// - If /e is not supplied or is not recognized, the default encoding is the Windows default Encoding for the user.
184 /// </remarks>
185 [STAThread()]
186 static void Main(string[] args)
187 {
188 //Application wide error handler for unhandled errors (later I figure out that's only for WinForm ex'es)
189 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
190 Application.ThreadException += new ThreadExceptionEventHandler(App_ThreadException);
191
192 // Add the event handler for handling non-UI thread exceptions to the event.
193 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(App_DomainException);
194
195#if DEBUG
196 // Print console messages to console if launched from console
197 // Note: Imported From kernel32.dll
198 AttachConsole(ATTACH_PARENT_PROCESS);
199#endif
200
201#if TRACE
202 DateTime startLoadTime = DateTime.Now;
203#endif
204
205 //Store a class instance of manager. Actual constructor does nothing.
206 _current = new CGDocumentManager();
207
208 //Get command line options; store in private class wide variables
209 var opset = new OptionSet() {
210 { "s=", s => _current.m_Server = s },
211 { "p=", p => _current.m_Port = int.Parse(p) },
212 { "a=", a => _current.m_AccessCode = a },
213 { "v=", v => _current.m_VerifyCode = v },
214 { "e=", e => _current.m_Encoding = e},
215 { "culture=", culture => _current.m_CultureName = culture }
216 };
217
218 opset.Parse(args);
219
220 //Init app
221 bool isEverythingOkay = _current.InitializeApp();
222
223 //if an error occurred, break out.
224 if (!isEverythingOkay) return;
225
226 //Create the first empty document
227 //A document holds the resources, appointments, and availabilites
228 //SAM: Good place for break point
229 CGDocument doc = new CGDocument();
230 doc.DocManager = _current;
231
232 //Create new View
233 //A view is a specific arrangement of appointments and availabilites that constitute a document
234 CGView view = new CGView();
235 view.InitializeDocView(doc, _current, doc.StartDate, _current.WindowText);
236
237 //Handle BMX Event
238 Application.DoEvents();
239
240 //test
241 //doc.ThrowException();
242 //test
243
244#if TRACE
245 DateTime EndLoadTime = DateTime.Now;
246 TimeSpan LoadTime = EndLoadTime - startLoadTime;
247 Debug.Write("Load Time for GUI is " + LoadTime.Seconds + " s & " + LoadTime.Milliseconds + " ms\n");
248#endif
249
250 view.Show();
251 view.Activate();
252
253 Application.Run();
254 }
255
256 /// <summary>
257 /// Exception handler for application errors. Only for WinForm Errors.
258 /// </summary>
259 /// <remarks>Never tested. I can't get an error to go here!</remarks>
260 /// <param name="sender"></param>
261 /// <param name="e"></param>
262 static void App_ThreadException(object sender, ThreadExceptionEventArgs e)
263 {
264 string msg = "A problem has occured in this applicaton. \r\n\r\n" +
265 "\t" + e.Exception.Message + "\r\n\r\n" +
266 "Would you like to continue the application?";
267
268 DialogResult res = MessageBox.Show(msg, "Unexpected Error", MessageBoxButtons.YesNo);
269
270 if (res == DialogResult.Yes) return;
271 else Application.Exit();
272 }
273
274 /// <summary>
275 /// If we are here, we are dead meat.
276 /// </summary>
277 /// <param name="sender"></param>
278 /// <param name="e"></param>
279 static void App_DomainException(object sender, UnhandledExceptionEventArgs e)
280 {
281 if (e.ExceptionObject is System.Net.Sockets.SocketException)
282 {
283 MessageBox.Show("Looks like we lost our connection with the server\nClick OK to terminate the application.");
284 }
285 else
286 {
287 Exception ex = e.ExceptionObject as Exception;
288
289 string msg = "A problem has occured in this applicaton. \r\n\r\n" +
290 "\t" + ex.InnerException.Message;
291
292 MessageBox.Show(msg, "Unexpected Error");
293 }
294 }// here application terminates
295
296 #region BMXNet Event Handler
297 private void CDocMgrEventHandler(Object obj, BMXNet.BMXNetEventArgs e)
298 {
299 if (e.BMXEvent == "BSDX CALL WORKSTATIONS")
300 {
301 string sParam = "";
302 string sDelim="~";
303 sParam += this.m_ConnectInfo.UserName + sDelim;
304 sParam += this.m_sHandle + sDelim;
305 sParam += Application.ProductVersion + sDelim;
306 sParam += this._views.Count.ToString();
307 _current.m_ConnectInfo.RaiseEvent("BSDX WORKSTATION REPORT", sParam, true);
308 }
309 if (e.BMXEvent == "BSDX ADMIN MESSAGE")
310 {
311 string sMsg = e.BMXParam;
312 ShowAdminMsgDelegate samd = new ShowAdminMsgDelegate(ShowAdminMsg);
313 //this.Invoke(samd, new object [] {sMsg});
314 samd.Invoke(sMsg);
315 }
316 if (e.BMXEvent == "BSDX ADMIN SHUTDOWN")
317 {
318 string sMsg = e.BMXParam;
319 CloseAllDelegate cad = new CloseAllDelegate(CloseAll);
320 //this.Invoke(cad, new object [] {sMsg});
321 cad.Invoke(sMsg);
322 }
323 }
324
325 delegate void ShowAdminMsgDelegate(string sMsg);
326
327 private void ShowAdminMsg(string sMsg)
328 {
329 MessageBox.Show(sMsg, "Message from Scheduling Administrator", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
330 }
331
332 #endregion BMXNet Event Handler
333
334
335 #region Methods & Events
336
337 /// <summary>
338 /// See InitializeApp(bool) below
339 /// </summary>
340 private bool InitializeApp()
341 {
342 return InitializeApp(false);
343 }
344
345 /// <summary>
346 /// Does a million things:
347 /// 1. Starts Connection and displays log-in dialogs
348 /// 2. Starts Splash screen
349 /// 3. Loads data tables
350 /// </summary>
351 /// <param name="bReLogin">Is the User logging in again from a currently running instance?
352 /// If so, display a dialog to collect access and verify codes.</param>
353 private bool InitializeApp(bool bReLogin)
354 {
355 //Set M connection info
356 m_ConnectInfo = new BMXNetConnectInfo(m_Encoding); // Encoding is "" unless passed in command line
357 _dal = new DAL(m_ConnectInfo); // Data access layer
358 //m_ConnectInfo.bmxNetLib.StartLog(); //This line turns on logging of messages
359
360 //Create a delegate to process events raised by BMX.
361 CDocMgrEventDelegate = new BMXNetConnectInfo.BMXNetEventDelegate(CDocMgrEventHandler);
362 //Tie delegate to Events generated by BMX.
363 m_ConnectInfo.BMXNetEvent += CDocMgrEventDelegate;
364 //Disable polling (But does this really work???? I don't see how it gets disabled)
365 m_ConnectInfo.EventPollingEnabled = false;
366
367 //Show a splash screen while initializing; define delegates to remote thread
368 DSplash m_ds = new DSplash();
369 DSplash.dSetStatus setStatusDelegate = new DSplash.dSetStatus(m_ds.SetStatus);
370 DSplash.dAny closeSplashDelegate = new DSplash.dAny(m_ds.RemoteClose);
371 DSplash.dProgressBarSet setMaxProgressDelegate = new DSplash.dProgressBarSet(m_ds.RemoteProgressBarMaxSet);
372 DSplash.dProgressBarSet setProgressDelegate = new DSplash.dProgressBarSet(m_ds.RemoteProgressBarValueSet);
373
374 //Start new thread for the Splash screen.
375 Thread threadSplash = new Thread(new ParameterizedThreadStart(frm => ((DSplash)frm).ShowDialog()));
376 threadSplash.IsBackground = true; //expendable thread -- exit even if still running.
377 threadSplash.Name = "Splash Thread";
378 threadSplash.Start(m_ds); // pass form as parameter.
379
380 //There are 21 steps to load the application. That's max for the progress bar.
381 setMaxProgressDelegate(21);
382
383 // smh--not used: System.Configuration.ConfigurationManager.GetSection("appSettings");
384
385 setStatusDelegate("Connecting to VISTA");
386
387 //Try to connect using supplied values for Server and Port
388 //Why am I doing this? The library BMX net uses prompts for access and verify code
389 //whether you can connect or not. Not good. So I test first whether
390 //we can connect at all by doing a simple connection and disconnect.
391 //TODO: Make this more robust by sending a TCPConnect message and seeing if you get a response
392 if (m_Server != "" && m_Port != 0)
393 {
394 System.Net.Sockets.TcpClient tcpClient = new System.Net.Sockets.TcpClient();
395 try
396 {
397 tcpClient.Connect(m_Server, m_Port); // open it
398 tcpClient.Close(); // then close it
399 }
400 catch (System.Net.Sockets.SocketException)
401 {
402 m_ds.RemoteMsgBox("Can't connect to server! Network Error");
403 return false;
404 }
405 }
406
407
408 bool bRetry = true;
409
410 // Do block is Log-in logic
411 do
412 {
413 // login crap
414 try
415 {
416 // Not my code
417 if (bReLogin == true)
418 {
419 //Prompt for Access and Verify codes
420 _current.m_ConnectInfo.LoadConnectInfo("", "");
421 }
422 // My code -- buts looks so ugly!
423 // Checks the passed parameters stored in the class variables
424 else
425 {
426 if (m_Server != String.Empty && m_Port != 0 && m_AccessCode != String.Empty
427 && m_VerifyCode != String.Empty)
428 {
429 m_ConnectInfo.LoadConnectInfo(m_Server, m_Port, m_AccessCode, m_VerifyCode);
430 }
431 else if (m_Server != String.Empty && m_Port != 0)
432 m_ConnectInfo.LoadConnectInfo(m_Server, m_Port, "", "");
433 else
434 m_ConnectInfo.LoadConnectInfo();
435 }
436 bRetry = false;
437 }
438 catch (System.Net.Sockets.SocketException)
439 {
440 m_ds.RemoteMsgBox("Cannot connect to VistA. Network Error");
441 }
442 catch (BMXNetException ex)
443 {
444 if (m_ds.RemoteMsgBox("Unable to connect to VistA. " + ex.Message, "Clinical Scheduling", MessageBoxButtons.RetryCancel) == DialogResult.Retry)
445 {
446 bRetry = true;
447 //I hate this, but this is how the library is designed. It throws an error if the user cancels. XXX: Won't fix library until BMX 4.0 port.
448 try { _current.m_ConnectInfo.ChangeServerInfo(); }
449 catch (Exception)
450 {
451 closeSplashDelegate();
452 bRetry = false;
453 return false; //tell main that it's a no go.
454 }
455 }
456 else
457 {
458 closeSplashDelegate();
459 bRetry = false;
460 return false; //tell main that it's a no go.
461 }
462 }
463 }while (bRetry == true);
464
465 //Printing
466
467 string DllLocation = string.Empty;
468 System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(Application.StartupPath + @"\Printing\");
469 if (di.Exists)
470 {
471 System.IO.FileInfo[] rgFiles = di.GetFiles("*.dll");
472
473 foreach (System.IO.FileInfo fi in rgFiles)
474 {
475 DllLocation = fi.FullName;
476 }
477 }
478
479 PrintingCreator Creator = null;
480 if (DllLocation == string.Empty)
481 {
482 this.m_PrintingObject = new Printing();
483 }
484 else
485 {
486 System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(DllLocation);
487 foreach (Type type in assembly.GetTypes())
488 {
489 if (type.IsClass == true & type.BaseType == typeof(PrintingCreator))
490 {
491 Creator = (PrintingCreator)Activator.CreateInstance(type);
492 break;
493 }
494 }
495 this.m_PrintingObject = Creator.PrintFactory();
496 }
497
498
499 //User Interface Culture (m_CultureName is set from the command line flag /culture)
500 //
501 //If passed, set that try that culture; fail over to Invariant Culture
502 if (m_CultureName != String.Empty)
503 {
504 try { Thread.CurrentThread.CurrentUICulture = new CultureInfo(m_CultureName); }
505 catch (CultureNotFoundException) { Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; }
506 }
507 //otherwise, use the Current Computer Culture, EVEN IF (!!) the UI Culture is different.
508 //this allows localization even if Windows still displays messages in English.
509 else
510 {
511 Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
512 }
513
514 //Create global dataset
515 _current.m_dsGlobal = new DataSet("GlobalDataSet");
516
517 //Version info
518 // Table #1
519 setProgressDelegate(1);
520 setStatusDelegate("Getting Version Info from Server...");
521
522 DataTable ver = _dal.GetVersion("BSDX");
523 ver.TableName = "VersionInfo";
524 m_dsGlobal.Tables.Add(ver);
525
526 //How to extract the version numbers:
527 DataTable dtVersion = m_dsGlobal.Tables["VersionInfo"];
528 Debug.Assert(dtVersion.Rows.Count == 1);
529 DataRow rVersion = dtVersion.Rows[0];
530 string sMajor = rVersion["MAJOR_VERSION"].ToString();
531 string sMinor = rVersion["MINOR_VERSION"].ToString();
532 string sBuild = rVersion["BUILD"].ToString();
533 decimal fBuild = Convert.ToDecimal(sBuild);
534
535 //Make sure that the server is running the same version the client is.
536 Version x = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
537
538 //if version numbers mismatch, don't continue.
539 if (!(x.Major.ToString() == sMajor && x.Minor.ToString() == sMinor))
540 {
541 MessageBox.Show(
542 "Server runs version " + sMajor + "." + sMinor + "\r\n" +
543 "You are running " + x.ToString() + "\r\n\r\n" +
544 "Major, Minor and Build versions must match",
545 "Version Mismatch");
546 closeSplashDelegate();
547 return false;
548 }
549
550
551 //Change encoding
552 // Call #2
553 setProgressDelegate(2);
554 setStatusDelegate("Setting encoding...");
555
556 if (m_Encoding == String.Empty)
557 {
558 string utf8_server_support = m_ConnectInfo.bmxNetLib.TransmitRPC("BMX UTF-8", "");
559 if (utf8_server_support == "1")
560 m_ConnectInfo.bmxNetLib.Encoder = System.Text.UTF8Encoding.UTF8;
561 }
562
563 //Set application context
564 // Call #3
565 setProgressDelegate(3);
566 setStatusDelegate("Setting Application Context to BSDXRPC...");
567 m_ConnectInfo.AppContext = "BSDXRPC";
568
569 //User Preferences Object
570 setProgressDelegate(4); //next number is 6 b/c two calls
571 setStatusDelegate("Getting User Preferences from the Server...");
572
573 _current.UserPreferences = new UserPreferences(); // Does the calling to do that...
574
575 //Load global recordsets
576 string statusConst = "Loading VistA data tables...";
577 setStatusDelegate(statusConst);
578
579 string sCommandText;
580
581 //Schedule User Info
582 // Table #4
583 setProgressDelegate(6);
584 setStatusDelegate(statusConst + " Schedule User");
585 DataTable dtUser = _dal.GetUserInfo(m_ConnectInfo.DUZ);
586 dtUser.TableName = "SchedulingUser";
587 m_dsGlobal.Tables.Add(dtUser);
588 Debug.Assert(dtUser.Rows.Count == 1);
589
590 // Only one row and one column named "MANAGER". Set local var m_bSchedManager to true if Manager.
591 DataRow rUser = dtUser.Rows[0];
592 Object oUser = rUser["MANAGER"];
593 string sUser = oUser.ToString();
594 m_bSchedManager = (sUser == "YES") ? true : false;
595
596 //Get Access Types
597 // Table #5
598 setProgressDelegate(7);
599 setStatusDelegate(statusConst + " Access Types");
600 DataTable dtAccessTypes = _dal.GetAccessTypes();
601 dtAccessTypes.TableName = "AccessTypes";
602 m_dsGlobal.Tables.Add(dtAccessTypes);
603
604 //Get Access Groups
605 // Table #6
606 setProgressDelegate(8);
607 setStatusDelegate(statusConst + " Access Groups");
608 LoadAccessGroupsTable();
609
610 //Build Primary Key for AccessGroup table
611 DataTable dtGroups = m_dsGlobal.Tables["AccessGroup"];
612 DataColumn dcKey = dtGroups.Columns["ACCESS_GROUP"];
613 DataColumn[] dcKeys = new DataColumn[1];
614 dcKeys[0] = dcKey;
615 dtGroups.PrimaryKey = dcKeys;
616
617 //Get Access Group Types (Combines Access Types and Groups)
618 //Optimization Note: Can eliminate Access type and Access Group Table
619 // But they are heavily referenced throughout the code.
620 // Table #7
621 setProgressDelegate(9);
622 setStatusDelegate(statusConst + " Access Group Types");
623 LoadAccessGroupTypesTable();
624
625 //Build Primary Key for AccessGroupType table
626 DataTable dtAGTypes = m_dsGlobal.Tables["AccessGroupType"];
627 DataColumn dcGTKey = dtAGTypes.Columns["ACCESS_GROUP_TYPEID"];
628 DataColumn[] dcGTKeys = new DataColumn[1];
629 dcGTKeys[0] = dcGTKey;
630 dtAGTypes.PrimaryKey = dcGTKeys;
631
632 //Build Data Relationship between AccessGroupType and AccessTypes tables
633 DataRelation dr = new DataRelation("AccessGroupType", //Relation Name
634 m_dsGlobal.Tables["AccessGroup"].Columns["BMXIEN"], //Parent
635 m_dsGlobal.Tables["AccessGroupType"].Columns["ACCESS_GROUP_ID"]); //Child
636 m_dsGlobal.Relations.Add(dr);
637
638 //ResourceGroup Table (Resource Groups by User)
639 // Table #8
640 // What shows up on the tree. The groups the user has access to.
641 setProgressDelegate(10);
642 setStatusDelegate(statusConst + " Resource Groups By User");
643 LoadResourceGroupTable();
644
645 //Resources by user
646 // Table #9
647 // Individual Resources
648 setProgressDelegate(11);
649 setStatusDelegate(statusConst + " Resources By User");
650 LoadBSDXResourcesTable();
651
652 //Build Primary Key for Resources table
653 DataColumn[] dc = new DataColumn[1];
654 dc[0] = m_dsGlobal.Tables["Resources"].Columns["RESOURCEID"];
655 m_dsGlobal.Tables["Resources"].PrimaryKey = dc;
656
657 //GroupResources table
658 // Table #10
659 // Resource Groups and Indivdual Resources together
660 setProgressDelegate(12);
661 setStatusDelegate(statusConst + " Group Resources");
662 LoadGroupResourcesTable();
663
664 //Build Primary Key for ResourceGroup table
665 dc = new DataColumn[1];
666 dc[0] = m_dsGlobal.Tables["ResourceGroup"].Columns["RESOURCE_GROUP"];
667 m_dsGlobal.Tables["ResourceGroup"].PrimaryKey = dc;
668
669 //Build Data Relationships between ResourceGroup and GroupResources tables
670 dr = new DataRelation("GroupResource", //Relation Name
671 m_dsGlobal.Tables["ResourceGroup"].Columns["RESOURCE_GROUP"], //Parent
672 m_dsGlobal.Tables["GroupResources"].Columns["RESOURCE_GROUP"]); //Child
673
674 m_dsGlobal.Relations.Add(dr);
675
676 //HospitalLocation table
677 //Table #11
678 setProgressDelegate(13);
679 setStatusDelegate(statusConst + " Clinics");
680 //cmd.CommandText = "SELECT BMXIEN 'HOSPITAL_LOCATION_ID', NAME 'HOSPITAL_LOCATION', DEFAULT_PROVIDER, STOP_CODE_NUMBER, INACTIVATE_DATE, REACTIVATE_DATE FROM HOSPITAL_LOCATION";
681 sCommandText = "BSDX HOSPITAL LOCATION";
682 ConnectInfo.RPMSDataTable(sCommandText, "HospitalLocation", m_dsGlobal);
683 Debug.Write("LoadGlobalRecordsets -- HospitalLocation loaded\n");
684
685 //Build Primary Key for HospitalLocation table
686 dc = new DataColumn[1];
687 DataTable dtTemp = m_dsGlobal.Tables["HospitalLocation"];
688 dc[0] = dtTemp.Columns["HOSPITAL_LOCATION_ID"];
689 m_dsGlobal.Tables["HospitalLocation"].PrimaryKey = dc;
690
691 //Build Data Relationships between Resources and HospitalLocation tables
692 dr = new DataRelation("HospitalLocationResource", //Relation Name
693 m_dsGlobal.Tables["HospitalLocation"].Columns["HOSPITAL_LOCATION_ID"], //Parent
694 m_dsGlobal.Tables["Resources"].Columns["HOSPITAL_LOCATION_ID"], false); //Child
695 m_dsGlobal.Relations.Add(dr);
696
697 //Build ScheduleUser table
698 //Table #12
699 setProgressDelegate(14);
700 setStatusDelegate(statusConst + " Schedule User");
701 this.LoadScheduleUserTable();
702
703 //Build Primary Key for ScheduleUser table
704 dc = new DataColumn[1];
705 dtTemp = m_dsGlobal.Tables["ScheduleUser"];
706 dc[0] = dtTemp.Columns["USERID"];
707 m_dsGlobal.Tables["ScheduleUser"].PrimaryKey = dc;
708
709 //Build ResourceUser table
710 //Table #13
711 //Acess to Resources by [this] User
712 setProgressDelegate(15);
713 setStatusDelegate(statusConst + " Resource User");
714 this.LoadResourceUserTable();
715
716 //Build Primary Key for ResourceUser table
717 dc = new DataColumn[1];
718 dtTemp = m_dsGlobal.Tables["ResourceUser"];
719 dc[0] = dtTemp.Columns["RESOURCEUSER_ID"];
720 m_dsGlobal.Tables["ResourceUser"].PrimaryKey = dc;
721
722 //Create relation between BSDX Resource and BSDX Resource User tables
723 dr = new DataRelation("ResourceUser", //Relation Name
724 m_dsGlobal.Tables["Resources"].Columns["RESOURCEID"], //Parent
725 m_dsGlobal.Tables["ResourceUser"].Columns["RESOURCEID"]); //Child
726 m_dsGlobal.Relations.Add(dr);
727
728 //Build active provider table
729 //Table #14
730 //TODO: Lazy load the provider table; no need to load in advance.
731 setProgressDelegate(16);
732 setStatusDelegate(statusConst + " Providers");
733 sCommandText = "SELECT BMXIEN, NAME FROM NEW_PERSON WHERE INACTIVE_DATE = '' AND BMXIEN > 1";
734 ConnectInfo.RPMSDataTable(sCommandText, "Provider", m_dsGlobal);
735 Debug.Write("LoadGlobalRecordsets -- Provider loaded\n");
736
737 //Build the HOLIDAY table
738 //Table #15
739 setProgressDelegate(17);
740 setStatusDelegate(statusConst + " Holiday");
741 sCommandText = "SELECT NAME, DATE FROM HOLIDAY WHERE INTERNAL[DATE] > '" + FMDateTime.Create(DateTime.Today).DateOnly.FMDateString + "'";
742 ConnectInfo.RPMSDataTable(sCommandText, "HOLIDAY", m_dsGlobal);
743 Debug.Write("LoadingGlobalRecordsets -- Holidays loaded\n");
744
745
746 //Save the xml schema
747 //m_dsGlobal.WriteXmlSchema(@"..\..\csSchema20060526.xsd");
748 //----------------------------------------------
749
750 setStatusDelegate("Setting Receive Timeout");
751 _current.m_ConnectInfo.ReceiveTimeout = 30000; //30-second timeout
752
753#if DEBUG
754 _current.m_ConnectInfo.ReceiveTimeout = 600000; //longer timeout for debugging
755#endif
756 // Event Subsriptions
757 setStatusDelegate("Subscribing to Server Events");
758 //Table #16
759 setProgressDelegate(18);
760 _current.m_ConnectInfo.SubscribeEvent("BSDX SCHEDULE");
761 //Table #17
762 setProgressDelegate(19);
763 _current.m_ConnectInfo.SubscribeEvent("BSDX CALL WORKSTATIONS");
764 //Table #18
765 setProgressDelegate(20);
766 _current.m_ConnectInfo.SubscribeEvent("BSDX ADMIN MESSAGE");
767 //Table #19
768 setProgressDelegate(21);
769 _current.m_ConnectInfo.SubscribeEvent("BSDX ADMIN SHUTDOWN");
770
771 _current.m_ConnectInfo.EventPollingInterval = 5000; //in milliseconds
772 _current.m_ConnectInfo.EventPollingEnabled = true;
773 _current.m_ConnectInfo.AutoFire = 12; //AutoFire every 12*5 seconds
774
775 //Close Splash Screen
776 closeSplashDelegate();
777
778 return true;
779
780 }
781
782
783
784 public void LoadAccessGroupsTable()
785 {
786 string sCommandText = "SELECT * FROM BSDX_ACCESS_GROUP";
787 ConnectInfo.RPMSDataTable(sCommandText, "AccessGroup", m_dsGlobal);
788 Debug.Write("LoadGlobalRecordsets -- AccessGroups loaded\n");
789 }
790
791 public void LoadAccessGroupTypesTable()
792 {
793 string sCommandText = "BSDX GET ACCESS GROUP TYPES";
794 ConnectInfo.RPMSDataTable(sCommandText, "AccessGroupType", m_dsGlobal);
795 Debug.Write("LoadGlobalRecordsets -- AccessGroupTypes loaded\n");
796 }
797
798 public void LoadBSDXResourcesTable()
799 {
800 string sCommandText = "BSDX RESOURCES^" + m_ConnectInfo.DUZ;
801 ConnectInfo.RPMSDataTable(sCommandText, "Resources", m_dsGlobal);
802 Debug.Write("LoadGlobalRecordsets -- Resources loaded\n");
803 }
804
805 public void LoadResourceGroupTable()
806 {
807 //ResourceGroup Table (Resource Groups by User)
808 //Table "ResourceGroup" contains all resource group names
809 //to which user has access
810 //Fields are: RESOURCE_GROUPID, RESOURCE_GROUP
811 string sCommandText = "BSDX RESOURCE GROUPS BY USER^" + m_ConnectInfo.DUZ;
812 ConnectInfo.RPMSDataTable(sCommandText, "ResourceGroup", m_dsGlobal);
813 Debug.Write("LoadGlobalRecordsets -- ResourceGroup loaded\n");
814 }
815
816 public void LoadGroupResourcesTable()
817 {
818 //Table "GroupResources" contains all active GROUP/RESOURCE combinations
819 //to which user has access based on entries in BSDX RESOURCE USER file
820 //If user has BSDXZMGR or XUPROGMODE keys, then ALL Group/Resource combinstions
821 //are returned.
822 //Fields are: RESOURCE_GROUPID, RESOURCE_GROUP, RESOURCE_GROUP_ITEMID, RESOURCE_NAME, RESOURCE_ID
823 string sCommandText = "BSDX GROUP RESOURCE^" + m_ConnectInfo.DUZ;
824 ConnectInfo.RPMSDataTable(sCommandText, "GroupResources", m_dsGlobal);
825 Debug.Write("LoadGlobalRecordsets -- GroupResources loaded\n");
826 }
827
828 public void LoadScheduleUserTable()
829 {
830 //Table "ScheduleUser" contains an entry for each user in File 200 (NEW PERSON)
831 //who possesses the BSDXZMENU security key.
832 string sCommandText = "BSDX SCHEDULE USER";
833 ConnectInfo.RPMSDataTable(sCommandText, "ScheduleUser", m_dsGlobal);
834 Debug.Write("LoadGlobalRecordsets -- ScheduleUser loaded\n");
835 }
836
837 public void LoadResourceUserTable()
838 {
839 //Table "ResourceUser" duplicates the BSDX RESOURCE USER File.
840 //NOTE: Column names are RESOURCEUSER_ID, RESOURCEID,
841 // OVERBOOK, MODIFY_SCHEDULE, USERID, USERID1
842 //string sCommandText = "SELECT BMXIEN RESOURCEUSER_ID, INTERNAL[RESOURCENAME] RESOURCEID, OVERBOOK, MODIFY_SCHEDULE, USERNAME USERID, INTERNAL[USERNAME] FROM BSDX_RESOURCE_USER";
843 LoadResourceUserTable(false);
844 }
845
846 public void LoadResourceUserTable(bool bAllUsers)
847 {
848 string sCommandText = @"SELECT BMXIEN RESOURCEUSER_ID, RESOURCENAME, INTERNAL[RESOURCENAME] RESOURCEID, OVERBOOK, MODIFY_SCHEDULE, MODIFY_APPOINTMENTS, USERNAME, INTERNAL[USERNAME] USERID FROM BSDX_RESOURCE_USER"; // WHERE INTERNAL[INSTITUTION]=" + m_ConnectInfo.DUZ2;
849
850 if (!bAllUsers)
851 {
852 sCommandText += String.Format(" WHERE INTERNAL[USERNAME] = {0}", m_ConnectInfo.DUZ);
853 }
854
855 ConnectInfo.RPMSDataTable(sCommandText, "ResourceUser", m_dsGlobal);
856 Debug.Write("LoadGlobalRecordsets -- ResourceUser loaded\n");
857 }
858
859
860 public void RegisterDocumentView(CGDocument doc, CGView view)
861 {
862 //Store the view in the list of views
863 this.Views.Add(view, doc);
864
865 //Hook into the view's 'closed' event
866 view.Closed += new EventHandler(ViewClosed);
867
868 //Hook into the view's mnuRPMSServer.Click event
869 view.mnuRPMSServer.Click += new EventHandler(mnuRPMSServer_Click);
870
871 //Hook into the view's mnuRPMSLogin.Click event
872 view.mnuRPMSLogin.Click += new EventHandler(mnuRPMSLogin_Click);
873
874 }
875
876 public void RegisterAVDocumentView(CGAVDocument doc, CGAVView view)
877 {
878 //Store the view in the list of views
879 this.AvailabilityViews.Add(view, doc);
880
881 //Hook into the view's 'closed' event
882 view.Closed += new EventHandler(AVViewClosed);
883 }
884
885 public CGAVView GetAVViewByResource(ArrayList sResourceArray)
886 {
887 if (sResourceArray == null)
888 return null;
889
890 bool bEqual = true;
891 foreach (CGAVView v in m_AVViews.Keys)
892 {
893 CGAVDocument d = v.Document;
894
895 bEqual = false;
896 if (d.Resources.Count == sResourceArray.Count)
897 {
898 bEqual = true;
899 for (int j = 0; j < sResourceArray.Count; j++)
900 {
901 if (sResourceArray.Contains(d.Resources[j]) == false)
902 {
903 bEqual = false;
904 break;
905 }
906 if (d.Resources.Contains(sResourceArray[j]) == false)
907 {
908 bEqual = false;
909 break;
910 }
911 }
912 if (bEqual == true)
913 return v;
914 }
915 }
916 return null;
917 }
918 /// <summary>
919 /// Return the first view having a resource array matching sResourceArray
920 /// </summary>
921 /// <param name="sResourceArray"></param>
922 /// <returns></returns>
923 public CGView GetViewByResource(ArrayList sResourceArray)
924 {
925 if (sResourceArray == null)
926 return null;
927
928 bool bEqual = true;
929 foreach (CGView v in _views.Keys)
930 {
931 CGDocument d = v.Document;
932
933 bEqual = false;
934 if (d.Resources.Count == sResourceArray.Count)
935 {
936 bEqual = true;
937 for (int j = 0; j < sResourceArray.Count; j++)
938 {
939 if (sResourceArray.Contains(d.Resources[j]) == false)
940 {
941 bEqual = false;
942 break;
943 }
944 if (d.Resources.Contains(sResourceArray[j]) == false)
945 {
946 bEqual = false;
947 break;
948 }
949 }
950 if (bEqual == true)
951 return v;
952 }
953 }
954 return null;
955 }
956
957 /// <summary>
958 /// Removes view and Handles Disconnection from Database if no views are left.
959 /// </summary>
960 /// <param name="sender"></param>
961 /// <param name="e"></param>
962 private void ViewClosed(object sender, EventArgs e)
963 {
964 //Remove the sender from our document list
965 Views.Remove(sender);
966
967 //If no documents left, then close RPMS connection & exit the application
968 if ((Views.Count == 0)&&(this.AvailabilityViews.Count == 0)&&(m_bExitOK == true))
969 {
970 m_ConnectInfo.EventPollingEnabled = false;
971 m_ConnectInfo.UnSubscribeEvent("BSDX SCHEDULE");
972 m_ConnectInfo.CloseConnection();
973 Application.Exit();
974 }
975 }
976
977 private void AVViewClosed(object sender, EventArgs e)
978 {
979 //Remove the sender from our document list
980 this.AvailabilityViews.Remove(sender);
981
982 //If no documents left, then close RPMS connection & exit the application
983 if ((Views.Count == 0)&&(this.AvailabilityViews.Count == 0)&&(m_bExitOK == true))
984 {
985 m_ConnectInfo.bmxNetLib.CloseConnection();
986 Application.Exit();
987 }
988 }
989
990 /// <summary>
991 /// Not used
992 /// </summary>
993 private void KeepAlive()
994 {
995 foreach (CGView v in _views.Keys)
996 {
997 CGDocument d = v.Document;
998 DateTime dNow = DateTime.Now;
999 DateTime dLast = d.LastRefreshed;
1000 TimeSpan tsDiff = dNow - dLast;
1001 if (tsDiff.Seconds > 180)
1002 {
1003 for (int j = 0; j < d.Resources.Count; j++)
1004 {
1005 v.RaiseRPMSEvent("SCHEDULE-" + d.Resources[j].ToString(), "");
1006 }
1007
1008 break;
1009 }
1010 }
1011 }
1012
1013 /// <summary>
1014 /// Propogate availability updates to all sRresource's doc/views
1015 /// </summary>
1016 public void UpdateViews(string sResource, string sOldResource)
1017 {
1018 if (sResource == null)
1019 return;
1020 foreach (CGView v in _views.Keys)
1021 {
1022 CGDocument d = v.Document;
1023 for (int j = 0; j < d.Resources.Count; j++)
1024 {
1025 if ((sResource == "") || (sResource == ((string) d.Resources[j])) || (sOldResource == ((string) d.Resources[j])))
1026 {
1027 d.RefreshDocument();
1028 break;
1029 }
1030 }
1031 v.UpdateTree();
1032 }
1033 }
1034
1035 /// <summary>
1036 /// Propogate availability updates to all doc/views
1037 /// </summary>
1038 public void UpdateViews()
1039 {
1040 UpdateViews("","");
1041 foreach (CGView v in _views.Keys)
1042 {
1043 v.UpdateTree();
1044 }
1045 }
1046
1047 /// <summary>
1048 /// Calls each view associated with document Doc and closes it.
1049 /// </summary>
1050 public void CloseAllViews(CGDocument doc)
1051 {
1052 //iterate through all views and call update.
1053 Hashtable h = CGDocumentManager.Current.Views;
1054
1055 CGDocument d;
1056 int nTempCount = h.Count;
1057 do
1058 {
1059 nTempCount = h.Count;
1060 foreach (CGView v in h.Keys)
1061 {
1062 d = (CGDocument) h[v];
1063 if (d == doc)
1064 {
1065 v.Close();
1066 break;
1067 }
1068 }
1069 } while ((h.Count > 0) && (nTempCount != h.Count));
1070 }
1071
1072 /// <summary>
1073 /// Calls each view associated with Availability Doc and closes it.
1074 /// </summary>
1075 public void CloseAllViews(CGAVDocument doc)
1076 {
1077 //iterate through all views and call update.
1078 Hashtable h = CGDocumentManager.Current.AvailabilityViews;
1079
1080 CGAVDocument d;
1081 int nTempCount = h.Count;
1082 do
1083 {
1084 nTempCount = h.Count;
1085 foreach (CGAVView v in h.Keys)
1086 {
1087 d = (CGAVDocument) h[v];
1088 if (d == doc)
1089 {
1090 v.Close();
1091 break;
1092 }
1093 }
1094 } while ((h.Count > 0) && (nTempCount != h.Count));
1095
1096
1097 }
1098
1099 /// <summary>
1100 /// Accomplishes Changing the Server to which you connect
1101 /// </summary>
1102 /// <remarks>
1103 /// Parameter relog-in for InitializeApp forces initialize app to use
1104 /// 1. The server the user just picked and then BMX saved off to User Preferences
1105 /// 2. A new access and verify code pair
1106 /// </remarks>
1107 /// <param name="sender">unused</param>
1108 /// <param name="e">unused</param>
1109 private void mnuRPMSServer_Click(object sender, EventArgs e)
1110 {
1111 //Warn that changing servers will close all schedules
1112 if (MessageBox.Show("Are you sure you want to close all schedules and connect to a different VistA server?", "Clinical Scheduling", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
1113 return;
1114
1115 //Reconnect to RPMS and recreate all global recordsets
1116 try
1117 {
1118 // Close All, but tell the Close All method not to call Applicaiton.Exit since we still plan to continue.
1119 // Close All does not call Application.Exit, but CGView_Close handler does
1120 m_bExitOK = false;
1121 CloseAll();
1122 m_bExitOK = true;
1123
1124 //Used in Do loop
1125 bool bRetry = true;
1126
1127 // Do Loop to deal with changing the server and the vagaries of user choices.
1128 do
1129 {
1130 try
1131 {
1132 //ChangeServerInfo does not re-login the user
1133 //It only changes the saved server information in the %APPDATA% folder
1134 //so it can be re-used when BMX tries to log in again.
1135 //Access and Verify code are prompted for in InitializeApp
1136 m_ConnectInfo.ChangeServerInfo();
1137 bRetry = false;
1138 }
1139 catch (Exception ex)
1140 {
1141 if (ex.Message == "User cancelled.")
1142 {
1143 bRetry = false;
1144 Application.Exit();
1145 return;
1146 }
1147 if (MessageBox.Show("Unable to connect to VistA. " + ex.Message , "Clinical Scheduling", MessageBoxButtons.RetryCancel) == DialogResult.Retry)
1148 {
1149 bRetry = true;
1150 }
1151 else
1152 {
1153 bRetry = false;
1154 Application.Exit();
1155 return;
1156 }
1157 }
1158 } while (bRetry == true);
1159
1160 //Parameter for initialize app tells it that this is a re-login and forces a new access and verify code.
1161 bool isEverythingOkay = this.InitializeApp(true);
1162
1163 //if an error occurred, break out. This time we need to call Application.Exit since it's already running.
1164 if (!isEverythingOkay)
1165 {
1166 Application.Exit();
1167 return;
1168 }
1169
1170 //Otherwise, everything is okay. So open document and view, then show and activate view.
1171 CGDocument doc = new CGDocument();
1172 doc.DocManager = _current;
1173
1174 CGView view = new CGView();
1175 view.InitializeDocView(doc, _current, doc.StartDate, _current.WindowText);
1176
1177 view.Show();
1178 view.Activate();
1179
1180 //Application.Run need not be called b/c it is already running.
1181 }
1182 catch (Exception ex)
1183 {
1184 throw ex;
1185 }
1186
1187 }
1188
1189 /// <summary>
1190 /// Accomplishes Re-login into RPMS/VISTA. Now all logic is in this event handler.
1191 /// </summary>
1192 /// <param name="sender">not used</param>
1193 /// <param name="e">not used</param>
1194 private void mnuRPMSLogin_Click(object sender, EventArgs e)
1195 {
1196 //Warn that changing login will close all schedules
1197 if (MessageBox.Show("Are you sure you want to close all schedules and login to VistA?", "Clinical Scheduling", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
1198 return;
1199
1200 //Reconnect to RPMS and recreate all global recordsets
1201 try
1202 {
1203 // Close All, but tell the Close All method not to call Applicaiton.Exit since we still plan to continue.
1204 // Close All does not call Application.Exit, but CGView_Close handler does
1205 m_bExitOK = false;
1206 CloseAll();
1207 m_bExitOK = true;
1208
1209 //Parameter for initialize app tells it that this is a re-login and forces a new access and verify code.
1210 bool isEverythingOkay = this.InitializeApp(true);
1211
1212 //if an error occurred, break out. This time we need to call Application.Exit since it's already running.
1213 if (!isEverythingOkay)
1214 {
1215 Application.Exit();
1216 return;
1217 }
1218
1219 //Otherwise, everything is okay. So open document and view, then show and activate view.
1220 CGDocument doc = new CGDocument();
1221 doc.DocManager = _current;
1222
1223 CGView view = new CGView();
1224 view.InitializeDocView(doc, _current, doc.StartDate, _current.WindowText);
1225
1226 view.Show();
1227 view.Activate();
1228
1229 //Application.Run need not be called b/c it is already running.
1230 }
1231 catch (Exception ex)
1232 {
1233 throw ex;
1234 }
1235
1236 }
1237
1238 delegate void CloseAllDelegate(string sMsg);
1239
1240 private void CloseAll(string sMsg)
1241 {
1242 if (sMsg == "")
1243 {
1244 sMsg = "Scheduling System Shutting Down Immediately for Maintenance.";
1245 }
1246
1247 MessageBox.Show(sMsg, "Clinical Scheduling Administrator -- System Shutdown Notification", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
1248
1249 CloseAll();
1250 }
1251
1252 private void CloseAll()
1253 {
1254 //Close all documents, views and connections
1255 Hashtable h = CGDocumentManager.Current.Views;
1256 int nTempCount = h.Count;
1257 do
1258 {
1259 nTempCount = h.Count;
1260 foreach (CGView v in h.Keys)
1261 {
1262 v.Close();
1263 break;
1264 }
1265 } while ((h.Count > 0) && (nTempCount != h.Count));
1266
1267 h = CGDocumentManager.Current.AvailabilityViews;
1268 nTempCount = h.Count;
1269 do
1270 {
1271 nTempCount = h.Count;
1272 foreach (CGAVView v in h.Keys)
1273 {
1274 v.Close();
1275 break;
1276 }
1277 } while ((h.Count > 0) && (nTempCount != h.Count));
1278
1279 }
1280
1281 public delegate DataTable RPMSDataTableDelegate(string CommandString, string TableName);
1282
1283 public DataTable RPMSDataTable(string sSQL, string sTableName)
1284 {
1285 //Retrieves a recordset from RPMS
1286 string sErrorMessage = "";
1287 DataTable dtOut;
1288
1289 try
1290 {
1291 //System.IntPtr pHandle = this.Handle;
1292 RPMSDataTableDelegate rdtd = new RPMSDataTableDelegate(ConnectInfo.RPMSDataTable);
1293 //dtOut = (DataTable) this.Invoke(rdtd, new object[] {sSQL, sTableName});
1294 dtOut = rdtd.Invoke(sSQL, sTableName);
1295 }
1296
1297 catch (Exception ex)
1298 {
1299 sErrorMessage = "CGDocumentManager.RPMSDataTable error: " + ex.Message;
1300 throw ex;
1301 }
1302
1303 return dtOut;
1304
1305 }
1306
1307 public void ChangeDivision(System.Windows.Forms.Form frmCaller)
1308 {
1309 this.ConnectInfo.ChangeDivision(frmCaller);
1310 foreach (CGView v in _views.Keys)
1311 {
1312 v.InitializeDocView(v.Document.DocName);
1313 v.Document.RefreshDocument();
1314 }
1315 }
1316
1317 public void ViewRefresh()
1318 {
1319 foreach (CGView v in _views.Keys)
1320 {
1321 try
1322 {
1323 v.Document.RefreshDocument();
1324 }
1325 catch (Exception ex)
1326 {
1327 Debug.Write("CGDocumentManager.ViewRefresh Exception: " + ex.Message + "\n");
1328 }
1329 finally
1330 {
1331 }
1332 }
1333 Debug.Write("DocManager refreshed all views.\n");
1334 }
1335
1336 #endregion Methods & Events
1337
1338 }
1339}
Note: See TracBrowser for help on using the repository browser.