# vApp

The base class for building applications.

## Synopsis

Header:
  `<v/vapp.h>`
Class name:
  vApp
Contains:
  vCmdWindow, vAppWinInfo

## Description

The `vApp` class serves as the base class for building applications. There must be exactly one instance of an object derived from the `vApp` class. The base class contains and hides the code for interacting with the host windowing system, and serves to simplify using the windowing system.

You will usually derive a class based on `vApp` that will serve as the main control center of the application, as well as containing the window objects needed for the user interface. The single instance of the application class is defined in the body of the derived application class code.

The `vApp` class has several utility methods of general usefulness, as well as several methods that are normally overridden to provide the control interface from the application to the command windows. The derived class will also usually have other methods used to interface with the application.

In order to simplify the control interface between the application and the windows, the `vAppWinInfo` class has been provided. The application can extend that class to keep track of relevant information for each window. When the `NewAppWin` method is used to create a window, it will create an appropriate instance of a `vAppWinInfo` object, and return a pointer to the new object. The base `vApp` then provides the method `getAppWinInfo` to retrieve the information associated with a given window.

## Constructor

#### vApp(char* appName)

#### vApp(char* appName, simSDI = 0, int fh = 0, int fw = 0)

appName Default name for the application. This name will be used by default when names are not provided for windows. The name also appears on the ``main window'' for some platforms, including Microsoft Windows, but not X. The constructor also initializes some internal state information. There must be exactly one instance of the `vApp` object, and will usually represent your derived `myApp` object. See the code below with `AppMain` for an example of creating the single app instance.

simSDI This optional parameter is used to specify that Vshould start as a Windows SDI application if it is set to 1. This parameter has no effect for the X version.

fw, fh These are used to specify the size of a menuless and canvasless Vapplication, and are optional.

## Methods to Override

#### void AppCommand(vWindow* win, ItemVal id, ItemVal retval, CmdType ctype)

Any window commands not processed by the `vWindow` object are passed to `AppCommand`. You can override this method to handle any commands not processed in windows.

#### int AppMain(int argc, char** argv)

This is a global function (not a class member!) that is called once by the system at start up time with the standard command line arguments `argc` and `argv`. You provide this function in your code.

Your program will not have a C `main` function. The main reason for this is portability. While you would usually have a `main` in a Unix based program, MS-Windows does not use `main`, but rather `PASCAL WinMain`. By handling how the program gets started and providing the `AppMain` mechanism, V allows you to ignore the differences. You will still have all the capability to access the command line arguments and do whatever else you would do in `main` without having to know about getting the host windowing system up and running.

The windowing system will have been initialized before `AppMain` is called. You can process the command line arguments, and perform other required initializations. The top level command window should also created in `AppMain` by calling `NewAppWin`.

Before `AppMain` is called, the single instance of your derived `vApp` object must also be constructed, usually by instantiating a static instance with a statement such as `static myApp* MyApp = new myApp("ProtoApp")`. As part of the construction of the `myApp` object, the global pointer `vApp* theApp` is also pointed to the single instance of the `vApp` or derived `myApp` object. You can then use `theApp` anywhere in your code to access methods provided by the `vApp` class.

Your `AppMain` should return a 0 if it was successful. A nonzero return value will cause the V system to terminate with an exit code corresponding to the value you returned.

### Example

    // EVERY V application needs the equivalent of the following line

      static myApp myApp("My V App");  // Construct the app.

    //==========================>>> AppMain <<<===========================
      int AppMain(int argc, char** argv)
      {
        // Use AppMain to perform special app initialization, and
        // to create the main window.  This example assumes that
        // NewAppWin knows how to create the proper window.

        (void) theApp->NewAppWin(0, "My V App", 350, 100, 0);
        return 0;
      }

#### int CloseAppWin(vWindow* win)

This is the normal way to close a window. Your derived `CloseAppWin` should first handle all housekeeping details, such as saving the contents of a file, and then call the default `vApp::CloseAppWin` method. Your code can abort the close process by not calling the default `vApp::CloseAppwin` class, and instead returning a 0. When you call the default method, the window's `CloseWin` method is called and the window removed.

The `CloseAppWin` method is also called when the user clicks the close button of the window. This close button will correspond to the standard close window button depending on the native windowing system. On X Windows, this button will depend on what window manager you are using. On Windows, this corresponds to a double click on the upper left box of the title bar, or the ``X'' box in Windows 95. To abort this "close all" procedure, return 0 from your class.

### Example

    //======================>>> videApp::CloseAppWin <<<===========================
      int videApp::CloseAppWin(vWindow* win)
      {
        // This will be called BEFORE a window has been really closed.

        videCmdWindow* cw = (videCmdWindow*)win; // get our cmd window
        if (cw->CheckClose())                    // check if OK to close
            return vApp::CloseAppWin(win);       // if OK, then call vApp method
        else
            return 0;                            // otherwise, abort close process
      }

#### int CloseLastCmdWindow(vWindow* win, int exitcode)

This method is provided mainly for MS-Windows MDI compatibility. The default behavior of V is to close the app when the last MDI child window is closed. This corresponds to what would happen on the X version. However, this is not standard behavior for Windows MDI apps.

If your app needs standard Windows behavior, then you should override `CloseLastCmdWindow`, and simply return. This will result in an empty MDI frame with a single active File menu with the commands New, Open, and Exit. You should also then override `vApp::AppCommand` to handle the New and Open cases. It will be harmless to duplicate this code for X apps.

The following code sample, taken from the V Text Editor code, shows how to get standard MDI behavior in a way that is compatible with both Windows and X.

    //======================>>> vedApp::AppCommand <<<===========================
      void vedApp::AppCommand(vWindow* win, ItemVal id, ItemVal val, CmdType cType)
      {
        // Commands not processed by the window will be passed here
        // switch is used to handle empty MDI frame commands New and Open
        // for Windows apps only. Harmless on X.

        UserDebug1(Build,"vedApp::AppCmd(ID: %d)\n",id);
        switch (id)
          {
            case M_New:
              {
                (void*) theApp->NewAppWin(0, "V Text Editor", 100, 50);
                return;
              }

            case M_Open:
              {
                vedCmdWindow* cw;
                cw = (vedCmdWindow*) theApp->NewAppWin(0, "V Text Editor", 100, 50);
                cw->WindowCommand((ItemVal)M_Open,(ItemVal)0,(CmdType)0);
                return;
              }
          }

        vApp::AppCommand(win, id, val, cType);
      }

    //===================>>> vedApp::CloseLastCmdWindow <<<======================
      void vedApp::CloseLastCmdWindow(vWindow* win, int exitcode)
      {
    #ifndef V_VersionWindows
        vApp::CloseLastCmdWindow(win,exitcode);   // call default for X
    #endif
      }

#### void Exit(void)

This is the normal way to exit from a standard V application. The overridden method can perform any special processing (e.g., asking ``Are you sure?'') required. The default `Exit` will call `CloseAppWin` for each window created with `NewAppWin`, and then exit from the windowing system.

#### void KeyIn(vWindow* win, vKey key, unsigned int shift)

Any input key events not handled by the `vWindow` object are passed to `vApp::KeyIn`. See `KeyIn` in the `vWindow` section for details of using keys.

#### vWindow* NewAppWin(vWindow* win, char* name, int w, int h, vAppWinInfo* winInfo)

The purpose of the `NewAppWin` method is to create a new instance of a window. Most likely, you will override `NewAppWin` with your own version, but you still must call the base `vApp::NewAppWin` method after your derived method has completed its initializations.

The default behavior of the base `NewAppWin` class is to set the window title to `name`, and the width `w` and height `h`. Note that the height and width are of the canvas, and not necessarily the whole app window. If you don't add a canvas to the command window, the results are not specified. Usually, your derived `NewAppWin` will create an instance of your derived `vCmdWindow` class, and you will pass its pointer in the `win` parameter. If the the `win` parameter is null, then a standard `vCmdWindow` will be created automatically, although that window won't be particularly useful to anyone.

Your `NewAppWin` class may also create an instance of your derived `vAppWinInfo` class. You would pass its pointer to the `winInfo` parameter. If you pass a null, then the base `NewAppWin` method also creates an instance of the standard `vAppWinInfo` class.

The real work done by the base `NewAppWin` is to register the instance of the window with the internal V run time system. This is why you must call the base `NewAppWin` method.

`NewAppWin` returns a pointer to the object just created. Your derived code can return the value returned by the base `vApp::NewAppWin`, or the pointer it created itself.

### Example

The following shows a minimal example of deriving a `NewAppWin` method.

    vWindow* myApp::NewAppWin(vWindow* win, char* name, int w, int h,
      vAppWinInfo* winInfo)
      {
        // Create and register a window. Usually this derived method
        // knows about the windows that need to be created, but
        // it is also possible to create the window instance outside.

        vWindow* thisWin = win;
        vAppWinInfo* theWinInfo = winInfo;

        if (!thisWin)   // Normal case: we will create the new window
            thisWin = new myCmdWindow(myname, w, h);  // create window

        // Now the application would do whatever it needed to create
        // a new view -- opening a file, tracking information, etc.
        // This information can be kept in the vAppWinInfo object.

        if (!theWinInfo)               // Create if not supplied
            vAppWinInfo* theWinInfo = new myAppWinInfo(name);

        // Now carry out the default actions
        return vApp::NewAppWin(thisWin, name, w, h, theWinInfo);
      }

## Utility Methods

#### char* ClipboardCheckText()

Returns 1 if there is text available on the clipboard.

#### void ClipboardClear()

Clears the contents of the clipboard. Deactivates `M_Paste`.

#### char* ClipboardGetText()

If there is text on the clipboard, this method will return a pointer to that text.

#### int ClipboardSetText(char* text)

This will set the system clipboard to the value of `text`. It will also send a `vApp::SetValueAll` message to each of your windows to set any command object `M_Paste` to sensitive. (Whenever the clipboard is emptied, a message to set `M_Paste` insensitive is also sent.)

Note that it is up to you to implement clipboard interaction. The `vTextCanvasPane` does not provide automatic clipboard support. Thus, your app needs to respond to cut, copy, and paste commands. The clipboard code will send a message to your Command Window to control the sensitivity of the `M_Paste` command.

#### int DefaultHeight()

Returns a default window canvas height value in pixels corresponding to 24 lines of text in the default font.

#### int DefaultWidth()

Returns a default window canvas width value in pixels corresponding to 80 columns of text in the default font.

#### vFont GetDefaultFont(void)

This method returns a `vFont` object representing the default system font. It is a convenience method, and probably not overly useful to application programs.

#### vFont GetVVersion(int& major, int& minor)

Returns the current major and minor version of V.

#### int IsRunning()

This method returns true if the windowing system is active and running. A false return means the program was started from a non-windowing environment.

#### int ScreenHeight()

Returns the overall height of the physical display screen in pixels. Note that this value may or may not be overly useful. On X, the `vCommandWindows` are drawn on the full display. On the Windows MDI version, the command windows all fall inside the MDI frame, and thus knowing the size of the whole screen is less useful.

#### int ScreenWidth()

Returns the overall width of the physical display screen in pixels. See `ScreenHeight`.

#### void SendWindowCommandAll(ItemVal id, int val, CmdType ctype)

This method can be used to send a message to the `WindowCommand` method of ALL currently active windows. This method is most useful for sending messages to windows from modeless dialogs. While messages to the `WindowCommand` method usually originate with the system in response to menu picks or command object selection, it can be useful to send the messages directly under program control. The `vDraw` sample program contains a good example of using `SendWindowCommandAll` (and `SetValueAll`) in `vdrwdlg.cpp`. There is no way to send a message to a specific window. The message is sent to all active windows.

#### void SetAppTitle(char* title)

This method is used to set the title of the main application window. This currently only applies to the Microsoft Windows MDI version of V. It is a no-op for the X version. It is still important that you choose a good title for your main window, and set it either with this method, or by providing a good name to the `vApp` initializer.

#### void SetValueAll(ItemVal itemId, int Val, ItemSetType what)

This method is similar to `vWindow::SetValue`, except that the control with the given `itemId` in ALL currently active windows is set. This is useful to keep control values in different windows in sync. The only difference between `vApp::SetValueAll` and `vWindow::SetValueAll` is that the `vApp` version can be easily called from dialogs as well as windows.

#### void SetStringAll(ItemVal itemId, char* title)

This method is similar to `vWindow::SetString`, except that the string with the given `itemId` in ALL currently active windows is set. This is useful to keep control strings in different windows in sync. The only difference between the `vApp::SetStringAll` version and the `vWindow::SetStringAll` version is that the `vApp` version can be easily called from dialogs as well as windows.

#### void showAppWin(bool show)

This method is intended to support dialog-only V apps. The strategy is to not define an AppWindow (don't call `NewAppWin` from `AppMain`), but rather define a dialog instead. Then, call `showAppWin(false)` before showing the dialog, and the main application window will be hidden.

Note that this is really a no-op on X, and hides the MDI frame on Windows. In practice, this means you will get a tiny flash as the MDI frame is shown briefly, and is then hidden. While this is slightly annoying, by setting the size to 1,1, the flash is minimized. This method seemed the most backward compatible way of supporting this feature.

Here is a short example of the code needed to define a dialog-only V app:

    //=======================================================================
    //
    //  Example of a dialog-only V app.
    //
    //=======================================================================

    #include "myapp.h"               // Header file defines appropriate things
    #include <v/vnotice.h>

      static myApp my_App("My V App",1,1,1);     // The instance of the app
                                     // Notice defined as SDI with size of 1,1
      int AppMain(int argc, char** argv)
      {
        // Don't call NewAppWin! Just create the dialog. This sample is
        // a simple vNotice box, but could be anything.

        vNoticeDialog note(theApp);   // dialog instance

        my_App.showAppWin(false);     // This hides App window

        note.Notice("This is a dialog only app.");  // And this is your dialog.
        theApp->Exit();               // exit app when dialog returns
        return 0;
      }

#### vAppWinInfo *getAppWinInfo(vWindow* win)

This method provides an easy way to retrieve the `vAppWinInfo` (or more typically, a derived class) object that is associated with a window. By convention, when a window is first created, it and its associated `vAppWinInfo` object are tracked by `NewAppWin`. When a user action in a window causes a method in `vApp` to be invoked, the `this` of that window is usually sent to the `vApp` method. You then use that `vWindow` pointer to call `getAppWinInfo` to get a pointer to the associated `vAppWinInfo` object. It will be up to you to determine what information that object has, and how to use it.

## MVC

With release 1.21, V adds support for writing MVC (Model View Controller) applications. The MVC paradigm is widely used for object-oriented applications. The basic idea of MVC is that your application consists of some kind of Model for the application. You show various Views of the Model under management of a controller.

How does this translate to V terms? Generally, it is up to you to build your model. Essentially, it will be your data structures and whatever else is needed to implement the core of your app. The controller is usually very closely related to a view of the model. The view and controller will usually be implemented in a `vCmdWindow` class. You can have different behavior for different views. The power of MVC comes from the ability of a given controller to send a message to all Views of the Model to update themselves as appropriate.

Consider a simple editing program that allows you to edit a data file either in text mode or in hex mode. Your app could have two Views of the Model (your internal representation of the file), one a text view, the other a hex view. Each of these views would be controlled and displayed by individual `vCmdWindow` classes. If the user makes a change in the text view, then the text view controller would send a message to the hex view to update itself.

V provides two methods to implement MVC, `vApp::UpdateAllViews`, and `vWindow::UpdateView`. Your controller sends a message to all other views using `UpdateAllViews`, and each view receives the message in `UpdateView`.

#### void UpdateAllViews(vWindow* sender, int hint, void* pHint)

This method is called by the user whenever a change is made to the model, e.g., the document. This causes `vWindow::UpdateView` to be called for every open window. The parameters are used to both filter and hint the windows on which actions to take in `vWindow::UpdateView`.

Generally, you call `UpdateAllViews` with `sender` set to `this`. `UpdateAllViews` will not call `UpdateView` for the `sender` window because typically the change of the model was a result of an interaction with this window. If you want the `sender` to be called, call with `sender` zero.

The hints are passed to `UpdateView` to help define what action the view needs to take. Generally, `hint` would have a value set to an `enum` defined in your derived `vApp` class. These values would hint about which kind of change is made so that only appropriate actions is taken by the appropriate views. The `pHint` is typically a pointer to the object representing the model.

## Tasking

Some applications may have extensive computation requirements. In traditional programming environments, this is usually no problem. However, for GUI based applications, the code cannot simply perform extensive computation in response to some command event (such as a "Begin Computation" menu command). GUIs make a basic assumption that the application will process events relatively quickly. While computation is in process, the application will not receive additional events, and may appear to hang if the computation is too long.

V provides two different approaches to handling compute bound applications. The most straight forward approach is to have the computation periodically call the V method `vApp::CheckEvents`. `CheckEvents` will process events, and pass the messages to the appropriate V method. This method may be the most appropriate for applications such as simulations. The second technique is to have the V system call a work procedure periodically to allow some computation to be performed. This technique may be most appropriate for applications that have short computations that should be performed even if the user is not entering commands or interacting with the application. The technique is supported by the `WorkSlice` method.

#### CheckEvents()

Most V applications will not need this utility. However, it is possible for some compute bound applications to lock out system response to the events needed to update the screen. If you notice that your application stops responding to input, or fails to consistently update items in your window, then place calls to `vApp::CheckEvents()` in your code somewhere. You may have to experiment how often you need to call it. It does have some overhead, so you don't want it to slow down your app. But it does need to get called enough so the system can keep up with the screen updates. This function needs no parameters, and returns no value.

#### EnableWorkSlice(long slice)

For applications that need computations to be performed continuously or periodically, even while the user is not interacting with the program, V provides `EnableWorkSlice` and `WorkSlice`. After `EnableWorkSlice` has been called, V will call the app's `WorkSlice` method every `slice` milliseconds. The `WorkSlice` method of every open `vCommandWindow` will also be called. Calling `EnableWorkSlice` with a zero value will stop the calls to the `WorkSlice` methods.

V uses a standard V `vTimer` object to implement this behavior. Thus, all of the information about actual time intervals and limits on the number of timers discussed in the `vTimer` description apply to `EnableWorkSlice` and `WorkSlice`.

#### WorkSlice()

When a `EnableWorkSlice` has been called with a positive value, V calls `vApp::WorkSlice` at approximately the specified interval (or more likely, the overridden method in your app), as well as the `vWindow::WorkSlice` method of each open `vCommandWindow`. Your application can override the appropriate `WorkSlice` method to perform short, periodic computations. Theses computations should be shorter than the time interval specified for `EnableWorkSlice`. This may be difficult to ensure since different processors will work at different speeds. One simple way to be sure you don't get multiple calls to the `WorkSlice` method is to set a static variable on entry to the code. Note that `vCommandWindow` also has a `WorkSlice` method. The `WorkSlice` for the `vApp` is called first, followed by a call to each open `vCommandWindow` sequentially in no specific order.

## See Also

vWindow, vAppWinInfo