From 1e8629263c0547be5afdf668e144b2a17f28f813 Mon Sep 17 00:00:00 2001 From: Jacob Date: Mon, 27 Nov 2023 23:31:00 +0100 Subject: [PATCH] Use internal/build for mobile lookup as well Does not seem to help deadcode elimination anything but it seems nice to clean up some code and have all build type information in one common place? --- app/app.go | 3 ++- container/apptabs.go | 3 ++- container/tabs.go | 31 ++++++++++++++------------ driver/software/render_test.go | 4 ++-- internal/build/device_desktop.go | 9 ++++++++ internal/build/device_goxjs.go | 19 ++++++++++++++++ internal/build/device_mobile.go | 9 ++++++++ internal/driver/glfw/device.go | 5 +++++ internal/driver/glfw/device_desktop.go | 4 ---- internal/driver/glfw/device_goxjs.go | 11 --------- internal/widget/scroller.go | 3 ++- test/device.go | 5 +++++ test/device_mobile.go | 8 ------- test/device_other.go | 8 ------- test/test.go | 3 ++- widget/button_test.go | 5 +++-- widget/check.go | 3 ++- widget/check_internal_test.go | 14 ++++++------ widget/entry.go | 3 ++- widget/gridwrap.go | 3 ++- widget/list.go | 3 ++- widget/menu_item.go | 5 +++-- widget/popup_menu.go | 3 ++- widget/radio_item.go | 3 ++- widget/slider.go | 3 ++- widget/table.go | 3 ++- widget/tree.go | 3 ++- 27 files changed, 105 insertions(+), 71 deletions(-) create mode 100644 internal/build/device_desktop.go create mode 100644 internal/build/device_goxjs.go create mode 100644 internal/build/device_mobile.go delete mode 100644 test/device_mobile.go delete mode 100644 test/device_other.go diff --git a/app/app.go b/app/app.go index 545b94b492..7d0d4dbddf 100644 --- a/app/app.go +++ b/app/app.go @@ -11,6 +11,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/internal" "fyne.io/fyne/v2/internal/app" + "fyne.io/fyne/v2/internal/build" intRepo "fyne.io/fyne/v2/internal/repository" "fyne.io/fyne/v2/storage/repository" ) @@ -145,7 +146,7 @@ func newAppWithDriver(d fyne.Driver, id string) fyne.App { store.Docs = makeStoreDocs(id, store) newApp.storage = store - if !d.Device().IsMobile() { + if !build.IsMobile() { newApp.settings.watchSettings() } diff --git a/container/apptabs.go b/container/apptabs.go index b02300e59a..6b6a7c3db7 100644 --- a/container/apptabs.go +++ b/container/apptabs.go @@ -3,6 +3,7 @@ package container import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -348,7 +349,7 @@ func (r *appTabsRenderer) buildTabButtons(count int) *fyne.Container { buttons := &fyne.Container{} var iconPos buttonIconPosition - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { cells := count if cells == 0 { cells = 1 diff --git a/container/tabs.go b/container/tabs.go index ac3d65c3dd..b1a1f1d209 100644 --- a/container/tabs.go +++ b/container/tabs.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/internal" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -89,20 +90,22 @@ type baseTabs interface { } func tabsAdjustedLocation(l TabLocation) TabLocation { + if !build.IsMobile() { + return l + } + // Mobile has limited screen space, so don't put app tab bar on long edges - if d := fyne.CurrentDevice(); d.IsMobile() { - if o := d.Orientation(); fyne.IsVertical(o) { - if l == TabLocationLeading { - return TabLocationTop - } else if l == TabLocationTrailing { - return TabLocationBottom - } - } else { - if l == TabLocationTop { - return TabLocationLeading - } else if l == TabLocationBottom { - return TabLocationTrailing - } + if o := fyne.CurrentDevice().Orientation(); fyne.IsVertical(o) { + if l == TabLocationLeading { + return TabLocationTop + } else if l == TabLocationTrailing { + return TabLocationBottom + } + } else { + if l == TabLocationTop { + return TabLocationLeading + } else if l == TabLocationBottom { + return TabLocationTrailing } } @@ -696,7 +699,7 @@ func (r *tabButtonRenderer) Refresh() { r.icon.Hide() } - if d := fyne.CurrentDevice(); r.button.onClosed != nil && (d.IsMobile() || r.button.hovered || r.close.hovered) { + if r.button.onClosed != nil && (build.IsMobile() || r.button.hovered || r.close.hovered) { r.close.Show() } else { r.close.Hide() diff --git a/driver/software/render_test.go b/driver/software/render_test.go index aa10608990..d24eae4850 100644 --- a/driver/software/render_test.go +++ b/driver/software/render_test.go @@ -4,9 +4,9 @@ import ( "image/color" "testing" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -45,7 +45,7 @@ func TestRenderCanvas(t *testing.T) { c := NewCanvas() c.SetContent(obj) - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { test.AssertImageMatches(t, "canvas_mobile.png", RenderCanvas(c, theme.LightTheme())) } else { test.AssertImageMatches(t, "canvas.png", RenderCanvas(c, theme.LightTheme())) diff --git a/internal/build/device_desktop.go b/internal/build/device_desktop.go new file mode 100644 index 0000000000..05b90928ce --- /dev/null +++ b/internal/build/device_desktop.go @@ -0,0 +1,9 @@ +//go:build !mobile && !js && !wasm +// +build !mobile,!js,!wasm + +package build + +// IsMobile returns true if running on a mobile device. +func IsMobile() bool { + return false +} diff --git a/internal/build/device_goxjs.go b/internal/build/device_goxjs.go new file mode 100644 index 0000000000..7912782e7f --- /dev/null +++ b/internal/build/device_goxjs.go @@ -0,0 +1,19 @@ +//go:build js || wasm +// +build js wasm + +package build + +import ( + "regexp" + "syscall/js" +) + +var isMobile = regexp.MustCompile("Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile") + +var userAgent = js.Global().Get("navigator").Get("userAgent").String() +var isMobile = isMobile.MatchString(userAgent) + +// IsMobile returns true if running on a mobile device. +func IsMobile() bool { + return isMobile +} diff --git a/internal/build/device_mobile.go b/internal/build/device_mobile.go new file mode 100644 index 0000000000..3262394fd3 --- /dev/null +++ b/internal/build/device_mobile.go @@ -0,0 +1,9 @@ +//go:build mobile +// +build mobile + +package build + +// IsMobile returns true if running on a mobile device. +func IsMobile() bool { + return true +} diff --git a/internal/driver/glfw/device.go b/internal/driver/glfw/device.go index 1d77ca8037..4ff78157b9 100644 --- a/internal/driver/glfw/device.go +++ b/internal/driver/glfw/device.go @@ -4,6 +4,7 @@ import ( "runtime" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/build" ) type glDevice struct { @@ -23,3 +24,7 @@ func (*glDevice) HasKeyboard() bool { func (*glDevice) IsBrowser() bool { return runtime.GOARCH == "js" || runtime.GOOS == "js" } + +func (*glDevice) IsMobile() bool { + return build.IsMobile() +} diff --git a/internal/driver/glfw/device_desktop.go b/internal/driver/glfw/device_desktop.go index 5d34ed7c76..ef9b50477d 100644 --- a/internal/driver/glfw/device_desktop.go +++ b/internal/driver/glfw/device_desktop.go @@ -9,10 +9,6 @@ import ( "fyne.io/fyne/v2" ) -func (*glDevice) IsMobile() bool { - return false -} - func (*glDevice) SystemScaleForWindow(w fyne.Window) float32 { if runtime.GOOS == "darwin" { return 1.0 // macOS scaling is done at the texture level diff --git a/internal/driver/glfw/device_goxjs.go b/internal/driver/glfw/device_goxjs.go index 1782820546..6776f02b71 100644 --- a/internal/driver/glfw/device_goxjs.go +++ b/internal/driver/glfw/device_goxjs.go @@ -4,22 +4,11 @@ package glfw import ( - "regexp" "syscall/js" "fyne.io/fyne/v2" ) -var isMobile = regexp.MustCompile("Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile") - -var navigator = js.Global().Get("navigator") -var userAgent = navigator.Get("userAgent").String() -var mobileCheck = isMobile.MatchString(userAgent) - -func (*glDevice) IsMobile() bool { - return mobileCheck -} - func (*glDevice) SystemScaleForWindow(w fyne.Window) float32 { // Get the scale information from the web browser directly return float32(js.Global().Get("devicePixelRatio").Float()) diff --git a/internal/widget/scroller.go b/internal/widget/scroller.go index e1e69ea54a..b984f566c3 100644 --- a/internal/widget/scroller.go +++ b/internal/widget/scroller.go @@ -4,6 +4,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/theme" ) @@ -407,7 +408,7 @@ func (s *Scroll) DragEnd() { // Dragged will scroll on any drag - bar or otherwise - for mobile func (s *Scroll) Dragged(e *fyne.DragEvent) { - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { return } diff --git a/test/device.go b/test/device.go index 628f60a853..97c5d44f27 100644 --- a/test/device.go +++ b/test/device.go @@ -4,6 +4,7 @@ import ( "runtime" "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/build" ) type device struct { @@ -31,3 +32,7 @@ func (d *device) SystemScaleForWindow(fyne.Window) float32 { func (*device) IsBrowser() bool { return runtime.GOARCH == "js" || runtime.GOOS == "js" } + +func (*device) IsMobile() bool { + return build.IsMobile() +} diff --git a/test/device_mobile.go b/test/device_mobile.go deleted file mode 100644 index 5702237931..0000000000 --- a/test/device_mobile.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build mobile -// +build mobile - -package test - -func (d *device) IsMobile() bool { - return true -} diff --git a/test/device_other.go b/test/device_other.go deleted file mode 100644 index 0c0275ba8c..0000000000 --- a/test/device_other.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !mobile -// +build !mobile - -package test - -func (d *device) IsMobile() bool { - return false -} diff --git a/test/test.go b/test/test.go index c675ad08b1..cfb99dbeb4 100644 --- a/test/test.go +++ b/test/test.go @@ -11,6 +11,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/driver" "fyne.io/fyne/v2/internal/painter/software" @@ -179,7 +180,7 @@ func LaidOutObjects(o fyne.CanvasObject) (objects []fyne.CanvasObject) { // MoveMouse simulates a mouse movement to the given position. func MoveMouse(c fyne.Canvas, pos fyne.Position) { - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { return } diff --git a/widget/button_test.go b/widget/button_test.go index 45e98b2ba9..929e49b5c4 100644 --- a/widget/button_test.go +++ b/widget/button_test.go @@ -6,6 +6,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -144,14 +145,14 @@ func TestButton_Hover(t *testing.T) { w := test.NewWindow(b) defer w.Close() - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { test.MoveMouse(w.Canvas(), fyne.NewPos(5, 5)) test.AssertImageMatches(t, "button/hovered.png", w.Canvas().Capture()) } b.Importance = widget.HighImportance b.Refresh() - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { test.AssertImageMatches(t, "button/high_importance_hovered.png", w.Canvas().Capture()) test.MoveMouse(w.Canvas(), fyne.NewPos(0, 0)) diff --git a/widget/check.go b/widget/check.go index 19d7dbced4..25356c96bd 100644 --- a/widget/check.go +++ b/widget/check.go @@ -8,6 +8,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -187,7 +188,7 @@ func (c *Check) MouseMoved(*desktop.MouseEvent) { // Tapped is called when a pointer tapped event is captured and triggers any change handler func (c *Check) Tapped(*fyne.PointEvent) { - if !c.focused && !fyne.CurrentDevice().IsMobile() { + if !c.focused && !build.IsMobile() { impl := c.super() if c := fyne.CurrentApp().Driver().CanvasForObject(impl); c != nil { diff --git a/widget/check_internal_test.go b/widget/check_internal_test.go index 6047db9ac1..fda2faf61f 100644 --- a/widget/check_internal_test.go +++ b/widget/check_internal_test.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/assert" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/test" "fyne.io/fyne/v2/theme" ) @@ -139,7 +139,7 @@ func TestCheck_Focused(t *testing.T) { assert.Equal(t, color.Transparent, render.focusIndicator.FillColor) test.Tap(check) - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { assert.False(t, check.focused) } else { assert.True(t, check.focused) @@ -151,7 +151,7 @@ func TestCheck_Focused(t *testing.T) { assert.Equal(t, color.Transparent, render.focusIndicator.FillColor) check.Enable() - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { assert.False(t, check.focused) } else { assert.True(t, check.focused) @@ -180,7 +180,7 @@ func TestCheck_Hovered(t *testing.T) { test.Tap(check) assert.True(t, check.hovered) - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { assert.Equal(t, theme.FocusColor(), render.focusIndicator.FillColor) } @@ -191,7 +191,7 @@ func TestCheck_Hovered(t *testing.T) { check.Enable() assert.True(t, check.hovered) - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { assert.Equal(t, theme.HoverColor(), render.focusIndicator.FillColor) } else { assert.Equal(t, theme.FocusColor(), render.focusIndicator.FillColor) @@ -199,7 +199,7 @@ func TestCheck_Hovered(t *testing.T) { check.MouseOut() assert.False(t, check.hovered) - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { assert.Equal(t, color.Transparent, render.focusIndicator.FillColor) } else { assert.Equal(t, theme.FocusColor(), render.focusIndicator.FillColor) @@ -217,7 +217,7 @@ func TestCheck_TypedRune(t *testing.T) { assert.False(t, check.Checked) test.Tap(check) - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { assert.True(t, check.focused) } assert.True(t, check.Checked) diff --git a/widget/entry.go b/widget/entry.go index e33e532b36..ffb9019196 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -13,6 +13,7 @@ import ( "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/driver/mobile" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" @@ -537,7 +538,7 @@ func (e *Entry) Append(text string) { // // Implements: fyne.Tappable func (e *Entry) Tapped(ev *fyne.PointEvent) { - if fyne.CurrentDevice().IsMobile() && e.selecting { + if build.IsMobile() && e.selecting { e.selecting = false } } diff --git a/widget/gridwrap.go b/widget/gridwrap.go index 8a782edd5e..771ed3477c 100644 --- a/widget/gridwrap.go +++ b/widget/gridwrap.go @@ -9,6 +9,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -528,7 +529,7 @@ func (l *gridWrapLayout) setupGridItem(li *gridWrapItem, id GridWrapItemID, focu f(id, li.child) } li.onTapped = func() { - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { l.list.RefreshItem(l.list.currentFocus) canvas := fyne.CurrentApp().Driver().CanvasForObject(l.list) if canvas != nil { diff --git a/widget/list.go b/widget/list.go index 0aeb686c31..56fc5fc35c 100644 --- a/widget/list.go +++ b/widget/list.go @@ -9,6 +9,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -611,7 +612,7 @@ func (l *listLayout) setupListItem(li *listItem, id ListItemID, focus bool) { f(id, li.child) } li.onTapped = func() { - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { canvas := fyne.CurrentApp().Driver().CanvasForObject(l.list) if canvas != nil { canvas.Focus(l.list) diff --git a/widget/menu_item.go b/widget/menu_item.go index 9c381509e4..d60034c016 100644 --- a/widget/menu_item.go +++ b/widget/menu_item.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -144,7 +145,7 @@ func (i *menuItem) Tapped(*fyne.PointEvent) { return } if i.Item.Action == nil { - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { i.activate() } return @@ -295,7 +296,7 @@ func (r *menuItemRenderer) MinSize() fyne.Size { func (r *menuItemRenderer) updateVisuals() { r.background.CornerRadius = theme.SelectionRadiusSize() - if fyne.CurrentDevice().IsMobile() { + if build.IsMobile() { r.background.Hide() } else if r.i.isActive() { r.background.FillColor = theme.FocusColor() diff --git a/widget/popup_menu.go b/widget/popup_menu.go index 8cf2ecf96b..5183f28a3b 100644 --- a/widget/popup_menu.go +++ b/widget/popup_menu.go @@ -2,6 +2,7 @@ package widget import ( "fyne.io/fyne/v2" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/widget" ) @@ -94,7 +95,7 @@ func (p *PopUpMenu) Show() { p.overlay.Show() p.Menu.Show() - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { p.canvas.Focus(p) } } diff --git a/widget/radio_item.go b/widget/radio_item.go index c387a9b38e..84ad97aa99 100644 --- a/widget/radio_item.go +++ b/widget/radio_item.go @@ -6,6 +6,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -115,7 +116,7 @@ func (i *radioItem) SetSelected(selected bool) { // // Implements: fyne.Tappable func (i *radioItem) Tapped(_ *fyne.PointEvent) { - if !i.focused && !fyne.CurrentDevice().IsMobile() { + if !i.focused && !build.IsMobile() { impl := i.super() if c := fyne.CurrentApp().Driver().CanvasForObject(impl); c != nil { diff --git a/widget/slider.go b/widget/slider.go index d799c253a9..5fc68e4052 100644 --- a/widget/slider.go +++ b/widget/slider.go @@ -9,6 +9,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" ) @@ -104,7 +105,7 @@ func (s *Slider) Dragged(e *fyne.DragEvent) { // Since: 2.4 func (s *Slider) Tapped(e *fyne.PointEvent) { driver := fyne.CurrentApp().Driver() - if !s.focused && !driver.Device().IsMobile() { + if !s.focused && !build.IsMobile() { impl := s.super() if c := driver.CanvasForObject(impl); c != nil { diff --git a/widget/table.go b/widget/table.go index 41b8c15e99..6386754e55 100644 --- a/widget/table.go +++ b/widget/table.go @@ -8,6 +8,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/driver/desktop" "fyne.io/fyne/v2/driver/mobile" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" @@ -558,7 +559,7 @@ func (t *Table) Tapped(e *fyne.PointEvent) { } t.Select(TableCellID{row, col}) - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { t.RefreshItem(t.currentFocus) canvas := fyne.CurrentApp().Driver().CanvasForObject(t) if canvas != nil { diff --git a/widget/tree.go b/widget/tree.go index bd71c2efb7..c548c3210b 100644 --- a/widget/tree.go +++ b/widget/tree.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/driver/desktop" + "fyne.io/fyne/v2/internal/build" "fyne.io/fyne/v2/internal/cache" "fyne.io/fyne/v2/internal/widget" "fyne.io/fyne/v2/theme" @@ -883,7 +884,7 @@ func (n *treeNode) Tapped(*fyne.PointEvent) { } n.tree.Select(n.uid) - if !fyne.CurrentDevice().IsMobile() { + if !build.IsMobile() { canvas := fyne.CurrentApp().Driver().CanvasForObject(n.tree) if canvas != nil { canvas.Focus(n.tree)