Milán Major

netscape-revival

1 branch
Code

sun-java/awt.bad/win/awt_javawindow.cpp

#include "awt_javawindow.h"
#include "awt_toolkit.h"

#include "resource.rh"

extern "C" {
#include "javastring.h"

#include "java_awt_Insets.h"
#include "java_awt_Component.h"
#include "java_awt_Window.h"

#include "sun_awt_windows_WComponentPeer.h"
#include "sun_awt_windows_WContainerPeer.h"
#include "sun_awt_windows_WWindowPeer.h"
};

char* AwtJavaWindow::m_pszWarningString = 0;


AwtJavaWindow::AwtJavaWindow(HWComponentPeer *peer) : AwtContainer((JHandle*)peer)
{
    DEFINE_AWT_SENTINAL("JWN");
    m_hStatusWnd = 0;
}


AwtJavaWindow::~AwtJavaWindow()
{
}


// -----------------------------------------------------------------------
//
// Create an AwtJavaWindow. Add a status bar to the normal creation to hold
// "Unsigned Java Applet Window"
//
// This method MUST be executed on the "main gui thread".  Since this
// method is ALWAYS executed on the same thread no locking is necessary.
//
// -----------------------------------------------------------------------
void AwtJavaWindow::CreateWidget(HWND hwndParent)
{
    Hjava_awt_Window *target;

#ifdef _WIN32
    //
    // Switch to the "main gui thread" if necessary... This method must
    // be executed on the "gui thread" because it creates a window...
    //
    if (! AwtToolkit::theToolkit->IsGuiThread()) {
        AwtMethodInfo info(this, AwtComponent::CREATE, (long)hwndParent);
        AwtToolkit::theToolkit->CallAwtMethod( &info );
        return;
    }
#endif

    //
    // This method is now being executed on the "main gui thread"
    //
    ASSERT( AwtToolkit::theToolkit->IsGuiThread() );

    target = (Hjava_awt_Window *)
                unhand((HWComponentPeer *)m_pJavaPeer)->target;

    CHECK_NULL( target, "Target is null." );


    //
    // Create the new window
    //
    m_hWnd = ::CreateWindow(WindowClass(),
                            "",
                            WindowStyle(),
                            (int) unhand(target)->x,
                            (int) unhand(target)->y,
                            (int) unhand(target)->width,
                            (int) unhand(target)->height,
                            hwndParent,
                            NULL,
                            WindowHInst(),
                            NULL);

    // check if a warning string is around ("Unsigned Java Applet")
    Hjava_lang_String* string = unhand(target)->warningString;
    if (string) {
        RECT rc;

        // assign the warning string to a static so that we don't have to
        // reload it for any other applet
        if (!AwtJavaWindow::m_pszWarningString) {
            int32_t len    = javaStringLength(string);
            AwtJavaWindow::m_pszWarningString = (char *)malloc(len+1);
            if (AwtJavaWindow::m_pszWarningString)
                javaString2CString(string, AwtJavaWindow::m_pszWarningString, len+1);
        }

        ::GetClientRect(m_hWnd, &rc);

        //
        // create a status bar 
        //
        m_hStatusWnd = ::CreateWindow("AwtWarningLabelClass",
                                "",
                                WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
                                0, 
                                rc.bottom - STATUS_BAR_HEIGHT,
                                rc.right,
                                (int) STATUS_BAR_HEIGHT,
                                m_hWnd,
                                NULL,
                                ::GetModuleHandle(NULL),
                                NULL);
    }
    //
    // Subclass the window to allow windows events to be intercepted...
    //
    ASSERT( ::IsWindow(m_hWnd) );
    SubclassWindow(TRUE);
}


DWORD AwtJavaWindow::WindowStyle()
{
    return WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
}


// -----------------------------------------------------------------------
//
// Adjust the size according to the existence of the warning status bar
//
// -----------------------------------------------------------------------
BOOL AwtJavaWindow::OnSize(UINT sizeCode, UINT newWidth, UINT newHeight)
{
    AwtContainer::OnSize(sizeCode, newWidth, newHeight);

    // update information if the warning status bar is there
    if (m_hStatusWnd) {
        RECT rc;
        ::GetClientRect(m_hWnd, &rc);
        ::SetWindowPos(m_hStatusWnd, 
                            HWND_TOP,
                            0, 
                            rc.bottom - STATUS_BAR_HEIGHT, 
                            rc.right, 
                            STATUS_BAR_HEIGHT, 
                            SWP_NOACTIVATE);
    }

    return FALSE;   // Pass the event on to Windows
}


//-------------------------------------------------------------------------
//
// Move update the x and y position for the component and fire a move event
// The (x,y) position is in screen coordinates.
//-------------------------------------------------------------------------
BOOL AwtJavaWindow::OnMove(int newX, int newY)
{
    Hjava_awt_Component *target;
    if (m_pJavaPeer) {
        //
        // Update the width & height in java.awt.Component
        //
        // Since the target's width and height properties are not public
        // they cannot be updated within WComponentPeer::handleResize() 
        //
        target = unhand((HWComponentPeer *)m_pJavaPeer)->target;
        if (target) {
            unhand(target)->x  = newX;
            unhand(target)->y  = newY;
        }

#if 0
        //
        // Call netscape.awt.windows.WComponentPeer::handleResize(...)
        //
        AwtToolkit::RaiseJavaEvent(m_pJavaPeer, AwtEventDescription::Move,
                                   ll_zero_const, NULL,
                                   newX, newY);
#endif
    }
    return FALSE;
}
    
    // -----------------------------------------------------------------------
//
// Allow the AwtJavaWindow to be resized by the user.  Resizable frames have
// a thick border (ie. WS_THICHFRAME) which can be dragged.
//
// -----------------------------------------------------------------------
void AwtJavaWindow::Resizable(BOOL bState)
{
    long style;
    ASSERT( ::IsWindow(m_hWnd) );
   
    // Get the current window style...
    style = ::GetWindowLong(m_hWnd, GWL_STYLE);

    // A window is resizable if the WS_THICKFRAME style is set.
    if (bState) {
        style |= WS_THICKFRAME;
    } else {
        style &= ~WS_THICKFRAME;
    }

    // Set the new window style...
    VERIFY(::SetWindowLong(m_hWnd, GWL_STYLE, style));
}


// -----------------------------------------------------------------------
//
// Move a window at the bottom of the z order
//
// -----------------------------------------------------------------------
void AwtJavaWindow::MoveToBack()
{
    ASSERT( ::IsWindow(m_hWnd) );
    ::SetWindowPos(m_hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}


//-------------------------------------------------------------------------
//
// Adjust insets according to the existence of the warning status bar
//
//-------------------------------------------------------------------------
void AwtJavaWindow::CalculateInsets(Hjava_awt_Insets *insets)
{
    RECT outside;
    RECT inside;

    if (insets) {
        ASSERT( ::IsWindow(m_hWnd ) );
        //
        // Get the inside and outside dimensions of the component
        //
        ::GetWindowRect(m_hWnd, &outside);
        ::GetClientRect(m_hWnd, &inside);

        //
        // Map the inside dimensions from client coordinates to screen
        // coordinates.
        //
        ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&inside, 2);

        //
        // Calculate the insets for the component...
        //
        unhand(insets)->top    = inside.top     - outside.top;
        unhand(insets)->bottom = outside.bottom - inside.bottom;
        unhand(insets)->left   = inside.left    - outside.left;
        unhand(insets)->right  = outside.right  - inside.right;
    }

    // add the status bar size if we need to
    if (m_hStatusWnd) {
        unhand(insets)->bottom += STATUS_BAR_HEIGHT;
    }

}


//
// native functions
//
extern "C" {

void 
sun_awt_windows_WWindowPeer_create(HWWindowPeer* self,
                                    HWComponentPeer* parent)
{
    AwtJavaWindow    *pNewWindow;

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

    pNewWindow = new AwtJavaWindow((HWComponentPeer*) self);
    CHECK_ALLOCATION(pNewWindow);

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

void 
sun_awt_windows_WWindowPeer_toBack(HWWindowPeer* self)
{
    CHECK_PEER(self);
    AwtJavaWindow* pWindow = GET_OBJ_FROM_PEER(AwtJavaWindow, self);
    if (pWindow)
        pWindow->MoveToBack();
}

};


//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
//
// Warning status bar window procedure
//
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
LRESULT AWT_CALLBACK StatusFrameProc(HWND hWnd, 
                                     UINT Msg, 
                                     WPARAM WParam, 
                                     LPARAM lParam)
{
    switch (Msg) {

		case WM_ERASEBKGND:
		return TRUE;

        case WM_PAINT: 
        {
            HDC hdc;
            PAINTSTRUCT ps;
			HBRUSH hBkColor;
			RECT rc;
			BITMAP bmp;
			bmp.bmWidth = 0; // zero the field we'll use

            hdc = ::BeginPaint(hWnd, &ps);
			
	        // select the font into the dc
	        HGDIOBJ hOldFont = ::SelectObject(hdc, ::GetStockObject(ANSI_VAR_FONT));

			// fill client area with background color
			::GetClientRect(hWnd, &rc);
			hBkColor = ::CreateSolidBrush(::GetSysColor(COLOR_BTNFACE));
			::FillRect(hdc, &rc, hBkColor);

            // load the broken key bitmap (unsigned java applet)
			HBITMAP hbKey = ::LoadBitmap(AwtToolkit::m_hDllInstance, MAKEINTRESOURCE(IDB_INSECURE));
			if (hbKey) {
				HDC hComp = ::CreateCompatibleDC(hdc);
				if (hComp) {

					if (::SelectObject(hComp, hbKey)) {

						// just to be sure the same mode is applied
						::SetMapMode(hComp, ::GetMapMode(hdc));

						// get the bitmap size
						if (::GetObject(hbKey, sizeof(BITMAP), &bmp)) {
							// splash the bitmap on screen
							::BitBlt(hdc, 10, 4, bmp.bmWidth, bmp.bmHeight, hComp, 0, 0, SRCCOPY);
						}
					}

					// delete the compatible dc
					::DeleteDC(hComp);
				}

				// delete the bitmap
				::DeleteObject(hbKey);
			}

            // create pens for 3d status bar look
            HPEN hPen1 = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNHIGHLIGHT));
            HPEN hPen2 = ::CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNSHADOW));

            if (AwtJavaWindow::m_pszWarningString) {
			    // get pszWarningString length
			    SIZE size;
			    ::GetTextExtentPoint(hdc, AwtJavaWindow::m_pszWarningString, 27, &size);
			    size.cx += size.cx / 4;

                // paint the box
                ::MoveToEx(hdc, 20 + bmp.bmWidth + size.cx, 3, NULL);

                ::SelectObject(hdc, hPen1);
                ::LineTo(hdc, 20 + bmp.bmWidth + size.cx, 19);
                ::LineTo(hdc, 20 + bmp.bmWidth, 19);

                ::SelectObject(hdc, hPen2);
                ::LineTo(hdc, 20 + bmp.bmWidth, 3);
                ::LineTo(hdc, 20 + bmp.bmWidth + size.cx, 3);

			    // paint a sort of 3D border
                ::SelectObject(hdc, hPen1);
                ::MoveToEx(hdc, 0, 0, NULL);
                ::LineTo(hdc, rc.right, 0);

                // paint the text
                ::SetTextColor(hdc, ::GetSysColor(COLOR_BTNTEXT));

			    int nMode = ::SetBkMode(hdc, TRANSPARENT);

                ::TextOut(hdc, 20 + bmp.bmWidth + 3, 4, AwtJavaWindow::m_pszWarningString, 27);

                ::SetBkMode(hdc, nMode);
                ::SelectObject(hdc, hOldFont);
            }

            ::EndPaint(hWnd, &ps);

            // clean up
            ::DeleteObject(hPen1);
            ::DeleteObject(hPen2);
            ::DeleteObject(hBkColor);
            return 0;
        }

    }

    return ::CallWindowProc(::DefWindowProc, hWnd, Msg, WParam, lParam);
}