1 /* AbiWord
2 * Copyright (C) 1998-2000 AbiSource, Inc.
3 * Copyright (C) 2001-2003 Hubert Figuiere
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA.
19 */
20
21 #include <Cocoa/Cocoa.h>
22
23 #include "ut_types.h"
24 #include "ut_debugmsg.h"
25 #include "ut_assert.h"
26 #include "xap_ViewListener.h"
27 #include "ap_FrameData.h"
28 #include "xap_CocoaFrame.h"
29 #include "ev_CocoaToolbar.h"
30 #include "xav_View.h"
31 #include "fv_View.h"
32 #include "fl_DocLayout.h"
33 #include "gr_CocoaCairoGraphics.h"
34 #include "xap_Scrollbar_ViewListener.h"
35 #include "ap_CocoaFrame.h"
36 #include "xap_CocoaApp.h"
37 #include "ap_CocoaTopRuler.h"
38 #include "ap_CocoaLeftRuler.h"
39 #include "ap_CocoaStatusBar.h"
40 #include "ap_CocoaViewListener.h"
41
42 #import "ap_CocoaFrameImpl.h"
43
44 /*****************************************************************/
45 #define ENSUREP_RF(p) do { UT_ASSERT(p); if (!p) return false; } while (0)
46 #define ENSUREP(p) do { UT_ASSERT(p); if (!p) goto Cleanup; } while (0)
47
48
setXScrollRange(void)49 void AP_CocoaFrame::setXScrollRange(void)
50 {
51 GR_Graphics* pGr = ((AP_FrameData*)m_pData)->m_pG;
52 AP_CocoaFrameImpl* pFrameImpl = static_cast<AP_CocoaFrameImpl *>(getFrameImpl());
53 UT_sint32 width = ((AP_FrameData*)m_pData)->m_pDocLayout->getWidth();
54 NSRect rect = [pFrameImpl->m_docAreaGRView frame];
55 UT_sint32 visibleWidth = pGr->tlu(lrintf(rect.size.width));
56 pFrameImpl->_setHVisible(visibleWidth);
57 UT_DEBUGMSG(("visibleWidth: %d, doc width:%d\n", visibleWidth, width));
58 if (m_pView == NULL) {
59 UT_DEBUGMSG(("m_pView is NULL\n"));
60 }
61
62 UT_sint32 newvalue = ((m_pView) ? m_pView->getXScrollOffset() : 0);
63 UT_sint32 newmax = width - visibleWidth; /* upper - page_size */
64 if (newmax <= 0)
65 newmax = 0;
66 else if (newvalue > newmax)
67 newvalue = newmax;
68 UT_DEBUGMSG (("newmax = %d, newvalue = %d\n", newmax, newvalue));
69 pFrameImpl->_setHScrollMax(newmax);
70 pFrameImpl->_setHScrollValue(newvalue);
71
72 m_pView->sendHorizontalScrollEvent(newvalue, newmax);
73 }
74
setYScrollRange(void)75 void AP_CocoaFrame::setYScrollRange(void)
76 {
77 GR_Graphics* pGr = ((AP_FrameData*)m_pData)->m_pG;
78 AP_CocoaFrameImpl * pFrameImpl = static_cast<AP_CocoaFrameImpl *>(getFrameImpl());
79 UT_sint32 height = ((AP_FrameData*)m_pData)->m_pDocLayout->getHeight();
80 NSRect rect = [pFrameImpl->m_docAreaGRView frame];
81 UT_sint32 visibleHeight = pGr->tlu(lrintf(rect.size.height));
82 pFrameImpl->_setVVisible(visibleHeight);
83 UT_DEBUGMSG(("visibleHeight: %d, doc height:%d\n", visibleHeight, height));
84 if (m_pView == NULL) {
85 UT_DEBUGMSG(("m_pView is NULL\n"));
86 }
87
88 UT_sint32 newvalue = ((m_pView) ? m_pView->getYScrollOffset() : 0);
89 UT_sint32 newmax = height - visibleHeight; /* upper - page_size */
90 if (newmax <= 0)
91 newmax = 0;
92 else if (newvalue > newmax)
93 newvalue = newmax;
94 UT_DEBUGMSG (("newmax = %d, newvalue = %d\n", newmax, newvalue));
95 pFrameImpl->_setVScrollMax(newmax);
96 pFrameImpl->_setVScrollValue(newvalue);
97
98 // TODO optimize
99 m_pView->sendVerticalScrollEvent(newvalue, newmax);
100 }
101
102
AP_CocoaFrame()103 AP_CocoaFrame::AP_CocoaFrame()
104 : AP_Frame (new AP_CocoaFrameImpl(this))
105 {
106 m_pData = NULL;
107 // static_cast<AP_CocoaFrameImpl *>(m_pFrameImpl)->setShowDocLocked(false);
108 }
109
AP_CocoaFrame(AP_CocoaFrame * f)110 AP_CocoaFrame::AP_CocoaFrame(AP_CocoaFrame * f)
111 : AP_Frame(static_cast<AP_Frame *>(f))
112 {
113 m_pData = NULL;
114 }
115
~AP_CocoaFrame()116 AP_CocoaFrame::~AP_CocoaFrame()
117 {
118 killFrameData();
119 }
120
initialize(XAP_FrameMode)121 bool AP_CocoaFrame::initialize(XAP_FrameMode /*frameMode*/)
122 {
123 AP_CocoaFrameImpl* pFrameImpl = static_cast<AP_CocoaFrameImpl *>(getFrameImpl());
124 UT_DEBUGMSG(("AP_CocoaFrame::initialize\n"));
125 if (!initFrameData())
126 return false;
127
128 if (!XAP_Frame::initialize(AP_PREF_KEY_KeyBindings,AP_PREF_DEFAULT_KeyBindings,
129 AP_PREF_KEY_MenuLayout, AP_PREF_DEFAULT_MenuLayout,
130 AP_PREF_KEY_StringSet, AP_PREF_DEFAULT_StringSet,
131 AP_PREF_KEY_ToolbarLayouts, AP_PREF_DEFAULT_ToolbarLayouts,
132 AP_PREF_KEY_StringSet, AP_PREF_DEFAULT_StringSet))
133 return false;
134
135 pFrameImpl->_createTopLevelWindow();
136 // gtk_widget_show(m_wTopLevelWindow);
137 if(getFrameMode() == XAP_NormalFrame)
138 {
139 // needs to be shown so that the following functions work
140 // TODO: get rid of cursed flicker caused by initially
141 // TODO: showing these and then hiding them (esp.
142 // TODO: noticable in the gnome build with a toolbar disabled)
143 pFrameImpl->_showOrHideToolbars();
144 pFrameImpl->_showOrHideStatusbar();
145 }
146 // pFrameImpl->_show(); // defer this
147
148 return true;
149 }
150
151
152
153
154 /*****************************************************************/
155
cloneFrame()156 XAP_Frame * AP_CocoaFrame::cloneFrame()
157 {
158 AP_CocoaFrame * pClone = new AP_CocoaFrame(this);
159 ENSUREP(pClone);
160 return static_cast<XAP_Frame *> (pClone);
161
162 Cleanup:
163 // clean up anything we created here
164 if (pClone)
165 {
166 XAP_App::getApp()->forgetFrame(pClone);
167 delete pClone;
168 }
169
170 return NULL;
171 }
172
173
_scrollFuncY(void * pData,UT_sint32 yoff,UT_sint32)174 void AP_CocoaFrame::_scrollFuncY(void * pData, UT_sint32 yoff, UT_sint32 /*yrange*/)
175 {
176 // this is a static callback function and doesn't have a 'this' pointer.
177 AP_CocoaFrame * pCocoaFrame = static_cast<AP_CocoaFrame *>(pData);
178 AP_CocoaFrameImpl* pFrameImpl = static_cast<AP_CocoaFrameImpl*>(pCocoaFrame->getFrameImpl());
179 AV_View * pView = pCocoaFrame->getCurrentView();
180
181 if (pFrameImpl->_getVScrollMin() > yoff) {
182 yoff = pFrameImpl->_getVScrollMin();
183 }
184 if (pFrameImpl->_getVScrollMax() < yoff) {
185 yoff = pFrameImpl->_getVScrollMax();
186 }
187 pFrameImpl->_setVScrollValue(yoff);
188
189 pView->setYScrollOffset(yoff);
190 }
191
_scrollFuncX(void * pData,UT_sint32 xoff,UT_sint32)192 void AP_CocoaFrame::_scrollFuncX(void * pData, UT_sint32 xoff, UT_sint32 /*xrange*/)
193 {
194 // this is a static callback function and doesn't have a 'this' pointer.
195
196 AP_CocoaFrame * pCocoaFrame = static_cast<AP_CocoaFrame *>(pData);
197 AP_CocoaFrameImpl* pFrameImpl = static_cast<AP_CocoaFrameImpl*>(pCocoaFrame->getFrameImpl());
198 AV_View * pView = pCocoaFrame->getCurrentView();
199
200 if (pFrameImpl->_getHScrollMin() > xoff) {
201 xoff = pFrameImpl->_getHScrollMin();
202 }
203 if (pFrameImpl->_getHScrollMax() < xoff) {
204 xoff = pFrameImpl->_getHScrollMax();
205 }
206 pFrameImpl->_setHScrollValue(xoff);
207
208 pView->setXScrollOffset(xoff);
209 }
210
211
212
translateDocumentToScreen(UT_sint32 &,UT_sint32 &)213 void AP_CocoaFrame::translateDocumentToScreen(UT_sint32 & /*x*/, UT_sint32 & /*y*/)
214 {
215 // translate the given document mouse coordinates into absolute screen coordinates.
216 UT_ASSERT (UT_NOT_IMPLEMENTED);
217 #if 0
218 Window child;
219 gint tx;
220 gint ty;
221
222 GdkWindowPrivate * priv = (GdkWindowPrivate*) m_dArea->window;
223 if (!priv->destroyed)
224 XTranslateCoordinates (priv->xdisplay, priv->xwindow, gdk_root_window, x, y, &tx, &ty, &child);
225
226 x = tx;
227 y = ty;
228 #endif
229 }
230
231
setStatusMessage(const char * szMsg)232 void AP_CocoaFrame::setStatusMessage(const char * szMsg)
233 {
234 ((AP_FrameData *)m_pData)->m_pStatusBar->setStatusMessage(szMsg);
235 }
236
237
toggleTopRuler(bool bRulerOn)238 void AP_CocoaFrame::toggleTopRuler(bool bRulerOn)
239 {
240 AP_FrameData *pFrameData = static_cast<AP_FrameData *>(getFrameData());
241 UT_ASSERT(pFrameData);
242
243 AP_CocoaTopRuler * pCocoaTopRuler = NULL;
244
245 UT_DEBUGMSG(("AP_CocoaFrame::toggleTopRuler %d, %p\n",
246 bRulerOn, pFrameData->m_pTopRuler));
247 if (bRulerOn) {
248 AP_TopRuler * pTop = pFrameData->m_pTopRuler;
249 if(pTop) {
250 delete pTop;
251 }
252
253 pCocoaTopRuler = new AP_CocoaTopRuler(this);
254 UT_ASSERT(pCocoaTopRuler);
255
256 // get the width from the left ruler and stuff it into the
257 // top ruler.
258
259 if (static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler) {
260 pCocoaTopRuler->setOffsetLeftRuler(((AP_FrameData*)m_pData)->m_pLeftRuler->getWidth());
261 }
262 else {
263 pCocoaTopRuler->setOffsetLeftRuler(0);
264 }
265
266 // attach everything
267 static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->_showTopRulerNSView();
268 FV_View * pView = static_cast<FV_View *>(m_pView);
269 UT_uint32 iZoom = pView->getGraphics()->getZoomPercentage();
270 static_cast<AP_TopRuler *>(pCocoaTopRuler)->setView(m_pView,iZoom);
271 }
272 else {
273 static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->_hideTopRulerNSView();
274 DELETEP(((AP_FrameData*)m_pData)->m_pTopRuler);
275 static_cast<FV_View *>(m_pView)->setTopRuler(NULL);
276 }
277 static_cast<AP_FrameData*>(m_pData)->m_pTopRuler = pCocoaTopRuler;
278 }
279
toggleLeftRuler(bool bRulerOn)280 void AP_CocoaFrame::toggleLeftRuler(bool bRulerOn)
281 {
282 AP_FrameData *pFrameData = (AP_FrameData *)getFrameData();
283 UT_ASSERT(pFrameData);
284
285 UT_DEBUGMSG(("AP_CocoaFrame::toggleLeftRuler %d, %p\n", bRulerOn, pFrameData->m_pLeftRuler));
286
287 if (bRulerOn) {
288 AP_CocoaLeftRuler* pCocoaLeftRuler;
289 FV_View * pView = static_cast<FV_View *>(m_pView);
290 UT_uint32 iZoom = pView->getGraphics()->getZoomPercentage();
291
292 pCocoaLeftRuler = new AP_CocoaLeftRuler(this);
293 UT_ASSERT(pCocoaLeftRuler);
294 pFrameData->m_pLeftRuler = pCocoaLeftRuler;
295
296 static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->_showLeftRulerNSView();
297 static_cast<AP_LeftRuler *>(pCocoaLeftRuler)->setView(m_pView, iZoom);
298 setYScrollRange ();
299 }
300 else {
301 if (pFrameData->m_pLeftRuler) {
302 DELETEP(pFrameData->m_pLeftRuler);
303 static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->_hideLeftRulerNSView();
304 static_cast<FV_View *>(m_pView)->setLeftRuler(NULL);
305 }
306 else {
307 UT_DEBUGMSG(("Left Ruler already hidden\n"));
308 }
309 }
310
311 }
312
toggleRuler(bool bRulerOn)313 void AP_CocoaFrame::toggleRuler(bool bRulerOn)
314 {
315 AP_FrameData *pFrameData = (AP_FrameData *)getFrameData();
316 UT_ASSERT(pFrameData);
317
318 toggleTopRuler(bRulerOn);
319 toggleLeftRuler(bRulerOn && (pFrameData->m_pViewMode == VIEW_PRINT));
320
321 [(static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->m_docAreaGRView) setNeedsDisplay:YES];
322 }
323
toggleBar(UT_uint32 iBarNb,bool bBarOn)324 void AP_CocoaFrame::toggleBar(UT_uint32 iBarNb, bool bBarOn)
325 {
326 UT_DEBUGMSG(("AP_CocoaFrame::toggleBar %d, %d\n", iBarNb, bBarOn));
327
328 AP_FrameData *pFrameData = static_cast<AP_FrameData *> (getFrameData());
329 UT_ASSERT(pFrameData);
330
331 if (bBarOn) {
332 pFrameData->m_pToolbar[iBarNb]->show();
333 }
334 else { // turning toolbar off
335 pFrameData->m_pToolbar[iBarNb]->hide();
336 }
337 }
338
toggleStatusBar(bool bStatusBarOn)339 void AP_CocoaFrame::toggleStatusBar(bool bStatusBarOn)
340 {
341 UT_DEBUGMSG(("AP_CocoaFrame::toggleStatusBar %d\n", bStatusBarOn));
342
343 AP_FrameData *pFrameData = static_cast<AP_FrameData *> (getFrameData());
344 UT_ASSERT(pFrameData);
345
346 if (bStatusBarOn) {
347 pFrameData->m_pStatusBar->show();
348 }
349 else { // turning status bar off
350 pFrameData->m_pStatusBar->hide();
351 }
352 }
353
_createScrollBarListeners(AV_View * pView,AV_ScrollObj * & pScrollObj,ap_ViewListener * & pViewListener,ap_Scrollbar_ViewListener * & pScrollbarViewListener,AV_ListenerId & lid,AV_ListenerId & lidScrollbarViewListener)354 bool AP_CocoaFrame::_createScrollBarListeners(AV_View * pView, AV_ScrollObj *& pScrollObj,
355 ap_ViewListener *& pViewListener, ap_Scrollbar_ViewListener *& pScrollbarViewListener,
356 AV_ListenerId &lid, AV_ListenerId &lidScrollbarViewListener)
357 {
358 // The "AV_ScrollObj pScrollObj" receives
359 // send{Vertical,Horizontal}ScrollEvents
360 // from both the scroll-related edit methods
361 // and from the UI callbacks.
362 //
363 // The "ap_ViewListener pViewListener" receives
364 // change notifications as the document changes.
365 // This ViewListener is responsible for keeping
366 // the title-bar up to date (primarily title
367 // changes, dirty indicator, and window number).
368 // ON UNIX ONLY: we subclass this with ap_UnixViewListener
369 // ON UNIX ONLY: so that we can deal with X-Selections.
370 //
371 // The "ap_Scrollbar_ViewListener pScrollbarViewListener"
372 // receives change notifications as the doucment changes.
373 // This ViewListener is responsible for recalibrating the
374 // scrollbars as pages are added/removed from the document.
375 //
376 // Each Toolbar will also get a ViewListener so that
377 // it can update toggle buttons, and other state-indicating
378 // controls on it.
379 //
380 // TODO we ***really*** need to re-do the whole scrollbar thing.
381 // TODO we have an addScrollListener() using an m_pScrollObj
382 // TODO and a View-Listener, and a bunch of other widget stuff.
383 // TODO and its very confusing.
384
385 pScrollObj = new AV_ScrollObj(this,_scrollFuncX,_scrollFuncY);
386 ENSUREP_RF(pScrollObj);
387
388 pViewListener = new ap_CocoaViewListener(this);
389 ENSUREP_RF(pViewListener);
390 pScrollbarViewListener = new ap_Scrollbar_ViewListener(this,pView);
391 ENSUREP_RF(pScrollbarViewListener);
392
393 if (!pView->addListener(static_cast<AV_Listener *>(pViewListener),&lid))
394 return false;
395 if (!pView->addListener(static_cast<AV_Listener *>(pScrollbarViewListener),
396 &lidScrollbarViewListener))
397 return false;
398
399 return true;
400 }
401
402
_getDocumentAreaWidth()403 UT_sint32 AP_CocoaFrame::_getDocumentAreaWidth()
404 {
405 return (UT_sint32)[static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->m_docAreaGRView frame].size.width;
406 }
407
_getDocumentAreaHeight()408 UT_sint32 AP_CocoaFrame::_getDocumentAreaHeight()
409 {
410 return (UT_sint32)[static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->m_docAreaGRView frame].size.height;
411 }
412
_createViewGraphics(GR_Graphics * & pG,UT_uint32 iZoom)413 bool AP_CocoaFrame::_createViewGraphics(GR_Graphics *& pG, UT_uint32 iZoom)
414 {
415
416 static_cast<AP_CocoaFrameImpl*>(getFrameImpl())->_createDocView(pG);
417 ENSUREP_RF(pG);
418 pG->setZoomPercentage(iZoom);
419
420 return true;
421 }
422
_setViewFocus(AV_View *)423 void AP_CocoaFrame::_setViewFocus(AV_View * /*pView*/)
424 {
425 AP_CocoaFrameImpl * pFrameImpl = static_cast<AP_CocoaFrameImpl *>(getFrameImpl());
426 pFrameImpl->giveFocus();
427 }
428
_bindToolbars(AV_View * pView)429 void AP_CocoaFrame::_bindToolbars(AV_View *pView)
430 {
431 static_cast<AP_CocoaFrameImpl *>(getFrameImpl())->_bindToolbars(pView);
432 }
433
434