Milán Major

netscape-revival

1 branch
Code

sun-java/awt/win/awt_dialog.cpp

#include "awt_dialog.h"
#include "awt_toolkit.h"

// All java header files are extern "C"
extern "C" {
#include "java_awt_Component.h"
#include "java_awt_Dialog.h"

#include "sun_awt_windows_WComponentPeer.h"
#include "sun_awt_windows_WDialogPeer.h"
};


AwtDialog::AwtDialog(HWComponentPeer *peer) : AwtJavaWindow(peer)
{
    DEFINE_AWT_SENTINAL("DLG");

    m_bModalLoop = FALSE;
    m_bInitiateModal = FALSE;
    m_pWindows = 0;
    m_nWindowsCount = 0;
    m_hForegroundWindow = 0;
}


// -----------------------------------------------------------------------
//
// Return the window style used to create an AwtDialog window
//
// -----------------------------------------------------------------------
DWORD AwtDialog::WindowStyle()
{
    return WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
}


//-------------------------------------------------------------------------
//
// Size only needs to do update java info for top level windows
//
//-------------------------------------------------------------------------
BOOL AwtDialog::OnMove(int newX, int newY)
{
#if 0
    // this code is currently dead!!!!!!!!!!!!!!!!!!
    // the reason being the old awt does not work always in parent's
    // coordinates even though specs seem to say so
    Hjava_awt_Component *target;
    RECT rc;
    RECT rcParent;
    HWND hwnd;

    if (m_pJavaPeer) {

        ::GetWindowRect(m_hWnd, &rc);        

        // if there is an owner switch coordinates system
        hwnd = ::GetWindow(m_hWnd, GW_OWNER);

        ASSERT(hwnd);

        ::GetWindowRect(hwnd, &rcParent);

        // update x and y position
        target = unhand((HWComponentPeer *)m_pJavaPeer)->target;
        if (target) {
            unhand(target)->x  = rc.left - rcParent.left;
            unhand(target)->y = rc.top - rcParent.top;
        }
    }
    
    return FALSE;
#endif

    // apparently no one cares about having all the java window with a parent
    // to be expressed in parent coordinates system
    return AwtJavaWindow::OnMove(newX, newY);
}


// -----------------------------------------------------------------------
//
// Modal Dialog specific code
//
// -----------------------------------------------------------------------

typedef struct _countWindows {
    HWND hMyself;
    int counter;
} COUNTWINDOWS;

typedef struct _disableWindows {
    COUNTWINDOWS cw;
    HWND* pWindows;
} DISABLEWINDOWS;


//
// count the number of top level windows in this thread
//
BOOL CALLBACK CountWindows(HWND hwnd, LPARAM lParam)
{
    COUNTWINDOWS* cw = (COUNTWINDOWS*)lParam;

    // if this is not the dialog neither is disabled, count it
    if (hwnd != cw->hMyself && ::IsWindowEnabled(hwnd))
        cw->counter++;

    return TRUE;
}


//
// disable all the top level window
//
BOOL CALLBACK DisableWindows(HWND hwnd, LPARAM lParam)
{
    DISABLEWINDOWS* dw = (DISABLEWINDOWS*)lParam;

    // if we filled the collection return FALSE and stop counting
    // it is ok or some windows will be left out
    if (dw->cw.counter == 0)
        return FALSE;

    // disable the window and add it to the list of handles
    if (hwnd != dw->cw.hMyself && ::IsWindowEnabled(hwnd)) {
        if (::GetParent(hwnd) == NULL) {
            ::EnableWindow(hwnd, FALSE);
            dw->cw.counter--;
            dw->pWindows[dw->cw.counter] = hwnd;
        }
    }

    return TRUE;
}


// -----------------------------------------------------------------------
//
// Disable all dialog's frame owner windows
//
// -----------------------------------------------------------------------
void AwtDialog::DisableWindows()
{
    DISABLEWINDOWS lParam;
    lParam.cw.hMyself = m_hWnd;
    lParam.cw.counter = 0;

#ifdef _WIN32
    // count how many windows to be disabled
    ::EnumThreadWindows(AwtToolkit::theToolkit->GetGuiThreadId(),
                        ::CountWindows,
                        (LPARAM)&lParam);
#else
    ::EnumWindows(::CountWindows,
                        (LPARAM)&lParam);
#endif

    m_nWindowsCount = lParam.cw.counter;

    if (m_nWindowsCount) {

        m_pWindows = new HWND[m_nWindowsCount];

        // disable the windows and add them to the collection
        lParam.pWindows = m_pWindows;

#ifdef _WIN32
        ::EnumThreadWindows(AwtToolkit::theToolkit->GetGuiThreadId(),
                            ::DisableWindows,
                            (LPARAM)&lParam);
#else
        ::EnumWindows(::DisableWindows,
                        (LPARAM)&lParam);
#endif

    }
}


// -----------------------------------------------------------------------
//
// Show implementation for dialogs
//
// -----------------------------------------------------------------------
void AwtDialog::ShowModal(long spinLoop)
{
#ifdef _WIN32
    m_hForegroundWindow = ::GetForegroundWindow();
#else
    m_hForegroundWindow = ::GetActiveWindow();
#endif

    // show the dialog
    Show(TRUE);

    if (m_bInitiateModal == FALSE) {

        m_bInitiateModal = TRUE;

        // disable all the top level windows on this thread
        DisableWindows();

        // this just to cover our ass from the insanity of modality 
        // in java. Enable this since this might have been a hidden 
        // instance in the past. Bullshit!!!
        ::EnableWindow(m_hWnd, TRUE);

#ifdef _WIN32
        ::SetForegroundWindow(m_hWnd);
#else
        ::SetActiveWindow(m_hWnd);
#endif

        //
        // spin a callback loop if required.
        // This happens when a modal dialog is open from a method running
        // in the callback loop (which is the most common case, click on 
        // a button and open a dialog..), we don't return until the dialog
        // is closed, so in order to have java working we must spin a callback loop
        //
        if (spinLoop) {
            m_bModalLoop = FALSE;
            AwtToolkit::theToolkit->CallbackLoop(&m_bModalLoop);
        }
    }
}


// -----------------------------------------------------------------------
//
// Hide implementation for dialogs
//
// -----------------------------------------------------------------------
void AwtDialog::HideModal()
{
    HWND hwnd;

    if (m_bInitiateModal) {
        // stop callback loop
        m_bModalLoop = TRUE;

        // enable all the previously disbaled windows
        for (int i = 0; i < m_nWindowsCount; i++) 
            if (m_pWindows[i])
                ::EnableWindow(m_pWindows[i], TRUE);

#ifdef _WIN32
        delete[] m_pWindows;

        ::SetForegroundWindow(m_hForegroundWindow);
#else
        //delete m_pWindows;

        ::SetActiveWindow(m_hForegroundWindow);
#endif

        m_pWindows = 0;

        m_bInitiateModal = FALSE;
    }

    // hide the dialog
    Show(FALSE);
}


//-------------------------------------------------------------------------
//
// Native method implementations for sun.awt.WDialogPeer
//
//-------------------------------------------------------------------------

extern "C" {

void 
sun_awt_windows_WDialogPeer_create(HWDialogPeer* self,
                                    HWComponentPeer* parent)
{
    AwtDialog    *pNewDialog;

    CHECK_NULL(self, "DialogPeer is null.");
    //CHECK_NULL(parent, "ComponentPeer is null.");

    pNewDialog = new AwtDialog((HWComponentPeer*) self);
    CHECK_ALLOCATION(pNewDialog);

    pNewDialog->CreateWidget( pNewDialog->GetParentWindowHandle(parent) );
}


void 
sun_awt_windows_WDialogPeer_setTitle(HWDialogPeer* self, 
                                        Hjava_lang_String* title)
{
    CHECK_PEER(self);
    CHECK_OBJECT(title);

    int32_t len;
    char *buffer = NULL;
    AwtDialog *obj = GET_OBJ_FROM_PEER(AwtDialog, self);

    len = javaStringLength(title);
    buffer = (char *)malloc(len+1);
    if (buffer) {
        javaString2CString(title, buffer, len+1);

        ::SetWindowText(obj->GetWindowHandle(), buffer);

        free(buffer);
    }
}


void 
sun_awt_windows_WDialogPeer_setResizable(HWDialogPeer* self,
                                            /*boolean*/ long resizable)
{
    CHECK_PEER(self);
    AwtDialog* pDialog = GET_OBJ_FROM_PEER(AwtDialog, self);
    if (pDialog)
        pDialog->Resizable((resizable) ? TRUE : FALSE);
}


void 
sun_awt_windows_WDialogPeer_showModal(HWDialogPeer* self, 
                                        long spinLoop)
{
    CHECK_PEER(self);

    AwtDialog *obj = GET_OBJ_FROM_PEER(AwtDialog, self);

    if (obj)
        obj->ShowModal(spinLoop);
}


void 
sun_awt_windows_WDialogPeer_hideModal(HWDialogPeer* self)
{
    CHECK_PEER(self);

    AwtDialog *obj = GET_OBJ_FROM_PEER(AwtDialog, self);

    if (obj)
        obj->HideModal();
}


}; // end of extern "C"