Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 8th, 2012  |  syntax: Vala  |  size: 24.78 KB  |  hits: 23  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
  2. //
  3. //  Copyright (C) 2011 Giulio Collura
  4. //
  5. //  This program is free software: you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation, either version 3 of the License, or
  8. //  (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, see <http://www.gnu.org/licenses/>.
  17. //
  18.  
  19. using Gtk;
  20. using Gee;
  21. using Cairo;
  22. using Granite.Widgets;
  23. using GMenu;
  24.  
  25. using Slingshot.Widgets;
  26. using Slingshot.Backend;
  27.  
  28. namespace Slingshot {
  29.  
  30.     public enum Modality {
  31.         NORMAL_VIEW = 0,
  32.         CATEGORY_VIEW = 1,
  33.         SEARCH_VIEW
  34.     }
  35.  
  36.     public class SlingshotView : PopOver {
  37.  
  38.         // Widgets
  39.         public SearchBar searchbar;
  40.         public Layout view_manager;
  41.         public Switcher page_switcher;
  42.         public ModeButton view_selector;
  43.  
  44.         // Views
  45.         private Widgets.Grid grid_view;
  46.         private SearchView search_view;
  47.         private CategoryView category_view;
  48.  
  49.         public Gtk.Grid top;
  50.         public Gtk.Grid center;
  51.         public Gtk.Grid bottom;
  52.         public Gtk.Grid container;
  53.  
  54.         public AppSystem app_system;
  55.         private ArrayList<TreeDirectory> categories;
  56.         public HashMap<string, ArrayList<App>> apps;
  57.  
  58.         private int current_position = 0;
  59.         private int search_view_position = 0;
  60.         private Modality modality;
  61.  
  62.         // Sizes
  63.         public int columns {
  64.             get {
  65.                 return grid_view.get_page_columns ();
  66.             }
  67.         }
  68.         public int rows {
  69.             get {
  70.                 return grid_view.get_page_rows ();
  71.             }
  72.         }
  73.         private int default_columns;
  74.         private int default_rows;
  75.  
  76.         public int view_height {
  77.             get {
  78.                 return (int) (rows*130 + rows*grid_view.row_spacing + 35);
  79.             }
  80.         }
  81.  
  82.         public SlingshotView () {
  83.  
  84.             // Window properties
  85.             this.title = "Slingshot";
  86.             this.skip_pager_hint = true;
  87.             this.skip_taskbar_hint = true;
  88.             set_keep_above (true);
  89.  
  90.             // Have the window in the right place
  91.             read_settings (true);
  92.  
  93.             Slingshot.icon_theme = IconTheme.get_default ();
  94.  
  95.             app_system = new AppSystem ();
  96.  
  97.             categories = app_system.get_categories ();
  98.             apps = app_system.get_apps ();
  99.            
  100.             if (Slingshot.settings.screen_resolution != @"$(screen.get_width ())x$(screen.get_height ())")
  101.                 setup_size ();
  102.             height_request = default_rows * 145 + 180;
  103.             setup_ui ();
  104.             connect_signals ();
  105.  
  106.             debug ("Apps loaded");
  107.  
  108.         }
  109.        
  110.         private void setup_size () {
  111.        
  112.             debug ("In setup_size ()");
  113.             Slingshot.settings.screen_resolution = @"$(screen.get_width ())x$(screen.get_height ())";
  114.             while ((default_columns*130 +48 >= 2*screen.get_width ()/3)) {
  115.                 default_columns--;
  116.             }
  117.            
  118.             while ((default_rows*145 + 72 >= 2*screen.get_height ()/3)) {
  119.                 default_rows--;
  120.             }
  121.             Slingshot.settings.columns = default_columns;
  122.             Slingshot.settings.rows = default_rows;
  123.         }
  124.  
  125.         private void setup_ui () {
  126.  
  127.             debug ("In setup_ui ()");
  128.  
  129.             // Create the base container
  130.             container = new Gtk.Grid ();
  131.  
  132.             // Add top bar
  133.             top = new Gtk.Grid ();
  134.            
  135.             var top_separator = new Label (""); // A fake label
  136.             top_separator.set_hexpand(true);
  137.  
  138.             view_selector = new ModeButton ();
  139.             view_selector.append (new Image.from_icon_name ("slingshot-view-list-icons-symbolic", IconSize.MENU));
  140.             view_selector.append (new Image.from_icon_name ("slingshot-view-list-filter-symbolic", IconSize.MENU));
  141.             if (Slingshot.settings.use_category)
  142.                 view_selector.selected = 1;
  143.             else
  144.                 view_selector.selected = 0;
  145.  
  146.             searchbar = new SearchBar (_("Search Apps..."));
  147.             searchbar.pause_delay = 200;
  148.             searchbar.width_request = 250;
  149.  
  150.             if (Slingshot.settings.show_category_filter) {
  151.                 top.attach (view_selector, 0, 0, 1, 1);
  152.             }
  153.             top.attach (top_separator, 1, 0, 1, 1);
  154.             top.attach (searchbar, 2, 0, 1, 1);
  155.  
  156.             center = new Gtk.Grid ();
  157.             // Create the layout which works like view_manager
  158.             view_manager = new Layout (null, null);
  159.             view_manager.set_size_request (default_columns*130, default_rows*145);
  160.             center.attach (view_manager, 0, 0, 1, 1);
  161.  
  162.             // Create the "NORMAL_VIEW"
  163.             grid_view = new Widgets.Grid (default_rows, default_columns);
  164.             view_manager.put (grid_view, 0, 0);
  165.  
  166.             // Create the "SEARCH_VIEW"
  167.             search_view = new SearchView (this);
  168.             foreach (ArrayList<App> app_list in apps.values) {
  169.                 search_view.add_apps (app_list);
  170.             }
  171.             view_manager.put (search_view, -columns*130, 0);
  172.  
  173.             // Create the "CATEGORY_VIEW"
  174.             category_view = new CategoryView (this);
  175.             view_manager.put (category_view, -columns*130, 0);
  176.  
  177.             // Create the page switcher
  178.             page_switcher = new Switcher ();
  179.  
  180.             // A bottom widget to keep the page switcher center
  181.             bottom = new Gtk.Grid ();
  182.            
  183.            
  184.             var bottom_separator1 = new Label (""); // A fake label
  185.             bottom_separator1.set_hexpand(true);
  186.             var bottom_separator2 = new Label (""); // A fake label
  187.             bottom_separator2.set_hexpand(true);
  188.             bottom.attach (bottom_separator1, 0, 0, 1, 1); // A fake label
  189.             bottom.attach (page_switcher, 1, 0, 1, 1);
  190.             bottom.attach (bottom_separator2, 2, 0, 1, 1); // A fake label
  191.  
  192.             container.attach (Utils.set_padding (top, 12, 12, 12, 12), 0, 0, 1, 1);
  193.             container.attach (Utils.set_padding (center, 0, 12, 12, 12), 0, 1, 1, 1);
  194.             container.attach (Utils.set_padding (bottom, 0, 24, 12, 24), 0, 2, 1, 1);
  195.  
  196.             // Add the container to the dialog's content area
  197.             var content_area = get_content_area () as Box;
  198.             content_area.pack_start (container);
  199.  
  200.             if (Slingshot.settings.use_category)
  201.                 set_modality (Modality.CATEGORY_VIEW);
  202.             else
  203.                 set_modality (Modality.NORMAL_VIEW);
  204.             debug ("Ui setup completed");
  205.  
  206.         }
  207.  
  208.         private void connect_signals () {
  209.  
  210.             this.focus_out_event.connect (() => {
  211.                 this.hide_slingshot();
  212.                 return false;
  213.             });
  214.  
  215.             this.focus_in_event.connect (() => {
  216.                 searchbar.grab_focus ();
  217.                 return false;
  218.             });
  219.  
  220.             //view_manager.draw.connect (this.draw_background);
  221.  
  222.             searchbar.text_changed_pause.connect ((text) => this.search (text.down ().strip ()));
  223.             searchbar.grab_focus ();
  224.  
  225.             search_view.app_launched.connect (destroy_slingshot);
  226.  
  227.             // This function must be after creating the page switcher
  228.             grid_view.new_page.connect (page_switcher.append);
  229.             populate_grid_view ();
  230.  
  231.             page_switcher.active_changed.connect (() => {
  232.  
  233.                 if (page_switcher.active > page_switcher.old_active)
  234.                     this.page_right (page_switcher.active - page_switcher.old_active);
  235.                 else
  236.                     this.page_left (page_switcher.old_active - page_switcher.active);
  237.  
  238.             });
  239.  
  240.             view_selector.mode_changed.connect (() => {
  241.  
  242.                 set_modality ((Modality) view_selector.selected);
  243.             });
  244.  
  245.             // Auto-update settings when changed
  246.             //Slingshot.settings.changed.connect (() => read_settings ());
  247.  
  248.             // Auto-update applications grid
  249.             app_system.changed.connect (() => {
  250.  
  251.                 categories = app_system.get_categories ();
  252.                 apps = app_system.get_apps ();
  253.  
  254.                 populate_grid_view ();
  255.  
  256.             });
  257.  
  258.             // position on the right monitor when settings changed
  259.             screen.size_changed.connect (() => {
  260.                 reposition ();
  261.             });
  262.             screen.monitors_changed.connect (() => {
  263.                 reposition ();
  264.             });
  265.  
  266.         }
  267.  
  268.         private void reposition () {
  269.  
  270.             debug("Repositioning");
  271.  
  272.             if (Slingshot.settings.open_on_mouse)
  273.                 window_position = WindowPosition.MOUSE;
  274.             else {
  275.                 Gdk.Rectangle monitor_dimensions;
  276.                 screen.get_monitor_geometry (this.screen.get_primary_monitor(), out monitor_dimensions);
  277.  
  278.                 move_to_coords (monitor_dimensions.x, monitor_dimensions.y); //this would be coordinates 0,0 on the screen
  279.             }
  280.         }
  281.  
  282.         public override bool key_press_event (Gdk.EventKey event) {
  283.  
  284.             switch (Gdk.keyval_name (event.keyval)) {
  285.  
  286.                 case "Escape":
  287.                     hide_slingshot ();
  288.                     return true;
  289.  
  290.                 case "Return":
  291.                     if (modality == Modality.SEARCH_VIEW) {
  292.                         search_view.launch_selected ();
  293.                         destroy_slingshot ();
  294.                     }
  295.                     return true;
  296.  
  297.                 case "Alt":
  298.                     break;
  299.  
  300.                 case "Tab":
  301.                     if (modality == Modality.NORMAL_VIEW)
  302.                         view_selector.selected = 1;
  303.                     else if (modality == Modality.CATEGORY_VIEW)
  304.                         view_selector.selected = 0;
  305.                     break;
  306.  
  307.                 case "1":
  308.                 case "KP_1":
  309.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  310.                         page_switcher.set_active (0);
  311.                     else if (modality == Modality.CATEGORY_VIEW)
  312.                         category_view.switcher.set_active (0);
  313.                     else
  314.                         return base.key_press_event (event);
  315.                     break;
  316.  
  317.                 case "2":
  318.                 case "KP_2":
  319.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  320.                         page_switcher.set_active (1);
  321.                     else if (modality == Modality.CATEGORY_VIEW)
  322.                         category_view.switcher.set_active (1);
  323.                     else
  324.                         return base.key_press_event (event);
  325.                     break;
  326.  
  327.                 case "3":
  328.                 case "KP_3":
  329.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  330.                         page_switcher.set_active (2);
  331.                     else if (modality == Modality.CATEGORY_VIEW)
  332.                         category_view.switcher.set_active (2);
  333.                     else
  334.                         return base.key_press_event (event);
  335.                     break;
  336.  
  337.                 case "4":
  338.                 case "KP_4":
  339.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  340.                         page_switcher.set_active (3);
  341.                     else if (modality == Modality.CATEGORY_VIEW)
  342.                         category_view.switcher.set_active (3);
  343.                     else
  344.                         return base.key_press_event (event);
  345.                     break;
  346.  
  347.                 case "5":
  348.                 case "KP_5":
  349.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  350.                         page_switcher.set_active (4);
  351.                     else if (modality == Modality.CATEGORY_VIEW)
  352.                         category_view.switcher.set_active (4);
  353.                     else
  354.                         return base.key_press_event (event);
  355.                     break;
  356.  
  357.                 case "6":
  358.                 case "KP_6":
  359.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  360.                         page_switcher.set_active (5);
  361.                     else if (modality == Modality.CATEGORY_VIEW)
  362.                         category_view.switcher.set_active (5);
  363.                     else
  364.                         return base.key_press_event (event);
  365.                     break;
  366.  
  367.                 case "7":
  368.                 case "KP_7":
  369.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  370.                         page_switcher.set_active (6);
  371.                     else if (modality == Modality.CATEGORY_VIEW)
  372.                         category_view.switcher.set_active (6);
  373.                     else
  374.                         return base.key_press_event (event);
  375.                     break;
  376.  
  377.                 case "8":
  378.                 case "KP_8":
  379.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  380.                         page_switcher.set_active (7);
  381.                     else if (modality == Modality.CATEGORY_VIEW)
  382.                         category_view.switcher.set_active (7);
  383.                     else
  384.                         return base.key_press_event (event);
  385.                     break;
  386.  
  387.                 case "9":
  388.                 case "KP_9":
  389.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  390.                         page_switcher.set_active (8);
  391.                     else if (modality == Modality.CATEGORY_VIEW)
  392.                         category_view.switcher.set_active (8);
  393.                     else
  394.                         return base.key_press_event (event);
  395.                     break;
  396.  
  397.                 case "0":
  398.                 case "KP_0":
  399.                     if (modality == Modality.NORMAL_VIEW && !searchbar.has_focus)
  400.                         page_switcher.set_active (9);
  401.                     else if (modality == Modality.CATEGORY_VIEW)
  402.                         category_view.switcher.set_active (9);
  403.                     else
  404.                         return base.key_press_event (event);
  405.                     break;
  406.  
  407.                 case "Left":
  408.                     if (modality == Modality.NORMAL_VIEW)
  409.                         page_switcher.set_active (page_switcher.active - 1);
  410.                     else if (modality == Modality.CATEGORY_VIEW)
  411.                         category_view.switcher.set_active (category_view.switcher.active - 1);
  412.                     else
  413.                         return base.key_press_event (event);
  414.                     break;
  415.  
  416.                 case "Right":
  417.                     if (modality == Modality.NORMAL_VIEW)
  418.                         page_switcher.set_active (page_switcher.active + 1);
  419.                     else if (modality == Modality.CATEGORY_VIEW)
  420.                         category_view.switcher.set_active (category_view.switcher.active + 1);
  421.                     else
  422.                         return base.key_press_event (event);
  423.                     break;
  424.  
  425.                 case "Up":
  426.                     if (modality == Modality.CATEGORY_VIEW)
  427.                         category_view.category_switcher.selected--;
  428.  
  429.                     else if (modality == Modality.SEARCH_VIEW) {
  430.                         search_view.selected--;
  431.                         search_view_up ();
  432.                     }
  433.                     break;
  434.  
  435.                 case "Down":
  436.                     if (modality == Modality.CATEGORY_VIEW)
  437.                         category_view.category_switcher.selected++;
  438.  
  439.                     if (modality == Modality.SEARCH_VIEW)
  440.                         search_view.selected++;
  441.                     if (search_view.selected > 7)
  442.                         search_view_down ();
  443.                     break;
  444.  
  445.                 default:
  446.                     if (!searchbar.has_focus)
  447.                         searchbar.grab_focus ();
  448.                     return base.key_press_event (event);
  449.  
  450.             }
  451.  
  452.             return true;
  453.  
  454.         }
  455.  
  456.         public override bool scroll_event (EventScroll event) {
  457.  
  458.             switch (event.direction.to_string ()) {
  459.                 case "GDK_SCROLL_UP":
  460.                 case "GDK_SCROLL_LEFT":
  461.                     if (modality == Modality.NORMAL_VIEW)
  462.                         page_switcher.set_active (page_switcher.active - 1);
  463.                     else if (modality == Modality.SEARCH_VIEW)
  464.                         search_view_up ();
  465.                     break;
  466.                 case "GDK_SCROLL_DOWN":
  467.                 case "GDK_SCROLL_RIGHT":
  468.                     if (modality == Modality.NORMAL_VIEW)
  469.                         page_switcher.set_active (page_switcher.active + 1);
  470.                     else if (modality == Modality.SEARCH_VIEW)
  471.                         search_view_down ();
  472.                     break;
  473.  
  474.             }
  475.  
  476.             return false;
  477.  
  478.         }
  479.  
  480.         public void hide_slingshot () {
  481.  
  482.             // Show the first page
  483.             searchbar.text = "";
  484.  
  485.             hide ();
  486.  
  487.             // grab_remove ((Widget) this);
  488.                     // get_current_event_device ().ungrab (Gdk.CURRENT_TIME);
  489.  
  490.         }
  491.        
  492.         public void destroy_slingshot () { //Reeeeeally bad solution, will find a proper one for Luna+1
  493.  
  494.             // Show the first page
  495.             searchbar.text = "";
  496.            
  497.             this.destroy ();
  498.             Process.spawn_command_line_async ("slingshot --silent");
  499.  
  500.         }
  501.  
  502.         public void show_slingshot () {
  503.  
  504.             reposition ();
  505.             show_all ();
  506.  
  507.             present ();
  508.             show_all ();
  509.             set_focus(null);
  510.             searchbar.grab_focus ();
  511.             set_modality ((Modality) view_selector.selected);
  512.  
  513.             //Utils.present_window (this);
  514.  
  515.         }
  516.  
  517.         private void page_left (int step = 1) {
  518.  
  519.             // Avoid unexpected behavior
  520.             if (modality != Modality.NORMAL_VIEW)
  521.                 return;
  522.  
  523.             if (current_position < 0) {
  524.                 int count = 0;
  525.                 int val = columns*130*step / 10;
  526.                 Timeout.add (20 / (2*step*step), () => {
  527.  
  528.                     if (count >= columns*130*step) {
  529.                         count = 0;
  530.                         return false;
  531.                     }
  532.                     view_manager.move (grid_view, current_position + val, 0);
  533.                     current_position += val;
  534.                     count += val;
  535.                     return true;
  536.  
  537.                 }, Priority.DEFAULT_IDLE);
  538.             }
  539.  
  540.         }
  541.  
  542.         private void page_right (int step = 1) {
  543.  
  544.             // Avoid unexpected behavior
  545.             if (modality != Modality.NORMAL_VIEW)
  546.                 return;
  547.  
  548.             if ((- current_position) < (grid_view.n_columns*130)) {
  549.                 int count = 0;
  550.                 int val = columns*130*step / 10;
  551.                 Timeout.add (20 / (2*step*step), () => {
  552.  
  553.                     if (count >= columns*130*step) {
  554.                         count = 0;
  555.                         return false;
  556.                     }
  557.                     view_manager.move (grid_view, current_position - val, 0);
  558.                     current_position -= val;
  559.                     count += val;
  560.                     return true;
  561.  
  562.                 }, Priority.DEFAULT_IDLE);
  563.             }
  564.  
  565.         }
  566.  
  567.         private void search_view_down () {
  568.  
  569.             if (search_view.apps_showed < default_rows * 3)
  570.                 return;
  571.  
  572.             if ((search_view_position) > -(search_view.apps_showed*48)) {
  573.                 view_manager.move (search_view, 0, search_view_position - 2*38);
  574.                 search_view_position -= 2*38;
  575.             }
  576.  
  577.         }
  578.  
  579.         private void search_view_up () {
  580.  
  581.             if (search_view_position < 0) {
  582.                 view_manager.move (search_view, 0, search_view_position + 2*38);
  583.                 search_view_position += 2*38;
  584.             }
  585.  
  586.         }
  587.  
  588.         private void set_modality (Modality new_modality) {
  589.  
  590.             modality = new_modality;
  591.  
  592.             switch (modality) {
  593.                 case Modality.NORMAL_VIEW:
  594.                
  595.                     Slingshot.settings.use_category = false;
  596.                     bottom.show ();
  597.                     view_selector.show_all ();
  598.                     page_switcher.show_all ();
  599.                     category_view.show_page_switcher (false);
  600.                     view_manager.move (search_view, -130*columns, 0);
  601.                     view_manager.move (category_view, 130*columns, 0);
  602.                     view_manager.move (grid_view, current_position, 0);
  603.                    
  604.                     // change the paddings/margins back to normal
  605.                     get_content_area ().set_margin_left (PADDINGS.left + SHADOW_SIZE + 5);
  606.                     center.set_margin_left (12);
  607.                     top.set_margin_left (12);
  608.                     view_manager.set_size_request (default_columns*130, default_rows*145);
  609.                     return;
  610.  
  611.                 case Modality.CATEGORY_VIEW:
  612.                    
  613.                     Slingshot.settings.use_category = true;
  614.                     bottom.show ();
  615.                     view_selector.show_all ();
  616.                     page_switcher.hide ();
  617.                     category_view.show_page_switcher (true);
  618.                     view_manager.move (grid_view, columns*130, 0);
  619.                     view_manager.move (search_view, -columns*130, 0);
  620.                     view_manager.move (category_view, 0, 0);
  621.                    
  622.                     // remove the padding/margin on the left
  623.                     get_content_area ().set_margin_left (PADDINGS.left + SHADOW_SIZE);
  624.                     center.set_margin_left (0);
  625.                     top.set_margin_left (17);
  626.                     view_manager.set_size_request (default_columns*130 + 17, default_rows*145);
  627.                     return;
  628.  
  629.                 case Modality.SEARCH_VIEW:
  630.                     view_selector.hide ();
  631.                     bottom.hide (); // Hide the switcher
  632.                     view_manager.move (grid_view, columns*130, 0); // Move the grid_view away
  633.                     view_manager.move (category_view, columns*130, 0);
  634.                     view_manager.move (search_view, 0, 0); // Show the searchview
  635.                    
  636.                     // change the paddings/margins back to normal
  637.                     get_content_area ().set_margin_left (PADDINGS.left + SHADOW_SIZE + 5);
  638.                     center.set_margin_left (12);
  639.                     top.set_margin_left (12);
  640.                     view_manager.set_size_request (default_columns*130, default_rows*145);
  641.                     return;
  642.  
  643.             }
  644.  
  645.         }
  646.  
  647.         private async void search (string text) {
  648.  
  649.             if (text == "") {
  650.                 set_modality ((Modality) view_selector.selected);
  651.                 return;
  652.             }
  653.  
  654.             if (modality != Modality.SEARCH_VIEW)
  655.                 set_modality (Modality.SEARCH_VIEW);
  656.             search_view_position = 0;
  657.             search_view.hide_all ();
  658.  
  659.             var filtered = yield app_system.search_results (text);
  660.  
  661.             foreach (App app in filtered) {
  662.                 search_view.show_app (app);
  663.             }
  664.  
  665.             if (filtered.size != 1)
  666.                 search_view.add_command (text);
  667.  
  668.         }
  669.  
  670.         public void populate_grid_view () {
  671.  
  672.             page_switcher.clear_children ();
  673.             grid_view.clear ();
  674.  
  675.             page_switcher.append ("1");
  676.             page_switcher.set_active (0);
  677.  
  678.             foreach (App app in app_system.get_apps_by_name ()) {
  679.  
  680.                 var app_entry = new AppEntry (app);
  681.  
  682.                 app_entry.app_launched.connect (destroy_slingshot);
  683.                 grid_view.append (app_entry);
  684.                 app_entry.show_all ();
  685.  
  686.             }
  687.  
  688.             current_position = 0;
  689.  
  690.         }
  691.  
  692.         private void read_settings (bool first_start = false) {
  693.  
  694.             if (Slingshot.settings.columns > 3)
  695.                 default_columns = Slingshot.settings.columns;
  696.             else
  697.                 default_columns = Slingshot.settings.columns = 5;
  698.  
  699.             if (Slingshot.settings.rows > 1)
  700.                 default_rows = Slingshot.settings.rows;
  701.             else
  702.                 default_rows = Slingshot.settings.rows = 3;
  703.  
  704.         }
  705.  
  706.     }
  707.  
  708. }