~ubuntu-branches/ubuntu/oneiric/apvlv/oneiric

« back to all changes in this revision

Viewing changes to src/ApvlvWindow.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Ritter
  • Date: 2009-07-15 14:48:33 UTC
  • Revision ID: james.westby@ubuntu.com-20090715144833-k4hx9jqtb6vef121
Tags: upstream-0.0.6.8
ImportĀ upstreamĀ versionĀ 0.0.6.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the apvlv package
 
3
 *
 
4
 * Copyright (C) 2008 Alf.
 
5
 *
 
6
 * Contact: Alf <naihe2010@gmail.com>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU General Public License
 
10
 * as published by the Free Software Foundation; either version 2.0 of
 
11
 * the License, or (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful, but
 
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
16
 * General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public
 
19
 * License along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
21
 *
 
22
 */
 
23
/* @CPPFILE ApvlvWindow.cpp
 
24
 *
 
25
 *  Author: Alf <naihe2010@gmail.com>
 
26
 */
 
27
/* @date Created: 2008/09/30 00:00:00 Alf */
 
28
 
 
29
#include "ApvlvView.hpp"
 
30
#include "ApvlvUtil.hpp"
 
31
#include "ApvlvParams.hpp"
 
32
#include "ApvlvDir.hpp"
 
33
#include "ApvlvWindow.hpp"
 
34
 
 
35
#include <gtk/gtk.h>
 
36
 
 
37
#include <string.h>
 
38
 
 
39
namespace apvlv
 
40
{
 
41
  ApvlvWindow *ApvlvWindow::m_curWindow = NULL;
 
42
 
 
43
  ApvlvWindow::ApvlvWindow (ApvlvCore *doc)
 
44
    {
 
45
      mIsClose = false;
 
46
 
 
47
      type = AW_CORE;
 
48
      if (doc == NULL)
 
49
        {
 
50
          mCore = new ApvlvDoc (0, 0, gParams->values ("zoom"));
 
51
        }
 
52
      else
 
53
        {
 
54
          mCore = doc;
 
55
        }
 
56
      m_son = m_daughter = m_parent = NULL;
 
57
    }
 
58
 
 
59
  ApvlvWindow::~ApvlvWindow ()
 
60
    {
 
61
      if (mIsClose)
 
62
        {
 
63
          return;
 
64
        }
 
65
 
 
66
      debug ("delete window: %p", this);
 
67
 
 
68
      mIsClose = true;
 
69
 
 
70
      if (m_parent != NULL)
 
71
        {
 
72
          if (m_parent->m_son == this)
 
73
            {
 
74
              m_parent->m_son = NULL;
 
75
            }
 
76
          else if (m_parent->m_daughter == this)
 
77
            {
 
78
              m_parent->m_daughter = NULL;
 
79
            }
 
80
        }
 
81
 
 
82
      if (type == AW_SP || type == AW_VSP)
 
83
        {
 
84
          if (m_son != NULL)
 
85
            {
 
86
              ApvlvWindow *win = m_son;
 
87
              m_son = NULL;
 
88
              delete win;
 
89
            }
 
90
          if (m_daughter != NULL)
 
91
            {
 
92
              ApvlvWindow *win = m_daughter;
 
93
              m_daughter = NULL;
 
94
              delete win;
 
95
            }
 
96
 
 
97
          g_object_unref (mPaned);
 
98
        }
 
99
    }
 
100
 
 
101
  GtkWidget *
 
102
    ApvlvWindow::widget ()
 
103
      {
 
104
        if (type == AW_CORE)
 
105
          {
 
106
            return mCore->widget ();
 
107
          }
 
108
        else if (type == AW_SP || type == AW_VSP)
 
109
          {
 
110
            return mPaned;
 
111
          }
 
112
        else
 
113
          {
 
114
            errp ("type error: %d", type);
 
115
            return NULL;
 
116
          }
 
117
      }
 
118
 
 
119
  void
 
120
    ApvlvWindow::setcurrentWindow (ApvlvWindow *pre, ApvlvWindow *win)
 
121
      {
 
122
        if (pre) asst (pre->type == AW_CORE);
 
123
        asst (win->type == AW_CORE);
 
124
        if (pre != NULL && pre->type == AW_CORE)
 
125
          {
 
126
            pre->mCore->setactive (false);
 
127
          }
 
128
 
 
129
        if (win->type == AW_CORE)
 
130
          {
 
131
            win->mCore->setactive (true);
 
132
          }
 
133
 
 
134
        m_curWindow = win;
 
135
      }
 
136
 
 
137
  void
 
138
    ApvlvWindow::delcurrentWindow ()
 
139
      {
 
140
        asst (currentWindow ()->istop () == false);
 
141
 
 
142
        ApvlvWindow *crwin = currentWindow ();
 
143
 
 
144
        ApvlvWindow *pwin = crwin->m_parent;
 
145
        ApvlvWindow *child = crwin == pwin->m_son? pwin->m_daughter: pwin->m_son;
 
146
        ApvlvWindow *cwin = pwin->unbirth (crwin, child);
 
147
        setcurrentWindow (NULL, cwin);
 
148
      }
 
149
 
 
150
  ApvlvWindow *
 
151
    ApvlvWindow::currentWindow ()
 
152
      {
 
153
        return m_curWindow;
 
154
      }
 
155
 
 
156
  returnType
 
157
    ApvlvWindow::process (int ct, guint key)
 
158
      {
 
159
        ApvlvWindow *nwin;
 
160
        debug ("input [%d]", key);
 
161
 
 
162
        switch (key)
 
163
          {
 
164
          case CTRL ('w'):
 
165
          case 'k':
 
166
          case 'j':
 
167
          case 'h':
 
168
          case 'l':
 
169
            nwin = getneighbor (ct, key);
 
170
            if (nwin != NULL)
 
171
              {
 
172
                setcurrentWindow (this, nwin);
 
173
              }
 
174
            break;
 
175
 
 
176
          case '-':
 
177
            smaller (ct);
 
178
            break;
 
179
 
 
180
          case '+':
 
181
            bigger (ct);
 
182
            break;
 
183
 
 
184
          default:
 
185
            break;
 
186
          }
 
187
        return MATCH;
 
188
      }
 
189
 
 
190
  ApvlvWindow *
 
191
    ApvlvWindow::getneighbor (int ct, guint key)
 
192
      {
 
193
        switch (key)
 
194
          {
 
195
          case CTRL ('w'):
 
196
            return getnext (ct);
 
197
          case 'k':
 
198
            return getkj (1, false);
 
199
          case 'j':
 
200
            return getkj (1, true);
 
201
          case 'h':
 
202
            return gethl (1, false);
 
203
          case 'l':
 
204
            return gethl (1, true);
 
205
          default:
 
206
            break;
 
207
          }
 
208
 
 
209
        return NULL;
 
210
      }
 
211
 
 
212
  inline ApvlvWindow *
 
213
    ApvlvWindow::getkj (int num, bool down)
 
214
      {
 
215
        ApvlvWindow *cw, *w, *nw, *fw;
 
216
        bool right = false;
 
217
 
 
218
        asst (this && type == AW_CORE);
 
219
        for (cw = fw = NULL, w = this; w != NULL; cw = w, w = w->m_parent)
 
220
          {
 
221
            if (w->type == AW_SP)
 
222
              {
 
223
                if ((cw == w->m_daughter && down == true)
 
224
                    || (cw == w->m_son && down == false))
 
225
                  {
 
226
                    continue;
 
227
                  }
 
228
                else
 
229
                  {
 
230
                    fw = down? w->m_daughter: w->m_son;
 
231
                    break;
 
232
                  }
 
233
              }
 
234
            else if (w->type == AW_VSP)
 
235
              {
 
236
                if (cw != NULL && cw == w->m_daughter)
 
237
                  {
 
238
                    right = true;
 
239
                  }
 
240
                else
 
241
                  {
 
242
                    right = false;
 
243
                  }
 
244
              }
 
245
          }
 
246
 
 
247
        for ( nw = w = fw; w != NULL; )
 
248
          {
 
249
            if (w->type == AW_CORE)
 
250
              {
 
251
                nw = w;
 
252
                break;
 
253
              }
 
254
            else if (w->type == AW_SP)
 
255
              {
 
256
                w = down? w->m_son: w->m_daughter;
 
257
              }
 
258
            else if (w->type == AW_VSP)
 
259
              {
 
260
                w = right? w->m_daughter: w->m_son;
 
261
              }
 
262
            else
 
263
              {
 
264
                debug ("error type: %d", w->type);
 
265
                return NULL;
 
266
              }
 
267
          }
 
268
 
 
269
        return nw;
 
270
      }
 
271
 
 
272
  inline ApvlvWindow *
 
273
    ApvlvWindow::gethl (int num, bool right)
 
274
      {
 
275
        ApvlvWindow *cw, *w, *nw, *fw;
 
276
        bool down = false;
 
277
 
 
278
        asst (this && type == AW_CORE);
 
279
        for (cw = fw = NULL, w = this; w != NULL; cw = w, w = w->m_parent)
 
280
          {
 
281
            if (w->type == AW_VSP)
 
282
              {
 
283
                if ((cw == w->m_daughter && right == true)
 
284
                    || (cw == w->m_son && right == false))
 
285
                  {
 
286
                    continue;
 
287
                  }
 
288
                else
 
289
                  {
 
290
                    fw = right? w->m_daughter: w->m_son;
 
291
                    break;
 
292
                  }
 
293
              }
 
294
            else if (w->type == AW_SP)
 
295
              {
 
296
                if (cw != NULL && cw == w->m_daughter)
 
297
                  {
 
298
                    down = true;
 
299
                  }
 
300
                else
 
301
                  {
 
302
                    down = false;
 
303
                  }
 
304
              }
 
305
          }
 
306
 
 
307
        for ( nw = w = fw; w != NULL; )
 
308
          {
 
309
            if (w->type == AW_CORE)
 
310
              {
 
311
                nw = w;
 
312
                break;
 
313
              }
 
314
            else if (w->type == AW_VSP)
 
315
              {
 
316
                w = right? w->m_son: w->m_daughter;
 
317
              }
 
318
            else if (w->type == AW_SP)
 
319
              {
 
320
                w = down? w->m_daughter: w->m_son;
 
321
              }
 
322
            else
 
323
              {
 
324
                debug ("error type: %d", w->type);
 
325
                return NULL;
 
326
              }
 
327
          }
 
328
 
 
329
        return nw;
 
330
      }
 
331
 
 
332
  ApvlvWindow *
 
333
    ApvlvWindow::getnext (int num)
 
334
      {
 
335
        ApvlvWindow *n = getkj (num, true);
 
336
        if (n == NULL)
 
337
          {
 
338
            n = gethl (num, true);
 
339
            if (n == NULL)
 
340
              {
 
341
                n = gethl (num, false);
 
342
                if (n == NULL)
 
343
                  n = getkj (num, false);
 
344
              }
 
345
          }
 
346
        return n;
 
347
      }
 
348
 
 
349
  // birth a new AW_CORE window, and the new window beyond the input doc
 
350
  // this made a AW_CORE window to AW_SP|AW_VSP
 
351
  ApvlvWindow *
 
352
    ApvlvWindow::birth (bool vsp, ApvlvCore *doc)
 
353
      {
 
354
        asst (type == AW_CORE);
 
355
 
 
356
        if (doc == mCore)
 
357
          {
 
358
            debug ("can't birth with orign doc, copy it");
 
359
            doc = NULL;
 
360
          }
 
361
 
 
362
        if (doc == NULL)
 
363
          {
 
364
            doc = mCore->copy ();
 
365
            gView->regloaded (doc);
 
366
          }
 
367
 
 
368
        ApvlvWindow *nwindow = new ApvlvWindow (doc);
 
369
        nwindow->m_parent = this;
 
370
        m_son = nwindow;
 
371
 
 
372
        ApvlvWindow *nwindow2 = new ApvlvWindow (mCore);
 
373
        nwindow2->m_parent = this;
 
374
        m_daughter = nwindow2;
 
375
 
 
376
        mPaned = vsp == false? gtk_vpaned_new (): gtk_hpaned_new ();
 
377
        g_object_ref (mPaned);
 
378
        g_signal_connect (G_OBJECT (mPaned), "button-release-event", G_CALLBACK (apvlv_window_paned_resized_cb), this);
 
379
 
 
380
        if (m_parent)
 
381
          {
 
382
            void (*panedcb) (GtkPaned *, GtkWidget *);
 
383
            GtkWidget *parent = m_parent->mPaned;
 
384
            if (gtk_paned_get_child1 (GTK_PANED (parent)) == widget ())
 
385
              {
 
386
                panedcb = gtk_paned_add1;
 
387
              }
 
388
            else
 
389
              {
 
390
                panedcb = gtk_paned_add2;
 
391
              }
 
392
 
 
393
            gtk_container_remove (GTK_CONTAINER (parent), widget ());
 
394
            panedcb (GTK_PANED (parent), mPaned);
 
395
          }
 
396
        else
 
397
          {
 
398
            replace_widget (widget (), mPaned);
 
399
          }
 
400
 
 
401
        gtk_paned_pack1 (GTK_PANED (mPaned), nwindow->widget (), TRUE, TRUE);
 
402
        gtk_paned_pack2 (GTK_PANED (mPaned), nwindow2->widget (), TRUE, TRUE);
 
403
 
 
404
        type = vsp == false? AW_SP: AW_VSP;
 
405
        if (type == AW_SP)
 
406
          {
 
407
            nwindow->setsize (mWidth, mHeight / 2);
 
408
            nwindow2->setsize (mWidth, mHeight / 2);
 
409
          }
 
410
        else if (type == AW_VSP)
 
411
          {
 
412
            nwindow->setsize (mWidth / 2, mHeight);
 
413
            nwindow2->setsize (mWidth / 2, mHeight);
 
414
          }
 
415
 
 
416
        gtk_widget_show_all (mPaned);
 
417
 
 
418
        setcurrentWindow (nwindow2, nwindow);
 
419
        return nwindow;
 
420
      }
 
421
 
 
422
  // unbirth a child
 
423
  // @param 1, be delete
 
424
  // @param 2, be unbirth, that is up to the parent
 
425
  // return the new child
 
426
  ApvlvWindow *
 
427
    ApvlvWindow::unbirth (ApvlvWindow *dead, ApvlvWindow *child)
 
428
      {
 
429
        asst (type == AW_SP || type == AW_VSP);
 
430
 
 
431
        if (m_parent)
 
432
          {
 
433
            void (*panedcb) (GtkPaned *, GtkWidget *);
 
434
            GtkWidget *parent = m_parent->mPaned;
 
435
            if (gtk_paned_get_child1 (GTK_PANED (parent)) == mPaned)
 
436
              {
 
437
                panedcb = gtk_paned_add1;
 
438
              }
 
439
            else
 
440
              {
 
441
                panedcb = gtk_paned_add2;
 
442
              }
 
443
 
 
444
            gtk_container_remove (GTK_CONTAINER (mPaned), child->widget ());
 
445
            gtk_container_remove (GTK_CONTAINER (parent), mPaned);
 
446
            panedcb (GTK_PANED (parent), child->widget ());
 
447
          }
 
448
        else
 
449
          {
 
450
            gtk_container_remove (GTK_CONTAINER (mPaned), child->widget ());
 
451
            replace_widget (mPaned, child->widget ());
 
452
          }
 
453
 
 
454
        if (child->type == AW_CORE)
 
455
          {
 
456
            ApvlvCore *doc = child->getCore ();
 
457
            type = AW_CORE;
 
458
            mCore = doc;
 
459
          }
 
460
        else if (child->type == AW_SP || child->type == AW_VSP)
 
461
          {
 
462
            type = child->type;
 
463
            mPaned = child->mPaned;
 
464
            m_son = child->m_son;
 
465
            m_son->m_parent = this;
 
466
            m_daughter = child->m_daughter;
 
467
            m_daughter->m_parent = this;
 
468
            child->type = AW_NONE;
 
469
          }
 
470
 
 
471
        gtk_widget_show_all (widget ());
 
472
 
 
473
        if (dead != NULL)
 
474
          delete dead;
 
475
        if (child != NULL)
 
476
          delete child;
 
477
 
 
478
        ApvlvWindow *win;
 
479
        for (win = this; win->type != AW_CORE; win = win->m_son);
 
480
 
 
481
        return win;
 
482
      }
 
483
 
 
484
  bool
 
485
    ApvlvWindow::istop ()
 
486
      {
 
487
        return m_parent == NULL? true: false;
 
488
      }
 
489
 
 
490
  void
 
491
    ApvlvWindow::getsize (int *width, int *height)
 
492
      {
 
493
        if (width)
 
494
          {
 
495
            *width = mWidth;
 
496
          }
 
497
        if (height)
 
498
          {
 
499
            *height = mHeight;
 
500
          }
 
501
      }
 
502
 
 
503
  void
 
504
    ApvlvWindow::setsize (int width, int height)
 
505
      {
 
506
        mWidth = width;
 
507
        mHeight = height;
 
508
        debug ("mWidth: %d, mHeight: %d", mWidth, mHeight);
 
509
 
 
510
        if (type == AW_CORE)
 
511
          {
 
512
            mCore->setsize (mWidth, mHeight);
 
513
          }
 
514
        else if (type == AW_SP
 
515
                 || type == AW_VSP)
 
516
          {
 
517
            g_timeout_add (50, apvlv_window_resize_children_cb, this);
 
518
          }
 
519
      }
 
520
 
 
521
  void
 
522
    ApvlvWindow::setCore (ApvlvCore *doc)
 
523
      {
 
524
        debug ("widget (): %p, doc->widget (): %p", widget (), doc->widget ());
 
525
        if (type == AW_CORE)
 
526
          {
 
527
            mCore->inuse (false);
 
528
          }
 
529
        replace_widget (widget (), doc->widget ());
 
530
        doc->inuse (true);
 
531
        type = AW_CORE;
 
532
        mCore = doc;
 
533
      }
 
534
 
 
535
  ApvlvCore *
 
536
    ApvlvWindow::getCore ()
 
537
      {
 
538
        asst (type == AW_CORE);
 
539
        ApvlvCore *rdoc = mCore;
 
540
        return rdoc;
 
541
      }
 
542
 
 
543
  void
 
544
    ApvlvWindow::smaller (int times)
 
545
      {
 
546
        if (m_parent == NULL) return;
 
547
 
 
548
        int val = gtk_paned_get_position (GTK_PANED (m_parent->mPaned));
 
549
        int len = 20 * times;
 
550
        m_parent->m_son == this? val -= len: val += len;
 
551
        gtk_paned_set_position (GTK_PANED (m_parent->mPaned), val);
 
552
 
 
553
        m_parent->resize_children ();
 
554
      }
 
555
 
 
556
  void
 
557
    ApvlvWindow::bigger (int times)
 
558
      {
 
559
        if (m_parent == NULL) return;
 
560
 
 
561
        int val = gtk_paned_get_position (GTK_PANED (m_parent->mPaned));
 
562
        int len = 20 * times;
 
563
        m_parent->m_son == this? val += len: val -= len;
 
564
        gtk_paned_set_position (GTK_PANED (m_parent->mPaned), val);
 
565
 
 
566
        m_parent->resize_children ();
 
567
      }
 
568
 
 
569
  gboolean
 
570
    ApvlvWindow::apvlv_window_paned_resized_cb (GtkWidget   *wid,
 
571
                                                GdkEventButton *but,
 
572
                                                ApvlvWindow *win)
 
573
      {
 
574
        win->resize_children ();
 
575
        return FALSE;
 
576
      }
 
577
 
 
578
  gboolean
 
579
    ApvlvWindow::resize_children ()
 
580
      {
 
581
        int mw1 = mWidth, mw2 = mWidth, mh1 = mHeight, mh2 = mHeight;
 
582
        int mi = GTK_PANED (mPaned)->min_position;
 
583
        int ma = GTK_PANED (mPaned)->max_position;
 
584
        int mv = gtk_paned_get_position (GTK_PANED (mPaned));
 
585
 
 
586
        int ms = ma - mi;
 
587
        if (ms != 0)
 
588
          {
 
589
            if (type == AW_SP)
 
590
              {
 
591
                mh1 = (mHeight * (mv - mi)) / ms;
 
592
                mh2 = mHeight - mh1;
 
593
              }
 
594
            else if (type == AW_VSP)
 
595
              {
 
596
                mw1 = (mWidth * (mv - mi)) / ms;
 
597
                mw2 = mWidth - mw1;
 
598
              }
 
599
 
 
600
            m_son->setsize (mw1, mh1);
 
601
            m_daughter->setsize (mw2, mh2);
 
602
 
 
603
            return TRUE;
 
604
          }
 
605
        else
 
606
          {
 
607
            return FALSE;
 
608
          }
 
609
      }
 
610
 
 
611
  gboolean
 
612
    ApvlvWindow::apvlv_window_resize_children_cb (gpointer data)
 
613
      {
 
614
        ApvlvWindow *win = (ApvlvWindow *) data;
 
615
        return win->resize_children () == TRUE? FALSE: FALSE;
 
616
      }
 
617
}