/*
    listPM list files under Presentation Manager. Uses Open Class Libarary.
    Copyright (C) 1998, 1999  Paul Elliott

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    Paul Elliott
    PMB # 181
    11900 Metric Blvd Ste. J
    Austin Tx 78758-3117
    pelliott@io.com
*/
#ifndef WINTHR
#define WINTHR

#include <iwindow.hpp>
#include <icmdhdr.hpp>
#include <ithread.hpp>

/*
 *  This class is used to run code on another thread
 * from a windows procedure.
 * To use:
 * 1) derive from this class defining
 *    a) thread() code to run on other threads. Required as this is
 *        an abstract base class
 *    b) begin() optional code to run on this thread before thread is started.
 *    c) finish() optional code to run on this thread after thread runs1
 *    if desired private data can be added to this derived class.
 * 2) construct specify a IWindow and a long denoting a command id.
 * the window must be serviced by the current thread.
 * the command id is to notified the window/current thread of completion.
 * 3)Then from a handler call back call win_th_start.
 * to start anonther thread running.
 */
class WindowThread
// handler to detect completion.
{
   private:



      // event id for completion notification.
      unsigned long eventid;

      // window to use/notify
      IWindow& window;

      // notes that we are notifying orig thread thru a post
      // event. Event will be ignored otherwise.

      // access to this variable must be protected by crit section.
      Boolean notifing;

      // we could derive privately from ICcommandHandler
      // but then the user of this class can not derive from
      // this class and ICommandHandler without conflict.

      // this is the command handler used to be called back
      // on completion.
      class ICom : public ICommandHandler
      {
        private:

          // remember our parent' class for call back.
          WindowThread& win_thread;


          // disabled, not defined.
          ICom( const ICom&);
          ICom& operator=( const ICom& );
        public:

          // conruct from window thread
          ICom( WindowThread& win_thread ) : win_thread(win_thread)
          {
            // handle events for our window.
            handleEventsFor( &win_thread.window );
          };

        protected:


          // command handler detects notification.
          virtual Boolean command( ICommandEvent& event );
      } thread_hand;

      // cooperate with our nested command handler class.
      friend class ICom;

         // disable default constructor, assignment operator, not defined
         WindowTheread( const WindowThread& );
         WindowThread& operator=(const WindowThread&);


      // nested thread class to run thread code.
      class WinThrFn : public IThreadFn
      {
         private:
           // disable default constructor, assignment operator
           WinThrFn();
           WinThrFn& operator=(const WinThrFn&);

           // save the window thread in use.
           WindowThread & wt;
         public:
           WinThrFn(WindowThread& wt) : wt(wt) {};

           // virtual destructor.
           virtual ~WinThrFn() {};

           // call the run call.
           virtual void run ();

      };

      // make the run code a friend.
      friend void WinThrFn::run();

   public:

      // constructor remembers IWindow and eveint id #
      WindowThread(IWindow& window,const long eventid);

      // virtual destructor.
      virtual ~WindowThread() {};

   public:

       // called by user to start the thread.
       virtual void win_th_start( Boolean autoInitGUI =
                                     IThread::defaultAutoInitGUI() );

   protected:

       // optional call back to user before running thread.
       virtual void begin() {} ;

       // code to run on other thread.

       // must be overridden.
       // this is thread code tor run.
       virtual void thread() = 0;

       // optional call back to user after running thread.
       virtual void finish() {} ;

       // runs thread internal, but overridable.
       virtual void run();

       // remember window we are on.
       IWindow& OurWindow() { return window; };

};

#endif  //WINTHR
