~ubuntu-branches/ubuntu/quantal/gnome-documents/quantal

« back to all changes in this revision

Viewing changes to src/searchbar.js

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2012-08-07 22:03:19 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20120807220319-cwvu1sb3x9lo9osb
Tags: 0.5.5-0ubuntu1
* New upstream release.
* debian/control.in:
  - Bump minimum libgdata 
  - Drop explicit liboauth-dev from build-depends to match
    configure.ac change

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
const Gd = imports.gi.Gd;
23
23
const Gdk = imports.gi.Gdk;
 
24
const GLib = imports.gi.GLib;
24
25
const Gtk = imports.gi.Gtk;
25
26
const GtkClutter = imports.gi.GtkClutter;
26
27
const Tracker = imports.gi.Tracker;
246
247
    Name: 'SearchController',
247
248
 
248
249
    _init: function() {
249
 
        this._dropdownState = false;
250
250
        this._string = '';
251
251
    },
252
252
 
265
265
    getTerms: function() {
266
266
        let str = Tracker.sparql_escape_string(this._string);
267
267
        return str.replace(/ +/g, ' ').split(' ');
268
 
    },
269
 
 
270
 
    setDropdownState: function(state) {
271
 
        if (this._dropdownState == state)
272
 
            return;
273
 
 
274
 
        this._dropdownState = state;
275
 
        this.emit('search-dropdown-changed', this._dropdownState);
276
 
    },
277
 
 
278
 
    getDropdownState: function() {
279
 
        return this._dropdownState;
280
268
    }
281
269
});
282
270
Signals.addSignalMethods(SearchController.prototype);
283
271
 
 
272
const Searchbar = new Lang.Class({
 
273
    Name: 'Searchbar',
 
274
 
 
275
    _init: function() {
 
276
        this._searchEntryTimeout = 0;
 
277
        this._searchTypeId = 0;
 
278
        this._searchMatchId = 0;
 
279
 
 
280
        this._in = false;
 
281
 
 
282
        this.widget = new Gtk.Toolbar();
 
283
        this.widget.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
 
284
 
 
285
        this.actor = new GtkClutter.Actor({ contents: this.widget,
 
286
                                            height: 0 });
 
287
 
 
288
        // subclasses will create this._searchEntry and this._searchContainer
 
289
        // GtkWidgets
 
290
        this.createSearchWidgets();
 
291
 
 
292
        let item = new Gtk.ToolItem();
 
293
        item.set_expand(true);
 
294
        item.add(this._searchContainer);
 
295
        this.widget.insert(item, 0);
 
296
 
 
297
        this._searchEntry.connect('key-press-event', Lang.bind(this,
 
298
            function(widget, event) {
 
299
                let keyval = event.get_keyval()[1];
 
300
 
 
301
                if (keyval == Gdk.KEY_Escape) {
 
302
                    Global.application.change_action_state('search', GLib.Variant.new('b', false));
 
303
                    return true;
 
304
                }
 
305
 
 
306
                return false;
 
307
            }));
 
308
 
 
309
        this._searchEntry.connect('changed', Lang.bind(this,
 
310
            function() {
 
311
                if (this._searchEntryTimeout != 0) {
 
312
                    Mainloop.source_remove(this._searchEntryTimeout);
 
313
                    this._searchEntryTimeout = 0;
 
314
                }
 
315
 
 
316
                this._searchEntryTimeout = Mainloop.timeout_add(_SEARCH_ENTRY_TIMEOUT, Lang.bind(this,
 
317
                    function() {
 
318
                        this._searchEntryTimeout = 0;
 
319
                        this.entryChanged();
 
320
                    }));
 
321
            }));
 
322
 
 
323
        // connect to the search action state for visibility
 
324
        let searchStateId = Global.application.connect('action-state-changed::search', Lang.bind(this,
 
325
            function(source, actionName, state) {
 
326
                if (state.get_boolean())
 
327
                    this.show();
 
328
                else
 
329
                    this.hide();
 
330
            }));
 
331
        this.widget.connect('destroy', Lang.bind(this,
 
332
            function() {
 
333
                Global.application.disconnect(searchStateId);
 
334
                Global.application.change_action_state('search', GLib.Variant.new('b', false));
 
335
            }));
 
336
 
 
337
        this.widget.show_all();
 
338
    },
 
339
 
 
340
    createSearchWidgets: function() {
 
341
        log('Error: Searchbar implementations must override createSearchWidgets');
 
342
    },
 
343
 
 
344
    entryChanged: function() {
 
345
        log('Error: Searchbar implementations must override entryChanged');
 
346
    },
 
347
 
 
348
    destroy: function() {
 
349
        this.widget.destroy();
 
350
    },
 
351
 
 
352
    handleEvent: function(event) {
 
353
        if (this._in)
 
354
            return false;
 
355
 
 
356
        if (!this._searchEntry.get_realized())
 
357
            this._searchEntry.realize();
 
358
 
 
359
        let handled = false;
 
360
 
 
361
        let preeditChanged = false;
 
362
        let preeditChangedId =
 
363
            this._searchEntry.connect('preedit-changed', Lang.bind(this,
 
364
                function() {
 
365
                    preeditChanged = true;
 
366
                }));
 
367
 
 
368
        let oldText = this._searchEntry.get_text();
 
369
        let res = this._searchEntry.event(event);
 
370
        let newText = this._searchEntry.get_text();
 
371
 
 
372
        this._searchEntry.disconnect(preeditChangedId);
 
373
 
 
374
        if (((res && (newText != oldText)) || preeditChanged)) {
 
375
            handled = true;
 
376
 
 
377
            if (!this._in)
 
378
                Global.application.change_action_state('search', GLib.Variant.new('b', true));
 
379
        }
 
380
 
 
381
        return handled;
 
382
    },
 
383
 
 
384
    show: function() {
 
385
        let eventDevice = Gtk.get_current_event_device();
 
386
        this._searchEntry.show();
 
387
 
 
388
        Tweener.addTween(this.actor, { height: this.widget.get_preferred_height()[1],
 
389
                                       time: 0.20,
 
390
                                       transition: 'easeOutQuad',
 
391
                                       onComplete: function() {
 
392
                                           this._in = true;
 
393
                                           Gd.entry_focus_hack(this._searchEntry, eventDevice);
 
394
                                       },
 
395
                                       onCompleteScope: this });
 
396
    },
 
397
 
 
398
    hide: function() {
 
399
        Tweener.addTween(this.actor, { height: 0,
 
400
                                       time: 0.20,
 
401
                                       transition: 'easeOutQuad',
 
402
                                       onComplete: function() {
 
403
                                           this._searchEntry.hide();
 
404
                                           this._in = false;
 
405
                                       },
 
406
                                       onCompleteScope: this });
 
407
    }
 
408
});
 
409
 
284
410
const Dropdown = new Lang.Class({
285
411
    Name: 'Dropdown',
286
412
 
313
439
        this._grid.add(this._matchView.widget);
314
440
        //this._grid.add(this._categoryView.widget);
315
441
 
316
 
        this.widget.show_all();
317
 
 
318
 
        Global.searchController.connect('search-dropdown-changed',
319
 
                                        Lang.bind(this, this._onSearchDropdown));
320
 
        this._onSearchDropdown();
 
442
        this.hide();
321
443
    },
322
444
 
323
445
    _onItemActivated: function() {
324
 
        Global.searchController.setDropdownState(false);
325
 
    },
326
 
 
327
 
    _onSearchDropdown: function() {
328
 
        let state = Global.searchController.getDropdownState();
329
 
        if (state)
330
 
            this._fadeIn();
331
 
        else
332
 
            this._fadeOut();
333
 
    },
334
 
 
335
 
    _fadeIn: function() {
 
446
        this.emit('item-activated');
 
447
    },
 
448
 
 
449
    show: function() {
 
450
        this.widget.show_all();
336
451
        this.actor.raise_top();
337
452
        Tweener.addTween(this.actor, { opacity: 245,
338
453
                                       time: 0.20,
339
454
                                       transition: 'easeOutQuad' });
340
455
    },
341
456
 
342
 
    _fadeOut: function() {
 
457
    hide: function() {
 
458
        this.widget.hide();
343
459
        Tweener.addTween(this.actor, { opacity: 0,
344
460
                                       time: 0.20,
345
461
                                       transition: 'easeOutQuad',
349
465
                                       onCompleteScope: this });
350
466
    }
351
467
});
352
 
 
353
 
const Searchbar = new Lang.Class({
354
 
    Name: 'Searchbar',
355
 
 
356
 
    _init: function() {
357
 
        this._searchEventId = 0;
358
 
        this._searchFocusId = 0;
359
 
        this._searchEntryTimeout = 0;
360
 
        this._sourcesId = 0;
361
 
        this._searchTypeId = 0;
362
 
        this._searchMatchId = 0;
363
 
 
364
 
        this._in = false;
365
 
        this._visible = false;
366
 
 
367
 
        this.widget = new Gtk.Toolbar();
368
 
        this.widget.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
369
 
 
370
 
        this.actor = new GtkClutter.Actor({ contents: this.widget,
371
 
                                            height: 0 });
372
 
 
373
 
        this._searchEntry = new Gd.TaggedEntry({ width_request: 260,
374
 
                                                 no_show_all: true,
375
 
                                                 hexpand: true });
376
 
        this._searchEntry.connect('tag-clicked',
377
 
            Lang.bind(this, this._onTagClicked));
 
468
Signals.addSignalMethods(Dropdown.prototype);
 
469
 
 
470
const OverviewSearchbar = new Lang.Class({
 
471
    Name: 'OverviewSearchbar',
 
472
    Extends: Searchbar,
 
473
 
 
474
    _init: function(dropdown) {
 
475
        this._dropdown = dropdown;
 
476
 
 
477
        this.parent();
378
478
 
379
479
        this._sourcesId = Global.sourceManager.connect('active-changed',
380
480
            Lang.bind(this, this._onActiveSourceChanged));
388
488
        this._onActiveSourceChanged();
389
489
        this._onActiveTypeChanged();
390
490
        this._onActiveMatchChanged();
391
 
 
392
 
        let box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });
393
 
        box.add(this._searchEntry);
394
 
 
 
491
    },
 
492
 
 
493
    createSearchWidgets: function() {
 
494
        this._searchContainer = new Gd.MarginContainer({ min_margin: 6,
 
495
                                                         max_margin: 64 });
 
496
        this._box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });
 
497
        this._searchContainer.add(this._box);
 
498
 
 
499
        // create the search entry
 
500
        this._searchEntry = new Gd.TaggedEntry({ width_request: 260,
 
501
                                                 no_show_all: true,
 
502
                                                 hexpand: true });
 
503
        this._searchEntry.connect('tag-clicked',
 
504
            Lang.bind(this, this._onTagClicked));
 
505
        this._searchEntry.set_text(Global.searchController.getString());
 
506
 
 
507
        // create the dropdown button
395
508
        this._dropdownButton = new Gtk.ToggleButton(
396
509
            { child: new Gtk.Arrow({ arrow_type: Gtk.ArrowType.DOWN }) });
397
510
        this._dropdownButton.connect('toggled', Lang.bind(this,
398
511
            function() {
399
512
                let active = this._dropdownButton.get_active();
400
 
                Global.searchController.setDropdownState(active);
401
 
            }));
402
 
 
403
 
        box.add(this._dropdownButton);
404
 
 
405
 
        this._searchDropdownId = Global.searchController.connect('search-dropdown-changed',
406
 
            Lang.bind(this, this._onDropdownStateChanged));
407
 
 
408
 
        let container = new Gd.MarginContainer({ min_margin: 6,
409
 
                                                 max_margin: 64 });
410
 
        container.add(box);
411
 
 
412
 
        let item = new Gtk.ToolItem();
413
 
        item.set_expand(true);
414
 
        item.add(container);
415
 
 
416
 
        this._searchEntry.connect('key-press-event', Lang.bind(this,
417
 
            function(widget, event) {
418
 
                let keyval = event.get_keyval()[1];
419
 
 
420
 
                if (keyval == Gdk.KEY_Escape) {
421
 
                    this.hide();
422
 
                    return true;
423
 
                }
424
 
 
425
 
                return false;
426
 
            }));
427
 
 
428
 
        this._searchEntry.connect('changed', Lang.bind(this, function() {
429
 
            if (this._searchEntryTimeout != 0) {
430
 
                Mainloop.source_remove(this._searchEntryTimeout);
431
 
                this._searchEntryTimeout = 0;
432
 
            }
433
 
 
434
 
            this._searchEntryTimeout = Mainloop.timeout_add(_SEARCH_ENTRY_TIMEOUT, Lang.bind(this,
435
 
                function() {
436
 
                    this._searchEntryTimeout = 0;
437
 
 
438
 
                    let currentText = this._searchEntry.get_text().toLowerCase();
439
 
                    Global.searchController.setString(currentText);
440
 
            }));
441
 
        }));
442
 
 
443
 
        this.widget.insert(item, 0);
444
 
        this._searchEntry.set_text(Global.searchController.getString());
445
 
 
446
 
        this.widget.show_all();
 
513
                if (active)
 
514
                    this._dropdown.show();
 
515
                else
 
516
                    this._dropdown.hide();
 
517
            }));
 
518
        this._dropdown.connect('item-activated', Lang.bind(this,
 
519
            function() {
 
520
                this._dropdownButton.set_active(false);
 
521
            }));
 
522
 
 
523
        this._box.add(this._searchEntry);
 
524
        this._box.add(this._dropdownButton);
 
525
        this._box.show_all();
 
526
    },
 
527
 
 
528
    entryChanged: function() {
 
529
        let currentText = this._searchEntry.get_text().toLowerCase();
 
530
        Global.searchController.setString(currentText);
447
531
    },
448
532
 
449
533
    _onActiveCollectionChanged: function() {
456
540
        }
457
541
    },
458
542
 
459
 
    destroy: function() {
460
 
        if (this._searchFocusId != 0) {
461
 
            Global.searchController.disconnect(this._searchFocusId);
462
 
            this._searchFocusId = 0;
463
 
        }
464
 
 
465
 
        if (this._searchEventId != 0) {
466
 
            Global.searchController.disconnect(this._searchEventId);
467
 
            this._searchEventId = 0;
468
 
        }
469
 
 
470
 
        if (this._sourcesId != 0) {
471
 
            Global.sourceManager.disconnect(this._sourcesId);
472
 
            this._sourcesId = 0;
473
 
        }
474
 
 
475
 
        if (this._searchTypeId != 0) {
476
 
            Global.searchTypeManager.disconnect(this._searchTypeId);
477
 
            this._searchTypeId = 0;
478
 
        }
479
 
 
480
 
        if (this._searchMatchId != 0) {
481
 
            Global.searchMatchManager.disconnect(this._searchMatchId);
482
 
            this._searchMatchId = 0;
483
 
        }
484
 
 
485
 
        if (this._searchDropdownId != 0) {
486
 
            Global.searchController.disconnect(this._searchDropdownId);
487
 
            this._searchDropdownId = 0;
488
 
        }
489
 
 
490
 
        if (this._collectionId != 0) {
491
 
            Global.searchController.disconnect(this._collectionId);
492
 
            this._collectionId = 0;
493
 
        }
494
 
 
495
 
        this.widget.destroy();
496
 
    },
497
 
 
498
 
    _onTagClicked: function() {
499
 
        this._dropdownButton.set_active(true);
500
 
    },
501
 
 
502
543
    _onActiveChangedCommon: function(id, manager) {
503
544
        let item = manager.getActiveItem();
504
545
 
530
571
        this._onActiveChangedCommon('match', Global.searchMatchManager);
531
572
    },
532
573
 
533
 
    _onDropdownStateChanged: function() {
534
 
        let state = Global.searchController.getDropdownState();
535
 
        this._dropdownButton.set_active(state);
536
 
    },
537
 
 
538
 
    deliverEvent: function(event) {
539
 
        if (this._in)
540
 
            return false;
541
 
 
542
 
        if (!this._searchEntry.get_realized())
543
 
            this._searchEntry.realize();
544
 
 
545
 
        let handled = false;
546
 
 
547
 
        let preeditChanged = false;
548
 
        let preeditChangedId =
549
 
            this._searchEntry.connect('preedit-changed', Lang.bind(this,
550
 
                function() {
551
 
                    preeditChanged = true;
552
 
                }));
553
 
 
554
 
        let oldText = this._searchEntry.get_text();
555
 
        let res = this._searchEntry.event(event);
556
 
        let newText = this._searchEntry.get_text();
557
 
 
558
 
        this._searchEntry.disconnect(preeditChangedId);
559
 
 
560
 
        if (((res && (newText != oldText)) || preeditChanged)) {
561
 
            handled = true;
562
 
 
563
 
            if (!this._in)
564
 
                this.show();
565
 
        }
566
 
 
567
 
        return handled;
568
 
    },
569
 
 
570
 
    toggle: function() {
571
 
        if (this._visible)
572
 
            this.hide();
573
 
        else
574
 
            this.show();
575
 
    },
576
 
 
577
 
    show: function() {
578
 
        let eventDevice = Gtk.get_current_event_device();
579
 
 
580
 
        this._visible = true;
581
 
        this._searchEntry.show();
582
 
 
583
 
        Tweener.addTween(this.actor, { height: this.widget.get_preferred_height()[1],
584
 
                                       time: 0.20,
585
 
                                       transition: 'easeOutQuad',
586
 
                                       onComplete: function() {
587
 
                                           this._in = true;
588
 
                                           Gd.entry_focus_hack(this._searchEntry, eventDevice);
589
 
                                       },
590
 
                                       onCompleteScope: this });
 
574
    _onTagClicked: function() {
 
575
        this._dropdownButton.set_active(true);
 
576
    },
 
577
 
 
578
    destroy: function() {
 
579
        if (this._sourcesId != 0) {
 
580
            Global.sourceManager.disconnect(this._sourcesId);
 
581
            this._sourcesId = 0;
 
582
        }
 
583
 
 
584
        if (this._searchTypeId != 0) {
 
585
            Global.searchTypeManager.disconnect(this._searchTypeId);
 
586
            this._searchTypeId = 0;
 
587
        }
 
588
 
 
589
        if (this._searchMatchId != 0) {
 
590
            Global.searchMatchManager.disconnect(this._searchMatchId);
 
591
            this._searchMatchId = 0;
 
592
        }
 
593
 
 
594
        if (this._collectionId != 0) {
 
595
            Global.collectionManager.disconnect(this._collectionId);
 
596
            this._collectionId = 0;
 
597
        }
 
598
 
 
599
        this.parent();
591
600
    },
592
601
 
593
602
    hide: function() {
594
603
        this._dropdownButton.set_active(false);
595
 
        this._visible = false;
596
 
 
597
 
        Tweener.addTween(this.actor, { height: 0,
598
 
                                       time: 0.20,
599
 
                                       transition: 'easeOutQuad',
600
 
                                       onComplete: function() {
601
 
                                           this._searchEntry.hide();
602
 
                                           this._in = false;
603
 
                                       },
604
 
                                       onCompleteScope: this });
 
604
        this.parent();
605
605
    }
606
606
});