Commits

Thibaut Colar committed e38fdba

Bug fixes and recent anel with shortcuts

  • Participants
  • Parent commits 8a00f54

Comments (0)

Files changed (14)

src/brie/fan/Frame.fan

     this.icon = Image(`fan://icons/x32/blueprints.png`)
     Actor.locals["frame"] = this
 
+    history.pushListeners.add(
+      |history| {recentPane.update(history)}
+    )
+
     // menu
     menuBar = Menu{
       Menu {
       Menu {
         text = "Navigation"
         MenuItem{ command = sys.commands.mostRecent.asCommand},
-        MenuItem{ command = sys.commands.recent.asCommand},
         MenuItem{ command = sys.commands.prevMark.asCommand},
         MenuItem{ command = sys.commands.nextMark.asCommand},
         MenuItem{ command = sys.commands.find.asCommand},
         MenuItem{ command = sys.commands.findInSpace.asCommand},
         MenuItem{ command = sys.commands.goto.asCommand},
-        MenuItem{ command = sys.commands.searchDocs.asCommand},
       },
       Menu {
         text = "Process"
         MenuItem{ command = sys.commands.build.asCommand},
         MenuItem{ command = sys.commands.run.asCommand},
         MenuItem{ command = sys.commands.buildAndRun.asCommand},
-        MenuItem{ command = sys.commands.esc.asCommand},
         MenuItem{ command = sys.commands.terminate.asCommand},
       },
       Menu {
+        text = "Panels"
+        MenuItem{ command = sys.commands.consoleToggle.asCommand},
+        MenuItem{ command = sys.commands.docsToggle.asCommand},
+        MenuItem{ command = sys.commands.recentToggle.asCommand},
+      },
+      Menu {
         text = "Options"
         MenuItem{ command = sys.commands.editConfig.asCommand},
         MenuItem{ command = sys.commands.reloadConfig.asCommand},
     this.statusBar = StatusBar(this)
     this.console   = Console(this)
     this.helpPane = HelpPane(this)
+    this.recentPane = RecentPane(this)
     this.content = EdgePane
     {
       it.top = spaceBar
           orientation = Orientation.horizontal
           weights = [80, 20]
           spacePane,
-          helpPane,
+          SashPane
+          {
+            orientation = Orientation.vertical
+            weights = [30, 70]
+            recentPane,
+            helpPane,
+          }
         },
         console,
       }
 
   HelpPane helpPane { private set }
 
+  RecentPane recentPane { private set }
+
   ** Navigation history
   History history := History() { private set }
 
   internal Void trapKeyDown(Event event)
   {
     cmd := sys.commands.findByKey(event.key)
-    if (cmd != null) cmd.invoke(event)
+    if (cmd != null)
+    {
+      cmd.invoke(event)
     }
+    if(event.keyChar >= '1'
+      && event.keyChar<='9'
+      && event.key.modifiers.toStr == sys.shortcuts.recentModifier)
+    {
+       sys.commands.recent.invoke(event)
+    }
+  }
 
   private Void doDrop(Obj data)
   {

src/brie/fan/History.fan

-//
-// Copyright (c) 2008, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-//   12 Sep 08  Brian Frank  Creation
-//   31 May 11  Brian Frank  Repurpose for Brie
-//
-
-using gfx
-using fwt
-
-**
-** History maintains the most recent navigation history
-** of the entire application.
-**
-class History
-{
-
-  **
-  ** Log navigation to the specified resource
-  ** into the history.  Return this.
-  **
-  This push(Space space, Item link)
-  {
-    // create history item
-    item := Item
-    {
-      it.space = space
-      it.file  = link.file
-      it.dis   = link.file.name
-      it.icon  = Theme.fileToIcon(link.file)
-    }
-
-    // remove any item that matches space + file
-    dup := items.findIndex |x|
-    {
-      item.space.typeof == x.space.typeof &&
-      item.file == x.file
-    }
-    if (dup != null) items.removeAt(dup)
-
-    // keep size below max
-    while (items.size >= max) items.removeAt(-1)
-
-    // push into most recent position
-    items.insert(0, item)
-    return this
-  }
-
-  **
-  ** The first item is the most recent navigation and the last
-  ** item is the oldest navigation.
-  **
-  Item[] items := [,] { private set }
-
-  private Int max := 40
-}
-
-**************************************************************************
-** HistoryPicker
-**************************************************************************
-
-class HistoryPicker : EdgePane
-{
-  new make(Item[] items, |Item, Event| onAction)
-  {
-    model := HistoryPickerModel(items)
-    center = Table
-    {
-      it.headerVisible = false
-      it.model = model
-      it.onAction.add |Event e|
-      {
-        onAction(model.items[e.index], e)
-      }
-      it.onKeyDown.add |Event e|
-      {
-        code := e.keyChar
-        if (code >= 97 && code <= 122) code -= 32
-        code -= 65
-        if (code >= 0 && code < 26 && code < model.numRows)
-          onAction(model.items[code], e)
-      }
-    }
-  }
-}
-
-internal class HistoryPickerModel : TableModel
-{
-  Sys? sys := Service.find(Sys#) as Sys
-
-  new make(Item[] items) { this.items = items }
-
-  override Int numCols() { return 3 }
-  override Int numRows() { return items.size }
-  override Int? prefWidth(Int col)
-  {
-    switch (col)
-    {
-      case 0: return 40
-      case 1: return 250
-      default: return null
-    }
-  }
-  override Image? image(Int col, Int row) { col==1 ? (items[row].icon ?: def) : null}
-  override Font? font(Int col, Int row) { col==0 ? accFont : null }
-  override Color? fg(Int col, Int row)  { col==0 ? accColor : null }
-  override Str text(Int col, Int row)
-  {
-    switch (col)
-    {
-      case 0:  return (row < 26) ? (row+65).toChar : ""
-      case 1:  return items[row].dis
-      case 2:  return items[row].space.dis
-      default: return ""
-    }
-  }
-  Item[] items
-  Image def := sys.theme.iconFile
-  Font accFont := sys.theme.font.toSize(sys.theme.font.size - 1)
-  Color accColor := Color("#666")
-}
-

src/brie/fan/Shortcuts.fan

   const Str buildAndRun           := "F6"
 
   @Setting{help = ["Escape (close console / panel)"]}
-  const Str escape                := "Esc"
+  const Str consoleToggle         := "Alt+C"
 
   @Setting{help = ["Insert a comment section(separator)"]}
   const Str insertCommentSection  := "Ctrl+="
   @Setting{help = ["Search docs for a pod/type/slot. Opens docc pane"]}
   const Str searchDocs            := "F1"
 
-  @Setting{help = ["Navigate between recent files"]}
-  const Str recent                := "Ctrl+Space"
+  @Setting{help = ["Search docs for a pod/type/slot. Opens docc pane"]}
+  const Str docsToggle            := "Alt+D"
 
-  @Setting{help = ["Back to most recent file (Equivalent to Ctrl+Space then a)"]}
-  const Str mostRecent            := "Alt+Space"
+  @Setting{help = ["Toggle recent files panel"]}
+  const Str recentToggle          := "Alt+R"
+
+  @Setting{help = ["Back to most recent file (Equivalent to Ctrl+1)"]}
+  const Str mostRecent            := "Ctrl+Space"
+
+  @Setting{help = ["Recent files will be mapped to Modifier + 1 .. 9"]}
+  const Str recentModifier := "Ctrl"
 
   @Setting{help = ["Next mark (next item in console)"]}
   const Str nextMark              := "F8"

src/brie/fan/command/Commands.fan

     exit        = ExitCmd{}
     reload      = ReloadCmd{key = Key(sys.shortcuts.reloadFile)}
     save        = SaveCmd{key = Key(sys.shortcuts.saveFile)}
-    esc         = EscCmd{key = Key(sys.shortcuts.escape)}
-    recent      = RecentCmd{key = Key(sys.shortcuts.recent)}
+    consoleToggle=ToggleConsoleCmd{key = Key(sys.shortcuts.consoleToggle)}
+    recentToggle= ToggleRecentCmd{key = Key(sys.shortcuts.recentToggle)}
+    docsToggle  = ToggleHelpCmd{key = Key(sys.shortcuts.docsToggle)}
     mostRecent  = MostRecentCmd{key = Key(sys.shortcuts.mostRecent)}
     prevMark    = PrevMarkCmd{key = Key(sys.shortcuts.prevMark)}
     nextMark    = NextMarkCmd{key = Key(sys.shortcuts.nextMark)}
   const Cmd exit
   const Cmd reload
   const Cmd save
-  const Cmd esc
-  const Cmd recent
+  const Cmd consoleToggle
+  const Cmd recentToggle
+  const Cmd docsToggle
   const Cmd prevMark
   const Cmd nextMark
   const Cmd find
   const Cmd searchDocs
   const Cmd mostRecent
   const Cmd newFile
+  const Cmd recent := RecentCmd {}
 }
 
 **************************************************************************

src/brie/fan/command/FileCommands.fan

   override Void invoke(Event event)
   {
     r := Dialog.openQuestion(frame, "Exit application?", null, Dialog.okCancel)
-    if (r != Dialog.ok) return
-      frame.saveSession
+    if (r != Dialog.ok)
+      return
+    frame.saveSession
     Env.cur.exit(0)
   }
   new make(|This| f) {f(this)}

src/brie/fan/command/NavigationCommands.fan

   override const Str name := "Recent Files"
   override Void invoke(Event event)
   {
-    Dialog? dlg
-    picker := HistoryPicker(frame.history.items) |item, e|
-    {
-      frame.goto(item)
-      dlg.close
-    }
-    pane := ConstraintPane { minw = 300; maxh = 300; add(picker) }
-    dlg = Dialog(frame) { title="Recent"; body=pane; commands=[Dialog.ok, Dialog.cancel] }
-    dlg.open
+    index := event.keyChar - '0'
+    echo(index)
+    items := frame.history.items
+    if(index>=0 && items.size > index)
+      frame.goto(items[index])
   }
   new make(|This| f) {f(this)}
 }

src/brie/fan/command/ProcessCommands.fan

 using fwt
 using concurrent
 
-**************************************************************************
-** EscCmd
-**************************************************************************
-
-internal const class EscCmd : Cmd
-{
-  new make(|This| f) {f(this)}
-  override const Str name := "Close Console"
-  override Void invoke(Event event)
-  {
-    frame.marks = Item[,]
-    frame.console.close
-    frame.curView?.onReady
-  }
-}
-
 internal const class TerminateCmd : Cmd
 {
   new make(|This| f) {f(this)}

src/brie/fan/command/ToggleCommands.fan

+using fwt
+
+internal const class ToggleHelpCmd : Cmd
+{
+  override const Str name := "Toggle Doc Pane"
+  override Void invoke(Event event)
+  {
+    frame.helpPane.toggle
+  }
+  new make(|This| f) {f(this)}
+}
+
+internal const class ToggleRecentCmd : Cmd
+{
+  override const Str name := "Toggle Recent Pane"
+  override Void invoke(Event event)
+  {
+    frame.recentPane.toggle
+  }
+  new make(|This| f) {f(this)}
+}
+
+internal const class ToggleConsoleCmd : Cmd
+{
+  new make(|This| f) {f(this)}
+  override const Str name := "Toggle Console Pane"
+  override Void invoke(Event event)
+  {
+    frame.console.toggle
+  }
+}
+
+

src/brie/fan/space/PodSpace.fan

 
   override Widget onLoad(Frame frame)
   {
+    frame.history.push(this, Item.makeFile(file))
     return EdgePane
     {
       left = EdgePane

src/brie/fan/widget/Console.fan

     this.content = this.list
     this.visible = false
   }
-  
+
   Void updateSys(Sys sys)
   {
     this.sys = sys
     inKill = false
     onDone = null
   }
-  
+
   Frame frame { private set }
   ItemList list { private set}
   Sys? sys
       cons := c.val as Console
       cons.procDone(result)
     }
-    
+
     return null
   }
 

src/brie/fan/widget/HelpPane.fan

     {
       search = Text
       {
-        text="";
-        prefCols = 10;
+        text="Search"
+        prefCols = 15
         onAction.add |Event e|
         {
           showSearch(search.text)
       }
       top = GridPane
       {
-        numCols = 4
+        numCols = 3
         Button{image = gfx::Image(`fan://icons/x16/arrowLeft.png`); onAction.add |Event e|
           {
             if( ! pageHistory.isEmpty) pageHistory.pop()
-              if( ! pageHistory.isEmpty)
+            if( ! pageHistory.isEmpty)
             {
               showPage(pageHistory.pop())
             }
         },
         Button{image = gfx::Image(`fan://camembert/res/home.png`, false); onAction.add |Event e| {showPage("") }},
         search,
-        Button
-        {
-          text="close";
-          onAction.add |Event e|
-          {
-            hide
-          }
-        },
       }
       center = BorderPane
       {
       // maybe support directly to a slot later (matchSlot)
       info := sys.index.matchTypes(uri[uri.index("#goto:") + 6 .. -1], MatchKind.exact).first
       if(info != null)
-      try{frame.goto(Item(info))}catch(Err err){}
+        try{frame.goto(Item(info))}catch(Err err){}
       e.data = null
     }
     if(uri.contains("://"))
       browser.load(text.toUri)
       return
     }
-    search.text = text
+    search.text = text.trim
     pageHistory.clear
     browser.loadStr(find(search.text))
   }
   {
     this.visible = false
     parent.relayout
+    if( ! frame.recentPane.visible)
+    {
+      parent.visible = false
+      parent.parent.relayout
+    }
+  }
+
+  Void toggle()
+  {
+    if(visible)
+      hide
+    else
+      show
   }
 
   private Void show()
   {
     this.visible = true
     parent.relayout
+    if(parent.visible == false)
+    {
+      parent.visible = true
+      parent.parent.relayout
+    }
   }
 
   private Void showPage(Str uri)
   ** Search pods and types for items matching the query
   private Str find(Str query, MatchKind kind := MatchKind.startsWith, Bool inclSlots := false)
   {
+    if(query.isEmpty) {showPage(""); return ""}
     index := sys.index
 
     results := "<h2>Pods:</h2>"

src/brie/fan/widget/RecentPane.fan

+using fwt
+using gfx
+
+** Sidebar to show recent documents
+class RecentPane : ContentPane
+{
+  Frame frame
+  RecentPicker picker
+
+  new make(Frame frame)
+  {
+    this.frame = frame
+    content = EdgePane
+    {
+      top = Label {text = "Recent Items (Modif+Number)"}
+      picker = RecentPicker(frame.history.items) |item, e|
+      {
+        frame.goto(item)
+      }
+      center = picker
+    }
+  }
+
+  Void update(History history)
+  {
+    (picker.mdl as RecentPickerModel).update(history)
+    picker.refresh
+  }
+
+  Void hide()
+  {
+    this.visible = false
+    parent.relayout
+    if( ! frame.helpPane.visible)
+    {
+      parent.visible = false
+      parent.parent.relayout
+    }
+  }
+
+  Void show()
+  {
+    this.visible = true
+    parent.relayout
+    if(parent.visible == false)
+    {
+      parent.visible = true
+      parent.parent.relayout
+    }
+  }
+
+  Void toggle()
+  {
+    if (this.visible)
+      hide
+    else
+      show
+  }
+}
+
+class RecentPicker : EdgePane
+{
+  Table table
+  RecentPickerModel mdl
+  new make(Item[] items, |Item, Event| onAction)
+  {
+    mdl = RecentPickerModel(items)
+    table = Table
+    {
+      it.headerVisible = false
+      it.model = mdl
+      it.onSelect.add |Event e|
+      {
+        onAction(mdl.items[e.index], e)
+      }
+      /*it.onKeyDown.add |Event e|
+      {
+        code := e.keyChar
+        if (code >= 97 && code <= 122) code -= 32
+        code -= 65
+        if (code >= 0 && code < 26 && code < mdl.numRows)
+          onAction(mdl.items[code], e)
+        if(e.key==Key.enter && table.selected.size>0)
+          onAction(mdl.items[table.selected[0]], e)
+      }*/
+    }
+    center = table
+  }
+
+  Void refresh()
+  {
+    table.refreshAll
+  }
+}
+
+class RecentPickerModel : TableModel
+{
+  Sys? sys := Service.find(Sys#) as Sys
+
+  new make(Item[] items) { this.items = items }
+
+  override Int numCols() { return 3 }
+  override Int numRows() { return items.size }
+  override Int? prefWidth(Int col)
+  {
+    switch (col)
+    {
+      case 0: return 25
+      case 1: return 200
+      default: return null
+    }
+  }
+  override Image? image(Int col, Int row) { col==1 ? (items[row].icon ?: def) : null}
+  override Font? font(Int col, Int row) { col==0 ? accFont : null }
+  override Color? fg(Int col, Int row)  { col==0 ? accColor : null }
+  override Str text(Int col, Int row)
+  {
+    switch (col)
+    {
+      case 0:  return row >= 1 && row <= 9 ? row.toStr : ""
+      case 1:  return items[row].dis
+      case 2:  return items[row].space.dis
+      default: return ""
+    }
+  }
+  Item[] items
+  Image def := sys.theme.iconFile
+  Font accFont := sys.theme.font.toSize(sys.theme.font.size - 1)
+  Color accColor := Color("#666")
+
+  Void update(History history)
+  {
+    items = history.items
+  }
+}
+
+class History
+{
+  |History|[] pushListeners := [,]
+
+  **
+  ** Log navigation to the specified resource
+  ** into the history.  Return this.
+  **
+  This push(Space space, Item link)
+  {
+    // create history item
+    item := Item
+    {
+      it.space = space
+      it.file  = link.file
+      it.dis   = link.file.name
+      it.icon  = Theme.fileToIcon(link.file)
+    }
+
+    // remove any item that matches space + file
+    dup := items.findIndex |x|
+    {
+      item.space.typeof == x.space.typeof &&
+      item.file == x.file
+    }
+    if (dup != null) items.removeAt(dup)
+
+    // keep size below max
+    while (items.size >= max) items.removeAt(-1)
+
+    // push into most recent position
+    items.insert(0, item)
+
+    pushListeners.each {it.call(this)}
+    return this
+  }
+
+  **
+  ** The first item is the most recent navigation and the last
+  ** item is the oldest navigation.
+  **
+  Item[] items := [,] { private set }
+
+  private Int max := 40
+}
+

src/brie/fan/widget/StatusBar.fan

       MenuItem
       {
         it.text = "Close Console"
-        it.accelerator = sys.commands.esc.key
+        it.accelerator = sys.commands.consoleToggle.key
         it.onAction.add |e| { frame.console.close }
       },
       MenuItem

src/brie/todo.txt

+delete file
+rename file
+duplicate file
+
+allow copy from console output
+fix bug where recent show same file many times
+
+space nav pill -> right click: find in space (so don't need to open file to do it)
+
+If file is opened in file view but file exists in pod view - open it in pod view ??
+-> or if opening  folder in file view that is a pod, the juts open it has a pod (show pod icon in file nav ?)
+
+File space -> Make new source root checkbox ? -> -> what if alreday in source roots
+file view / dir -> Open as new space
+file space -> show only name rather than full path (full path on rollover)
+
+when file nav is used, highlight current file and stay on it (not reset navbar each time)
+or when open file -> highlight in navbar / scroll to
+
+Bocce: Ctrl+A -> select all
+
+pod view -> Specific pod : customize root ? (for example from /camembert/src/brie/ to /camembert)
+
+If detecting a buildgroup type build.fan, present that as pod collection(folder) in podl ist, then can open if (file view)