Skip to content

Commit 976d0d9

Browse files
authored
Merge pull request #15 from leafOfTree/dev
Enable mouse hover to activate tabs; add option for auto hide and align tabs
2 parents 68ad89d + f01a9bd commit 976d0d9

File tree

7 files changed

+82
-14
lines changed

7 files changed

+82
-14
lines changed

WtProgram/ManagerViewService/Views/BehaviorView.fs

+27-8
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,37 @@ type HotKeyView() =
2828

2929
let settingsCheckbox key = checkBox(settingsProperty(key))
3030

31+
let dropDown (prop:IProperty<string>, items: string list) =
32+
let combo = new ComboBox()
33+
34+
// First add items
35+
combo.Items.AddRange(items |> List.toArray |> Array.map box)
36+
37+
// Then set initial value if exists, otherwise select first item
38+
let initialIndex =
39+
match items |> List.tryFindIndex ((=) prop.value) with
40+
| Some index -> index
41+
| None -> if combo.Items.Count > 0 then 0 else -1
42+
43+
if initialIndex >= 0 then
44+
combo.SelectedIndex <- initialIndex
45+
46+
combo.SelectedIndexChanged.Add(fun _ ->
47+
if combo.SelectedIndex >= 0 then
48+
prop.value <- combo.SelectedItem.ToString()
49+
)
50+
51+
combo :> Control
52+
53+
let settingsDropDown key value = dropDown(settingsProperty(key), value)
54+
3155
let basicForm =
3256
let fields = List2([
3357
("runAtStartup", settingsCheckbox "runAtStartup")
3458
("hideInactiveTabs", settingsCheckbox "hideInactiveTabs")
3559
("isTabbingEnabledForAllProcessesByDefault", checkBox(prop<IFilterService, bool>(Services.filter, "isTabbingEnabledForAllProcessesByDefault")))
60+
("autoHide", settingsCheckbox "autoHide")
61+
("alignment", settingsDropDown "alignment" ["Left"; "Center"; "Right"])
3662
])
3763
"Basics", UIHelper.form fields
3864

@@ -63,21 +89,14 @@ type HotKeyView() =
6389
editor.value <- Services.program.getHotKey(key)
6490
editor.changed.Add <| fun() ->
6591
Services.program.setHotKey key (unbox<int>(editor.value))
66-
67-
let checkBox (prop:IProperty<bool>) =
68-
let checkbox = BoolEditor() :> IPropEditor
69-
checkbox.value <- box(prop.value)
70-
checkbox.changed.Add <| fun() -> prop.value <- unbox<bool>(checkbox.value)
71-
checkbox.control
72-
73-
let settingsCheckbox key = checkBox(settingsProperty(key))
7492

7593
let fields = hotKeys.map <| fun(key,text) ->
7694
let editor = editors.find key
7795
text, editor.control
7896

7997
let fields = fields.prependList(List2([
8098
("enableCtrlNumberHotKey", settingsCheckbox "enableCtrlNumberHotKey")
99+
("enableHoverActivate", settingsCheckbox "enableHoverActivate")
81100
]))
82101

83102
"Switch Tabs", UIHelper.form fields

WtProgram/Properties/Resources.ja-JP.resx

+9
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@
165165
<data name="enableCtrlNumberHotKey" xml:space="preserve">
166166
<value>Ctrl+1、... Ctrl+9 でタブをアクティブ化を有効にする</value>
167167
</data>
168+
<data name="enableHoverActivate" xml:space="preserve">
169+
<value>マウスホバーでタブを有効にする</value>
170+
</data>
171+
<data name="autoHide" xml:space="preserve">
172+
<value>最大化時にタブを自動的に隠す</value>
173+
</data>
174+
<data name="alignment" xml:space="preserve">
175+
<value>タブの配置</value>
176+
</data>
168177
<data name="Height" xml:space="preserve">
169178
<value>高さ</value>
170179
</data>

WtProgram/Properties/Resources.resx

+10-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,16 @@
163163
<value>Group windows in WindowTabs task switcher</value>
164164
</data>
165165
<data name="enableCtrlNumberHotKey" xml:space="preserve">
166-
<value>Enable Ctrl+1, ...Ctrl+9 to active tab</value>
166+
<value>Enable Ctrl+1, ...Ctrl+9 to activate tab</value>
167+
</data>
168+
<data name="enableHoverActivate" xml:space="preserve">
169+
<value>Enable mouse hover to activate tab</value>
170+
</data>
171+
<data name="autoHide" xml:space="preserve">
172+
<value>Auto hide tab when maximized</value>
173+
</data>
174+
<data name="alignment" xml:space="preserve">
175+
<value>Align tabs</value>
167176
</data>
168177
<data name="Height" xml:space="preserve">
169178
<value>Height</value>

WtProgram/Settings.fs

+6
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ type Settings(isStandAlone) as this =
8686
replaceAltTab = settingsJson.getBool("replaceAltTab").def(false)
8787
groupWindowsInSwitcher = settingsJson.getBool("groupWindowsInSwitcher").def(false)
8888
enableCtrlNumberHotKey = settingsJson.getBool("enableCtrlNumberHotKey").def(true)
89+
enableHoverActivate = settingsJson.getBool("enableHoverActivate").def(false)
90+
autoHide = settingsJson.getBool("autoHide").def(true)
8991
version = settingsJson.getString("version").def(String.Empty)
92+
alignment = settingsJson.getString("alignment").def("Center")
9093
tabAppearance =
9194
let appearanceObject = settingsJson.getObject("tabAppearance").def(JObject())
9295
appearanceObject.items.fold this.defaultTabAppearance <| fun appearance (key,value) ->
@@ -105,6 +108,7 @@ type Settings(isStandAlone) as this =
105108
let settingsJson = this.settingsJson
106109
settingsJson.setString("version", settings.version)
107110
settingsJson.setString("licenseKey", settings.licenseKey)
111+
settingsJson.setString("alignment", settings.alignment)
108112
settings.ticket.iter <| fun ticket -> settingsJson.setString("ticket", ticket)
109113
settingsJson.setBool("runAtStartup", settings.runAtStartup)
110114
settingsJson.setBool("hideInactiveTabs", settings.hideInactiveTabs)
@@ -113,6 +117,8 @@ type Settings(isStandAlone) as this =
113117
settingsJson.setBool("replaceAltTab", settings.replaceAltTab)
114118
settingsJson.setBool("groupWindowsInSwitcher", settings.groupWindowsInSwitcher)
115119
settingsJson.setBool("enableCtrlNumberHotKey", settings.enableCtrlNumberHotKey)
120+
settingsJson.setBool("enableHoverActivate", settings.enableHoverActivate)
121+
settingsJson.setBool("autoHide", settings.autoHide)
116122
settingsJson.setStringArray("includedPaths", settings.includedPaths.items)
117123
settingsJson.setStringArray("excludedPaths", settings.excludedPaths.items)
118124
settingsJson.setStringArray("autoGroupingPaths", settings.autoGroupingPaths.items)

WtProgram/Shared/ProgramTypes.fs

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ type SettingsRec = {
3131
groupWindowsInSwitcher: bool
3232
enableCtrlNumberHotKey: bool
3333
combineIconsInTaskbar: bool
34+
enableHoverActivate: bool
35+
autoHide: bool
36+
alignment: string
3437
}
3538

3639
type ILicenseManager =

WtProgram/TabStrip.fs

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Bemo
1+
namespace Bemo
22
open System
33
open System.Collections
44
open System.Drawing
@@ -11,6 +11,7 @@ open Bemo.Win32.Forms
1111

1212
type ITabStripMonitor =
1313
abstract member tabClick : (MouseButton * Tab * TabPart * MouseAction * Pt) -> unit
14+
abstract member tabActivate : (Tab) -> unit
1415
abstract member tabClose : Tab -> unit
1516
abstract member tabMoved : Tab * int -> unit
1617
abstract member windowMsg : Win32Message -> unit
@@ -34,7 +35,18 @@ type TabStrip(monitor:ITabStripMonitor) as this =
3435
let showInsideCell = Cell.create(false)
3536
let isInAltTabCell = Cell.create(false)
3637
let iconOnlyCell = Cell.create(false)
37-
let alignment = Cell.create(Map2(List2([(TabUp,TabLeft);(TabDown,TabCenter)])))
38+
let alignmentMap =
39+
Map.ofList [
40+
"Left", TabLeft
41+
"Center", TabCenter
42+
"Right", TabRight
43+
]
44+
let alignmentDefault =
45+
let alignmentDefault = Services.settings.getValue("alignment").cast<string>()
46+
match alignmentMap.TryFind alignmentDefault with
47+
| Some align -> align
48+
| None -> TabCenter
49+
let alignment = Cell.create(Map2(List2([(TabUp,alignmentDefault);(TabDown,alignmentDefault)])))
3850
let capturedCell = Cell.create(None : Option<Tab*TabPart>)
3951
let hoverCell = Cell.create(None : Option<Tab*TabPart>)
4052
let slideCell = Cell.create(None)
@@ -67,7 +79,7 @@ type TabStrip(monitor:ITabStripMonitor) as this =
6779

6880
Cell.listen <| fun() ->
6981
this.update()
70-
82+
7183
member private this.inAltSwitch = isInAltTabCell.value
7284

7385
member private this.layeredWindow = layeredWindowCell.value.Value
@@ -130,6 +142,10 @@ type TabStrip(monitor:ITabStripMonitor) as this =
130142
if this.window.hasCapture.not then
131143
this.window.trackMouseLeave()
132144
hoverCell.set(this.hit)
145+
let enableHoverActivate = Services.settings.getValue("enableHoverActivate").cast<bool>()
146+
if enableHoverActivate then
147+
this.hit.iter <| fun(hitTab, hitPart) ->
148+
monitor.tabActivate(hitTab)
133149
| MouseClick(pt, btn, action) ->
134150
this.setPt(Some(pt))
135151
this.hit.iter <| fun(hitTab, hitPart) ->

WtProgram/TabStripDecorator.fs

+8-2
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ type TabStripDecorator(group:WindowGroup) as this =
167167
})
168168

169169
let autoHideItem =
170-
let isEnabled = group.bb.read("autoHide", true)
170+
let isAutoHideEnabledDef = Services.settings.getValue("autoHide").cast<bool>()
171+
let isEnabled = group.bb.read("autoHide", isAutoHideEnabledDef)
171172
CmiRegular({
172173
text = "Auto hide maximized"
173174
flags = checked(isEnabled)
@@ -295,7 +296,9 @@ type TabStripDecorator(group:WindowGroup) as this =
295296
let update() = cell.value <- group.bb.read(key, def)
296297
group.bb.subscribe key update
297298
cell
298-
let autoHideCell = propCell("autoHide", true)
299+
300+
let isAutoHideEnabledDef = Services.settings.getValue("autoHide").cast<bool>()
301+
let autoHideCell = propCell("autoHide", isAutoHideEnabledDef)
299302
let contextMenuVisibleCell = propCell("contextMenuVisible", false)
300303
let renamingTabCell = propCell("renamingTab", false)
301304
let isRecentlyChangedZorderCell =
@@ -347,6 +350,9 @@ type TabStripDecorator(group:WindowGroup) as this =
347350
| MouseMiddle ->
348351
group.tabActivate(tab, false)
349352
| _ -> ()
353+
354+
member x.tabActivate((tab)) =
355+
group.tabActivate(tab, false)
350356

351357
member x.tabMoved(Tab(hwnd), index) =
352358
group.onTabMoved(hwnd, index)

0 commit comments

Comments
 (0)