|
| 1 | +// Copyright (c) 2021, The Grid Authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style |
| 3 | +// license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +package main |
| 6 | + |
| 7 | +import ( |
| 8 | + "fmt" |
| 9 | + |
| 10 | + "github.com/goki/gi/gi" |
| 11 | + "github.com/goki/gi/gimain" |
| 12 | + "github.com/goki/gi/gist" |
| 13 | + "github.com/goki/gi/giv" |
| 14 | + "github.com/goki/gi/svg" |
| 15 | + "github.com/goki/gi/units" |
| 16 | + "github.com/goki/grid/grid" |
| 17 | + "github.com/goki/ki/ki" |
| 18 | + "github.com/mitchellh/go-homedir" |
| 19 | +) |
| 20 | + |
| 21 | +func main() { |
| 22 | + gimain.Main(func() { |
| 23 | + mainrun() |
| 24 | + }) |
| 25 | +} |
| 26 | + |
| 27 | +var CurFilename = "" |
| 28 | +var TheSVG *grid.GridView |
| 29 | +var TheZoom *gi.SpinBox |
| 30 | +var TheTransX *gi.SpinBox |
| 31 | +var TheTransY *gi.SpinBox |
| 32 | +var TheFile *gi.TextField |
| 33 | + |
| 34 | +func SetZoom(zf float32) { |
| 35 | + TheSVG.Scale = zf |
| 36 | + TheZoom.SetValue(zf) |
| 37 | + TheSVG.SetTransform() |
| 38 | +} |
| 39 | + |
| 40 | +func SetTrans(xt, yt float32) { |
| 41 | + TheSVG.Trans.Set(xt, yt) |
| 42 | + TheTransX.SetValue(xt) |
| 43 | + TheTransY.SetValue(yt) |
| 44 | + TheSVG.SetTransform() |
| 45 | +} |
| 46 | + |
| 47 | +func OpenSVG(fnm string) { |
| 48 | + CurFilename = fnm |
| 49 | + TheFile.SetText(CurFilename) |
| 50 | + updt := TheSVG.UpdateStart() |
| 51 | + TheSVG.SetFullReRender() |
| 52 | + fmt.Printf("Opening: %v\n", CurFilename) |
| 53 | + TheSVG.OpenXML(CurFilename) |
| 54 | + SetZoom(TheSVG.ParentWindow().LogicalDPI() / 96.0) |
| 55 | + SetTrans(0, 0) |
| 56 | + TheSVG.UpdateEnd(updt) |
| 57 | +} |
| 58 | + |
| 59 | +func FileViewOpenSVG(vp *gi.Viewport2D) { |
| 60 | + giv.FileViewDialog(vp, CurFilename, ".svg", giv.DlgOpts{Title: "Open SVG"}, nil, |
| 61 | + vp.Win, func(recv, send ki.Ki, sig int64, data interface{}) { |
| 62 | + if sig == int64(gi.DialogAccepted) { |
| 63 | + dlg, _ := send.(*gi.Dialog) |
| 64 | + OpenSVG(giv.FileViewDialogValue(dlg)) |
| 65 | + } |
| 66 | + }) |
| 67 | +} |
| 68 | + |
| 69 | +func mainrun() { |
| 70 | + width := 1600 |
| 71 | + height := 1200 |
| 72 | + |
| 73 | + gi.SetAppName("svg") |
| 74 | + gi.SetAppAbout(`This is a demo of the SVG rendering (and start on editing) in the <b>GoGi</b> graphical interface system, within the <b>GoKi</b> tree framework. See <a href="https://github.com/goki">GoKi on GitHub</a> |
| 75 | +<p>You can drag the image around and use the scroll wheel to zoom.</p>`) |
| 76 | + |
| 77 | + win := gi.NewMainWindow("gogi-svg-viewer", "GoGi SVG Viewer", width, height) |
| 78 | + |
| 79 | + vp := win.WinViewport2D() |
| 80 | + updt := vp.UpdateStart() |
| 81 | + |
| 82 | + mfr := win.SetMainFrame() |
| 83 | + |
| 84 | + tbar := gi.AddNewToolBar(mfr, "tbar") |
| 85 | + tbar.SetStretchMaxWidth() |
| 86 | + |
| 87 | + svgrow := gi.AddNewLayout(mfr, "svgrow", gi.LayoutHoriz) |
| 88 | + svgrow.SetProp("horizontal-align", "center") |
| 89 | + svgrow.SetProp("margin", 2.0) // raw numbers = px = 96 dpi pixels |
| 90 | + svgrow.SetStretchMaxWidth() |
| 91 | + svgrow.SetStretchMaxHeight() |
| 92 | + |
| 93 | + svge := grid.AddNewGridView(svgrow, "svg") |
| 94 | + TheSVG = svge |
| 95 | + svge.InitScale() |
| 96 | + svge.Fill = true |
| 97 | + svge.SetProp("background-color", "white") |
| 98 | + svge.SetProp("width", units.NewPx(float32(width-20))) |
| 99 | + svge.SetProp("height", units.NewPx(float32(height-100))) |
| 100 | + svge.SetStretchMaxWidth() |
| 101 | + svge.SetStretchMaxHeight() |
| 102 | + |
| 103 | + loads := tbar.AddAction(gi.ActOpts{Label: "Open SVG", Icon: "file-open"}, win.This(), |
| 104 | + func(recv, send ki.Ki, sig int64, data interface{}) { |
| 105 | + FileViewOpenSVG(vp) |
| 106 | + }) |
| 107 | + loads.StartFocus() |
| 108 | + |
| 109 | + fnm := gi.AddNewTextField(tbar, "cur-fname") |
| 110 | + TheFile = fnm |
| 111 | + fnm.SetMinPrefWidth(units.NewCh(60)) |
| 112 | + |
| 113 | + zmlb := gi.AddNewLabel(tbar, "zmlb", "Zoom: ") |
| 114 | + zmlb.SetProp("vertical-align", gist.AlignMiddle) |
| 115 | + zmlb.Tooltip = "zoom scaling factor -- can use mouse scrollwheel to zoom as well" |
| 116 | + |
| 117 | + zoomout := tbar.AddAction(gi.ActOpts{Icon: "zoom-out", Name: "zoomout", Tooltip: "zoom out"}, |
| 118 | + win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 119 | + SetZoom(svge.Scale * 0.9) |
| 120 | + win.FullReRender() |
| 121 | + }) |
| 122 | + zoomout.SetProp("margin", 0) |
| 123 | + zoomout.SetProp("padding", 0) |
| 124 | + zoomout.SetProp("#icon", ki.Props{ |
| 125 | + "width": units.NewEm(1.5), |
| 126 | + "height": units.NewEm(1.5), |
| 127 | + }) |
| 128 | + zoom := gi.AddNewSpinBox(tbar, "zoom") |
| 129 | + // zoom.SetMinPrefWidth(units.NewEm(10)) |
| 130 | + zoom.SetValue(svge.Scale) |
| 131 | + zoom.Tooltip = "zoom scaling factor -- can use mouse scrollwheel to zoom as well" |
| 132 | + TheZoom = zoom |
| 133 | + zoom.SpinBoxSig.Connect(win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 134 | + sp := send.(*gi.SpinBox) |
| 135 | + SetZoom(sp.Value) |
| 136 | + win.FullReRender() |
| 137 | + }) |
| 138 | + |
| 139 | + zoomin := tbar.AddAction(gi.ActOpts{Icon: "zoom-in", Name: "zoomin", Tooltip: " zoom in"}, |
| 140 | + win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 141 | + SetZoom(svge.Scale * 1.1) |
| 142 | + win.FullReRender() |
| 143 | + }) |
| 144 | + zoomin.SetProp("margin", 0) |
| 145 | + zoomin.SetProp("padding", 0) |
| 146 | + zoomin.SetProp("#icon", ki.Props{ |
| 147 | + "width": units.NewEm(1.5), |
| 148 | + "height": units.NewEm(1.5), |
| 149 | + }) |
| 150 | + |
| 151 | + gi.AddNewSpace(tbar, "spctr") |
| 152 | + trlb := gi.AddNewLabel(tbar, "trlb", "Translate: ") |
| 153 | + trlb.Tooltip = "Translation of overall image -- can use mouse drag to move as well" |
| 154 | + trlb.SetProp("vertical-align", gist.AlignMiddle) |
| 155 | + |
| 156 | + trx := gi.AddNewSpinBox(tbar, "trx") |
| 157 | + // zoom.SetMinPrefWidth(units.NewEm(10)) |
| 158 | + trx.SetValue(svge.Trans.X) |
| 159 | + TheTransX = trx |
| 160 | + trx.SpinBoxSig.Connect(win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 161 | + SetTrans(trx.Value, svge.Trans.Y) |
| 162 | + win.FullReRender() |
| 163 | + }) |
| 164 | + |
| 165 | + try := gi.AddNewSpinBox(tbar, "try") |
| 166 | + // zoom.SetMinPrefWidth(units.NewEm(10)) |
| 167 | + try.SetValue(svge.Trans.Y) |
| 168 | + TheTransY = try |
| 169 | + try.SpinBoxSig.Connect(win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 170 | + SetTrans(svge.Trans.X, try.Value) |
| 171 | + win.FullReRender() |
| 172 | + }) |
| 173 | + |
| 174 | + fnm.TextFieldSig.Connect(win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 175 | + if sig == int64(gi.TextFieldDone) { |
| 176 | + tf := send.(*gi.TextField) |
| 177 | + fn, _ := homedir.Expand(tf.Text()) |
| 178 | + OpenSVG(fn) |
| 179 | + } |
| 180 | + }) |
| 181 | + |
| 182 | + svge.NodeSig.Connect(win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 183 | + ssvg := send.Embed(svg.KiT_Editor).(*grid.GridView) |
| 184 | + SetZoom(ssvg.Scale) |
| 185 | + SetTrans(ssvg.Trans.X, ssvg.Trans.Y) |
| 186 | + }) |
| 187 | + |
| 188 | + vp.UpdateEndNoSig(updt) |
| 189 | + |
| 190 | + // main menu |
| 191 | + appnm := gi.AppName() |
| 192 | + mmen := win.MainMenu |
| 193 | + mmen.ConfigMenus([]string{appnm, "File", "Edit", "Window"}) |
| 194 | + |
| 195 | + amen := win.MainMenu.ChildByName(appnm, 0).(*gi.Action) |
| 196 | + amen.Menu = make(gi.Menu, 0, 10) |
| 197 | + amen.Menu.AddAppMenu(win) |
| 198 | + |
| 199 | + emen := win.MainMenu.ChildByName("Edit", 1).(*gi.Action) |
| 200 | + emen.Menu = make(gi.Menu, 0, 10) |
| 201 | + emen.Menu.AddCopyCutPaste(win) |
| 202 | + |
| 203 | + // note: Command in shortcuts is automatically translated into Control for |
| 204 | + // Linux, Windows or Meta for MacOS |
| 205 | + fmen := win.MainMenu.ChildByName("File", 0).(*gi.Action) |
| 206 | + fmen.Menu = make(gi.Menu, 0, 10) |
| 207 | + fmen.Menu.AddAction(gi.ActOpts{Label: "Open", Shortcut: "Command+O"}, |
| 208 | + win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 209 | + FileViewOpenSVG(vp) |
| 210 | + }) |
| 211 | + fmen.Menu.AddSeparator("csep") |
| 212 | + fmen.Menu.AddAction(gi.ActOpts{Label: "Close Window", Shortcut: "Command+W"}, |
| 213 | + win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { |
| 214 | + win.OSWin.Close() |
| 215 | + }) |
| 216 | + |
| 217 | + win.SetCloseCleanFunc(func(w *gi.Window) { |
| 218 | + go gi.Quit() // once main window is closed, quit |
| 219 | + }) |
| 220 | + |
| 221 | + // todo: when saving works, add option to save, and change above to CloseReq |
| 222 | + |
| 223 | + win.MainMenuUpdated() |
| 224 | + |
| 225 | + win.StartEventLoop() |
| 226 | +} |
0 commit comments