/* AbiWord * Copyright (C) 1998 AbiSource, Inc. * Copyright (C) 2001-2004 Hubert Figuiere * * 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., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #import #include "ut_types.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "xap_Frame.h" #include "xap_CocoaFrame.h" #include "ap_CocoaFrame.h" #include "ap_CocoaStatusBar.h" #import "xap_CocoaFrameImpl.h" #define FIELD_SPACING 4.0f class ap_csb_TextListener : public AP_StatusBarFieldListener { public: /* policy is as usual retain the object */ ap_csb_TextListener(AP_StatusBarField *pStatusBarField, NSTextField *pLabel) : AP_StatusBarFieldListener(pStatusBarField) { m_pLabel = pLabel; [m_pLabel retain]; } virtual ~ap_csb_TextListener() { [m_pLabel release]; } virtual void notify(); protected: NSTextField *m_pLabel; }; void ap_csb_TextListener::notify() { UT_ASSERT(m_pLabel); AP_StatusBarField_TextInfo * textInfo = ((AP_StatusBarField_TextInfo *)m_pStatusBarField); NSString* str = [[NSString alloc] initWithUTF8String:textInfo->getBuf().utf8_str()]; [m_pLabel setStringValue:str]; [str release]; // we conditionally update the size request, if the representative string (or an earlier // size) wasn't large enough, if the element uses the representative string method // and is aligned with the center if (textInfo->getFillMethod() == REPRESENTATIVE_STRING && textInfo->getAlignmentMethod() == CENTER) { // TODO FIXME /* GtkRequisition requisition; gint iOldWidthRequest, iOldHeightRequest; gtk_widget_get_size_request(m_pLabel, &iOldWidthRequest, &iOldHeightRequest); gtk_widget_set_size_request(m_pLabel, -1, -1); gtk_widget_size_request(m_pLabel, &requisition); if (requisition.width > iOldWidthRequest) gtk_widget_set_size_request(m_pLabel, requisition.width, -1); else gtk_widget_set_size_request(m_pLabel, iOldWidthRequest, -1); */ } } ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// AP_CocoaStatusBar::AP_CocoaStatusBar(XAP_Frame * pFrame) : AP_StatusBar(pFrame), m_wStatusBar(nil), m_hidden(false), m_requestedWidth(0), m_numMaxWidth(0) { /* fetch the widget from the controller */ m_wStatusBar = [(XAP_CocoaFrameController *)(static_cast(m_pFrame->getFrameImpl()))->_getController() getStatusBar]; [m_wStatusBar setPostsFrameChangedNotifications:YES]; [m_wStatusBar setPostsBoundsChangedNotifications:YES]; UT_DEBUGMSG(("XAP_CocoaNSStatusBar did subscribe to resize notification\n")); NSRect frame = [m_wStatusBar frame]; [m_wStatusBar setXAPOwner:this]; UT_DEBUGMSG(("m_wStatusBar x=%f y=%f w=%f h=%f\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height)); [[NSNotificationCenter defaultCenter] addObserver:m_wStatusBar selector:@selector(statusBarDidResize:) name:NSViewFrameDidChangeNotification object:m_wStatusBar]; } AP_CocoaStatusBar::~AP_CocoaStatusBar(void) { if ((m_hidden) && ([m_wStatusBar superview] == nil)) { [m_wStatusBar setXAPOwner:nil]; [m_wStatusBar release]; [[NSNotificationCenter defaultCenter] removeObserver:m_wStatusBar]; } } void AP_CocoaStatusBar::setView(AV_View * pView) { AP_StatusBar::setView(pView); } XAP_CocoaNSStatusBar * AP_CocoaStatusBar::createWidget(void) { UT_ASSERT(m_wStatusBar); float currentX = 0.0; float height = [m_wStatusBar frame].size.height; NSString* str; m_requestedWidth = 0; m_numMaxWidth = 0; NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; for (UT_sint32 k=0; kgetItemCount(); k++) { AP_StatusBarField * pf = (AP_StatusBarField *)m_vecFields.getNthItem(k); UT_ASSERT(pf); // we should NOT have null elements AP_StatusBarField_TextInfo *pf_TextInfo = static_cast(pf); NSRect frame = NSMakeRect (currentX, 0, 100, height); NSTextField *pStatusBarElementLabel = [[NSTextField alloc] initWithFrame:frame]; pf->setListener(static_cast(new ap_csb_TextListener (pf_TextInfo, pStatusBarElementLabel))); [pStatusBarElementLabel setFont:font]; [pStatusBarElementLabel setEditable:NO]; [pStatusBarElementLabel setBezeled:YES]; [pStatusBarElementLabel setSelectable:NO]; // align text switch (pf_TextInfo->getAlignmentMethod()) { case LEFT: [pStatusBarElementLabel setAlignment:NSNaturalTextAlignment]; break; case CENTER: [pStatusBarElementLabel setAlignment:NSCenterTextAlignment]; break; default: UT_ASSERT_NOT_REACHED(); } // size and place switch (pf_TextInfo->getFillMethod()) { case REPRESENTATIVE_STRING: str = [[NSString alloc] initWithUTF8String:pf_TextInfo->getRepresentativeString()]; [pStatusBarElementLabel setStringValue:str]; [str release]; [pStatusBarElementLabel sizeToFit]; [pStatusBarElementLabel setStringValue:@""]; frame = [pStatusBarElementLabel bounds]; height = frame.size.height; m_requestedWidth += frame.size.width + FIELD_SPACING; [pStatusBarElementLabel setTag:lrintf(frame.size.width)]; UT_DEBUGMSG(("New size is: w=%f h=%f\n", frame.size.width, frame.size.height)); break; case MAX_POSSIBLE: [pStatusBarElementLabel setTag:-1]; m_numMaxWidth++; break; default: UT_ASSERT_NOT_REACHED(); } [m_wStatusBar addSubview:pStatusBarElementLabel]; UT_DEBUGMSG(("added status bar element. Frame = %f %f %f %f\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height)); [pStatusBarElementLabel release]; currentX += frame.size.width + FIELD_SPACING; } _repositionFields([m_wStatusBar subviews]); return m_wStatusBar; } void AP_CocoaStatusBar::_repositionFields(NSArray *fields) { float maxWidth = [m_wStatusBar bounds].size.width; float freeWidth = maxWidth - m_requestedWidth; NSEnumerator* iter = [fields objectEnumerator]; NSTextField* obj; float prevX = 0; while ((obj = [iter nextObject])) { int tag = [obj tag]; NSRect frame = [obj frame]; frame.origin.x = prevX; if (tag == -1) { frame.size.width = (freeWidth / (float)m_numMaxWidth) - FIELD_SPACING; } prevX += frame.size.width + FIELD_SPACING; [obj setFrame:frame]; UT_DEBUGMSG(("resized status bar element. Frame = %f %f %f %f\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height)); } } void AP_CocoaStatusBar::show(void) { UT_DEBUGMSG(("AP_CocoaStatusBar::show(void)\n")); if ([m_wStatusBar superview] == nil) { [m_superView addSubview:m_wStatusBar]; [m_wStatusBar release]; } m_hidden = false; } void AP_CocoaStatusBar::hide(void) { UT_DEBUGMSG(("AP_CocoaStatusBar::hide(void)\n")); if ([m_wStatusBar superview] != nil) { m_superView = [m_wStatusBar superview]; UT_ASSERT (m_superView); [m_wStatusBar retain]; [m_wStatusBar removeFromSuperview]; } // TODO Check about resizing / layout changes m_hidden = true; } @implementation XAP_CocoaNSStatusBar - (id)initWithFrame:(NSRect)frame { if(![super initWithFrame:frame]) { return nil; } return self; } - (void)setXAPOwner:(AP_CocoaStatusBar*)owner { _xap = owner; } - (void)statusBarDidResize:(NSNotification *)notification { UT_UNUSED(notification); if (_xap) { UT_DEBUGMSG(("-[XAP_CocoaNSStatusBar statusBarDidResize:]\n")); _xap->_repositionFields([self subviews]); } } @end