Compare commits

...

30 Commits

Author SHA1 Message Date
Sasha Koshka a9fc52c55b Change clip behaviors to sub behaviors
Remedies #4
2024-05-15 01:37:21 -04:00
Sasha Koshka e745e80f09 Add more information to README.md 2024-05-14 12:43:40 -04:00
Sasha Koshka 748996c789 Be more descriptive with what a path is 2024-05-14 12:34:42 -04:00
Sasha Koshka d4aac7e26c Set CapRound as the default cap style 2024-05-14 12:32:44 -04:00
Sasha Koshka 3d645b8064 Tweak doc comments for canvas.Pen 2024-05-14 12:32:09 -04:00
Sasha Koshka bde1a2bc34 Remove wierd spacing from box interface definitions
Seemed like a good idea at the time
2024-05-14 12:20:44 -04:00
Sasha Koshka d43ba6b1af Replace Window's Show/Hide methods with Visible/SetVisible 2024-05-14 12:18:21 -04:00
Sasha Koshka 096c1b5e1b Add Visible() and SetVisible() to Box 2024-05-14 12:17:14 -04:00
Sasha Koshka c44ff4a34a Change ContainerBox.Delete() to Remove()
Remedy #3
2024-05-14 12:11:00 -04:00
Sasha Koshka dc02f4dfb4 Remedy #1 2024-05-14 12:09:34 -04:00
Sasha Koshka 7c30b2bac0 Add requirement for ContainerBox.Add to remove a previously
parented object first
2024-05-14 12:03:10 -04:00
Sasha Koshka 24264bbc91 Fix capitalization errors with previous commit 2024-05-14 11:58:48 -04:00
Sasha Koshka f167af3281 Describe the canvas used by CanvasBox in detail 2024-05-14 11:57:48 -04:00
Sasha Koshka 9a5b4ee7e8 Add home icon 2024-05-05 02:53:07 -04:00
Sasha Koshka 3e561d7bf0 Fix wording of theme.Theme doc comment 2024-05-03 13:46:50 -04:00
Sasha Koshka b96e8f744f Namespace icon IDs 2024-05-03 13:21:35 -04:00
Sasha Koshka 9aa6f2900e Added application role icons 2024-05-03 13:10:44 -04:00
Sasha Koshka a3fc0ce66d Remove ApplicationIcon from Theme
Since Icon can now take in arbitrary strings, we can just have it
serve application icons as well.
2024-05-03 13:08:14 -04:00
Sasha Koshka 65bf341514 Icon IDs are now strings 2024-05-03 13:07:27 -04:00
Sasha Koshka 042f2f0131 Completely remove plugin system
Plugins may be moved to Nasin
2024-04-30 13:12:34 -04:00
Sasha Koshka 4fd5e54e42 Add editorconfig 2024-04-29 16:23:46 -04:00
Sasha Koshka 9a9e546b37 Remove application framework stuff 2024-04-29 00:39:17 -04:00
Sasha Koshka a2a5c16e38 Changed the semantics of ContentBounds 2023-09-14 14:47:33 -04:00
Sasha Koshka 28cd889254 Removed tiler for now, needs to be rethought a bit 2023-09-08 20:57:15 -04:00
Sasha Koshka e682fdd9d8 Add icon for switch 2023-09-08 20:57:00 -04:00
Sasha Koshka 9719391e5d NewApplicationWindow returns MainWindow nows 2023-09-08 16:29:03 -04:00
Sasha Koshka 8a531986eb What??? 2023-09-07 18:25:35 -04:00
Sasha Koshka c3c6ff61f5 Add Tiler interface 2023-09-05 18:14:36 -04:00
Sasha Koshka 89f7bf47ce Add ability to create an undecorated window 2023-09-05 13:21:59 -04:00
Sasha Koshka bebd58dac1 Added event capturing to containers 2023-09-05 13:10:35 -04:00
13 changed files with 370 additions and 853 deletions

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 8
charset = utf-8
[*.md]
indent_style = space
indent_size = 2

View File

@ -2,4 +2,7 @@
[![Go Reference](https://pkg.go.dev/badge/git.tebibyte.media/tomo/tomo.svg)](https://pkg.go.dev/git.tebibyte.media/tomo/tomo) [![Go Reference](https://pkg.go.dev/badge/git.tebibyte.media/tomo/tomo.svg)](https://pkg.go.dev/git.tebibyte.media/tomo/tomo)
Tomo is a lightweight GUI toolkit written in pure Go. Tomo is a lightweight GUI toolkit written in pure Go. This repository defines
the API that other components of the toolkit agree on. In order to use Tomo in
an application, use [Nasin](https://git.tebibyte.media/tomo/nasin), which builds
an application framework on top of Tomo.

View File

@ -1,113 +0,0 @@
package tomo
import "image"
// Application represents an application object.
type Application interface {
// Describe returns a description of the application.
Describe () ApplicationDescription
// Init performs the initial setup of the application.
Init ()
}
// ApplicationDescription describes the name and type of an application.
type ApplicationDescription struct {
// The name or ID of the application.
Name string
// Role describes what the application does.
Role ApplicationRole
}
// String satisfies the fmt.Stringer interface.
func (application ApplicationDescription) String () string {
if application.Name == "" {
return application.Role.String()
} else {
return application.Name
}
}
// ApplicationRole describes what an application does.
type ApplicationRole int; const (
RoleUnknown ApplicationRole = iota
RoleWebBrowser
RoleMesssanger
RolePhone
RoleMail
RoleTerminalEmulator
RoleFileBrowser
RoleTextEditor
RoleDocumentViewer
RoleWordProcessor
RoleSpreadsheet
RoleSlideshow
RoleCalculator
RolePreferences
RoleProcessManager
RoleSystemInformation
RoleManual
RoleCamera
RoleImageViewer
RoleMediaPlayer
RoleImageEditor
RoleAudioEditor
RoleVideoEditor
RoleClock
RoleCalendar
RoleChecklist
)
// String satisfies the fmt.Stringer interface.
func (role ApplicationRole) String () string {
switch role {
case RoleWebBrowser: return "Web Browser"
case RoleMesssanger: return "Messsanger"
case RolePhone: return "Phone"
case RoleMail: return "Mail"
case RoleTerminalEmulator: return "Terminal Emulator"
case RoleFileBrowser: return "File Browser"
case RoleTextEditor: return "Text Editor"
case RoleDocumentViewer: return "Document Viewer"
case RoleWordProcessor: return "Word Processor"
case RoleSpreadsheet: return "Spreadsheet"
case RoleSlideshow: return "Slideshow"
case RoleCalculator: return "Calculator"
case RolePreferences: return "Preferences"
case RoleProcessManager: return "Process Manager"
case RoleSystemInformation: return "System Information"
case RoleManual: return "Manual"
case RoleCamera: return "Camera"
case RoleImageViewer: return "Image Viewer"
case RoleMediaPlayer: return "Media Player"
case RoleImageEditor: return "Image Editor"
case RoleAudioEditor: return "Audio Editor"
case RoleVideoEditor: return "Video Editor"
case RoleClock: return "Clock"
case RoleCalendar: return "Calendar"
case RoleChecklist: return "Checklist"
default: return "unknown"
}
}
// RunApplication is like Run, but runs an application.
func RunApplication (application Application) error {
return Run(application.Init)
}
// NewApplicationWindow creates a window for an application. It will
// automatically set window information to signal to the OS that the window is
// owned by the application.
func NewApplicationWindow (application Application, bounds image.Rectangle) (Window, error) {
window, err := NewWindow(bounds)
if err != nil { return nil, err }
window.SetTitle(application.Describe().String())
return window, nil
}

View File

@ -11,12 +11,19 @@ import "git.tebibyte.media/tomo/tomo/canvas"
type Backend interface { type Backend interface {
// These methods create new objects. The backend must reject any object // These methods create new objects. The backend must reject any object
// that was not made by it. // that was not made by it.
NewWindow (image.Rectangle) (MainWindow, error)
NewBox () Box NewBox () Box
NewTextBox () TextBox NewTextBox () TextBox
NewCanvasBox () CanvasBox NewCanvasBox () CanvasBox
NewContainerBox () ContainerBox NewContainerBox () ContainerBox
// NewWindow creates a normal MainWindow and returns it.
NewWindow (image.Rectangle) (MainWindow, error)
// NewPlainWindow creates an undecorated window that does not appear in
// window lists and returns it. This is intended for making things like
// panels, docks, etc.
NewPlainWindow (image.Rectangle) (MainWindow, error)
// NewTexture creates a new texture from an image. The backend must // NewTexture creates a new texture from an image. The backend must
// reject any texture that was not made by it. // reject any texture that was not made by it.
NewTexture (image.Image) canvas.TextureCloser NewTexture (image.Image) canvas.TextureCloser

View File

@ -8,9 +8,9 @@ import "image/color"
// Cap represents a stroke cap type. // Cap represents a stroke cap type.
type Cap int; const ( type Cap int; const (
CapButt Cap = iota // Square cap that ends at the point CapRound Cap = iota // Round cap that surrounds the point
CapRound // Round cap that surrounds the point CapSquare // Square cap that surrounds the point
CapSquare // square cap that surrounds the point CapButt // Square cap that ends at the point
) )
// Joint represents a stroke joint type. // Joint represents a stroke joint type.
@ -30,23 +30,38 @@ type StrokeAlign int; const (
// Pen represents a drawing context that is linked to a canvas. Each canvas can // Pen represents a drawing context that is linked to a canvas. Each canvas can
// have multiple pens associated with it, each maintaining their own drawing // have multiple pens associated with it, each maintaining their own drawing
// context. // state.
type Pen interface { type Pen interface {
// Rectangle draws a rectangle // Rectangle draws a rectangle.
Rectangle (image.Rectangle) Rectangle (image.Rectangle)
// Path draws a path // Path draws a path, which is a series of connected points.
Path (points ...image.Point) Path (points ...image.Point)
Closed (bool) // if the path is closed // StrokeWeight sets how thick the stroke is. The default value is zero.
Cap (Cap) // line cap stype StrokeWeight (int)
Joint (Joint) // line joint style // SetClosed sets whether the path is a closed shape, or has an open
StrokeWeight (int) // how thick the stroke is // side. This only applies if the stroke weight is greater than zero.
StrokeAlign (StrokeAlign) // where the stroke is drawn Closed (bool)
// Cap sets how the ends of the stroke look. This only applies if the
// stroke weight is greater than zero, and if the path is not closed.
// The default value is CapRound.
Cap (Cap)
// Joint sets how bend points in the stroke look. This only applies if
// the stroke weight is greater than zero. The default value is
// JointRound.
Joint (Joint)
// StrokeAlign sets where the stroke is drawn in relation to the path.
// This only applies if the stroke weight is greater than zero. The
// default value is StrokeAlignCenter.
StrokeAlign (StrokeAlign)
Stroke (color.Color) // Sets the stroke to a solid color // Stroke sets the stroke to a solid color.
Fill (color.Color) // Sets the fill to a solid color Stroke (color.Color)
Texture (Texture) // Overlaps a texture onto the fill color // Fill sets the fill to a solid color.
Fill (color.Color)
// Texture overlaps a texture onto the fill color.
Texture (Texture)
} }
// Canvas is an image that supports drawing paths. // Canvas is an image that supports drawing paths.
@ -56,8 +71,10 @@ type Canvas interface {
// Pen returns a new pen for this canvas. // Pen returns a new pen for this canvas.
Pen () Pen Pen () Pen
// Clip returns a new canvas that points to a specific area of this one. // SubCanvas returns a returns a Canvas representing the portion of this
Clip (image.Rectangle) Canvas // Canvas visible and drawable through a rectangle. The returned value
// shares pixels with the original Canvas.
SubCanvas (image.Rectangle) Canvas
} }
// Drawer is an object that can draw to a canvas. // Drawer is an object that can draw to a canvas.

View File

@ -7,9 +7,10 @@ import "image"
type Texture interface { type Texture interface {
image.Image image.Image
// Clip returns a smaller section of this texture, pointing to the same // SubTexture returns a returns a Texture representing the portion of
// internal data. // this Texture visible through a rectangle. The returned value shares
Clip (image.Rectangle) Texture // pixels with the original Texture.
SubTexture (image.Rectangle) Texture
} }
// TextureCloser is a texture that can be closed. Anything that receives a // TextureCloser is a texture that can be closed. Anything that receives a

139
object.go
View File

@ -101,7 +101,7 @@ type Align int; const (
AlignEven // similar to justified text AlignEven // similar to justified text
) )
// Object is any obscreen object. Each object must be linked to a box, even if // Object is any onscreen object. Each object must be linked to a box, even if
// it is that box. // it is that box.
type Object interface { type Object interface {
GetBox () Box GetBox () Box
@ -112,13 +112,13 @@ type Box interface {
Object Object
// Window returns the Window this Box is a part of. // Window returns the Window this Box is a part of.
Window () Window Window () Window
// Bounds returns the outer bounding rectangle of the Box relative to // Bounds returns the outer bounding rectangle of the Box relative to
// the Window. // the Window.
Bounds () image.Rectangle Bounds () image.Rectangle
// InnerBounds returns the inner bounding rectangle of the box. It is // InnerBounds returns the inner bounding rectangle of the box. It is
// the value of Bounds inset by the Box's border and padding. // the value of Bounds inset by the Box's border and padding.
InnerBounds () image.Rectangle InnerBounds () image.Rectangle
// MinimumSize returns the minimum width and height this Box's bounds // MinimumSize returns the minimum width and height this Box's bounds
// can be set to. This will return the value of whichever of these is // can be set to. This will return the value of whichever of these is
// greater: // greater:
@ -126,30 +126,36 @@ type Box interface {
// - The size taken up by the Box's border and padding. If there is // - The size taken up by the Box's border and padding. If there is
// internal content that does not overflow, the size of that is also // internal content that does not overflow, the size of that is also
// taken into account here. // taken into account here.
MinimumSize () image.Point MinimumSize () image.Point
// SetBounds sets the bounding rectangle of this Box relative to the // SetBounds sets the bounding rectangle of this Box relative to the
// Window. // Window.
SetBounds (image.Rectangle) SetBounds (image.Rectangle)
// SetColor sets the background color of this Box. // SetColor sets the background color of this Box.
SetColor (color.Color) SetColor (color.Color)
// SetTexture sets a repeating background texture. If the texture is // SetTexture sets a repeating background texture. If the texture is
// transparent, it will be overlayed atop the color specified by // transparent, it will be overlayed atop the color specified by
// SetColor(). // SetColor().
SetTexture (canvas.Texture) SetTexture (canvas.Texture)
// SetBorder sets the Border(s) of the box. The first Border will be the // SetBorder sets the Border(s) of the box. The first Border will be the
// most outset, and the last Border will be the most inset. // most outset, and the last Border will be the most inset.
SetBorder (...Border) SetBorder (...Border)
// SetMinimumSize sets the minimum width and height of the box, as // SetMinimumSize sets the minimum width and height of the box, as
// described in MinimumSize. // described in MinimumSize.
SetMinimumSize (image.Point) SetMinimumSize (image.Point)
// SetPadding sets the padding between the Box's innermost Border and // SetPadding sets the padding between the Box's innermost Border and
// its content. // its content.
SetPadding (Inset) SetPadding (Inset)
// SetVisible sets whether or not this box is visible. If invisible,
// it will not be drawn and no space will be created for it in the
// layout. Boxes are visible by default.
SetVisible (bool)
// Visible returns whether or not this box is visible.
Visible () bool
// SetDNDData sets the data that will be picked up if this Box is // SetDNDData sets the data that will be picked up if this Box is
// dragged. If this is nil (which is the default), this Box will not be // dragged. If this is nil (which is the default), this Box will not be
// picked up. // picked up.
SetDNDData (data.Data) SetDNDData (data.Data)
// SetDNDAccept sets the type of data that can be dropped onto this Box. // SetDNDAccept sets the type of data that can be dropped onto this Box.
// If this is nil (which is the default), this Box will reject all // If this is nil (which is the default), this Box will reject all
// drops. // drops.
@ -157,16 +163,16 @@ type Box interface {
// SetFocused sets whether or not this Box has keyboard focus. If set to // SetFocused sets whether or not this Box has keyboard focus. If set to
// true, this method will steal focus away from whichever Object // true, this method will steal focus away from whichever Object
// currently has focus. // currently has focus.
SetFocused (bool) SetFocused (bool)
// SetFocusable sets whether or not this Box can receive keyboard focus. // SetFocusable sets whether or not this Box can receive keyboard focus.
// If set to false and the Box is already focused. the focus is removed. // If set to false and the Box is already focused. the focus is removed.
SetFocusable (bool) SetFocusable (bool)
// Focused returns whether or not this Box has keyboard focus. // Focused returns whether or not this Box has keyboard focus.
Focused () bool Focused () bool
// Modifiers returns which modifier keys on the keyboard are currently // Modifiers returns which modifier keys on the keyboard are currently
// being held down. // being held down.
Modifiers () input.Modifiers Modifiers () input.Modifiers
// MousePosition returns the position of the mouse pointer relative to // MousePosition returns the position of the mouse pointer relative to
// the Window. // the Window.
MousePosition () image.Point MousePosition () image.Point
@ -195,8 +201,13 @@ type CanvasBox interface {
Box Box
// SetDrawer sets the Drawer that will be called upon to draw the Box's // SetDrawer sets the Drawer that will be called upon to draw the Box's
// content when it is invalidated. // content when it is invalidated. The Canvas passed to the drawer will
SetDrawer (canvas.Drawer) // have these properties:
// - It will have the same origin (0, 0) as the window which contains
// the CanvasBox
// - The Canvas bounds will describe the portion of the CanvasBox
// visible on screen
SetDrawer (canvas.Drawer)
// Invalidate causes the Box's area to be redrawn at the end of the // Invalidate causes the Box's area to be redrawn at the end of the
// event cycle, even if it wouldn't be otherwise. // event cycle, even if it wouldn't be otherwise.
@ -211,16 +222,16 @@ type ContentBox interface {
// SetOverflow sets whether or not the Box's content overflows // SetOverflow sets whether or not the Box's content overflows
// horizontally and vertically. Overflowing content is clipped to the // horizontally and vertically. Overflowing content is clipped to the
// bounds of the Box inset by all Borders (but not padding). // bounds of the Box inset by all Borders (but not padding).
SetOverflow (horizontal, vertical bool) SetOverflow (horizontal, vertical bool)
// SetAlign sets how the Box's content is distributed horizontally and // SetAlign sets how the Box's content is distributed horizontally and
// vertically. // vertically.
SetAlign (x, y Align) SetAlign (x, y Align)
// ContentBounds returns the bounds of the inner content of the Box // ContentBounds returns the bounds of the inner content of the Box
// relative to the window. // relative to the Box's InnerBounds.
ContentBounds () image.Rectangle ContentBounds () image.Rectangle
// ScrollTo shifts the origin of the Box's content to the origin of the // ScrollTo shifts the origin of the Box's content to the origin of the
// Box's InnerBounds, offset by the given point. // Box's InnerBounds, offset by the given point.
ScrollTo (image.Point) ScrollTo (image.Point)
// OnContentBoundsChange specifies a function to be called when the // OnContentBoundsChange specifies a function to be called when the
// Box's ContentBounds or InnerBounds changes. // Box's ContentBounds or InnerBounds changes.
OnContentBoundsChange (func ()) event.Cookie OnContentBoundsChange (func ()) event.Cookie
@ -231,26 +242,26 @@ type TextBox interface {
ContentBox ContentBox
// SetText sets the text content of the Box. // SetText sets the text content of the Box.
SetText (string) SetText (string)
// SetTextColor sets the text color. // SetTextColor sets the text color.
SetTextColor (color.Color) SetTextColor (color.Color)
// SetFace sets the font face text is rendered in. // SetFace sets the font face text is rendered in.
SetFace (font.Face) SetFace (font.Face)
// SetWrap sets whether or not the text wraps. // SetWrap sets whether or not the text wraps.
SetWrap (bool) SetWrap (bool)
// SetSelectable sets whether or not the text content can be // SetSelectable sets whether or not the text content can be
// highlighted/selected. // highlighted/selected.
SetSelectable (bool) SetSelectable (bool)
// SetDotColor sets the highlight color of selected text. // SetDotColor sets the highlight color of selected text.
SetDotColor (color.Color) SetDotColor (color.Color)
// Select sets the text cursor or selection. // Select sets the text cursor or selection.
Select (text.Dot) Select (text.Dot)
// Dot returns the text cursor or selection. // Dot returns the text cursor or selection.
Dot () text.Dot Dot () text.Dot
// OnDotChange specifies a function to be called when the text cursor or // OnDotChange specifies a function to be called when the text cursor or
// selection changes. // selection changes.
OnDotChange (func ()) event.Cookie OnDotChange (func ()) event.Cookie
} }
// ContentBox is a box that can contain child Objects. It arranges them // ContentBox is a box that can contain child Objects. It arranges them
@ -258,30 +269,35 @@ type TextBox interface {
type ContainerBox interface { type ContainerBox interface {
ContentBox ContentBox
// SetPropagateEvents specifies whether or not child Objects will
// receive user input events. It is true by default. If it is false, all
// user input that would otherwise be directed to a child Box is
// directed to this Box.
SetPropagateEvents (bool)
// SetGap sets the gap between child Objects. // SetGap sets the gap between child Objects.
SetGap (image.Point) SetGap (image.Point)
// Add appends a child Object. // Add appends a child Object. If the object is already a child of
Add (Object) // another object, it will be removed from that object first.
// Delete removes a child Object, if it is a child of this Box. Add (Object)
Delete (Object) // Remove removes a child Object, if it is a child of this Box.
Remove (Object)
// Insert inserts a child Object before a specified Object. If the // Insert inserts a child Object before a specified Object. If the
// before Object is nil or is not contained within this Box, the // before Object is nil or is not contained within this Box, the
// inserted Object is appended. // inserted Object is appended.
Insert (child Object, before Object) Insert (child Object, before Object)
// Clear removes all child Objects. // Clear removes all child Objects.
Clear () Clear ()
// Length returns the amount of child objects. // Length returns the amount of child Objects.
Length () int Length () int
// At returns the child Object at the specified index. // At returns the child Object at the specified index.
At (int) Object At (int) Object
// SetLayout sets the layout of this Box. Child Objects will be // SetLayout sets the layout of this Box. Child Objects will be
// positioned according to it. // positioned according to it.
SetLayout (Layout) SetLayout (Layout)
// These methods control whether certain user input events get
// propagated to child Objects. If set to true, the relevant events will
// be sent to this container. If set to false (which is the default),
// the events will be sent to the appropriate child Object.
CaptureDND (bool)
CaptureMouse (bool)
CaptureScroll (bool)
CaptureKeyboard (bool)
} }
// LayoutHints are passed to a layout to tell it how to arrange child boxes. // LayoutHints are passed to a layout to tell it how to arrange child boxes.
@ -289,14 +305,14 @@ type LayoutHints struct {
// Bounds is the bounding rectangle that children should be placed // Bounds is the bounding rectangle that children should be placed
// within. Any padding values are already applied. // within. Any padding values are already applied.
Bounds image.Rectangle Bounds image.Rectangle
// OverflowX and OverflowY control wether child Boxes may be positioned // OverflowX and OverflowY control whether child Boxes may be positioned
// outside of Bounds. // outside of Bounds.
OverflowX bool OverflowX bool
OverflowY bool OverflowY bool
// AlignX and AlignY control how child Boxes are aligned horizontally // AlignX and AlignY control how child Boxes are aligned horizontally
// and vertically. The effect of this may vary depending on the Layout. // and vertically. The effect of this may vary depending on the Layout.
AlignX Align AlignX Align
AlignY Align AlignY Align
// Gap controls the amount of horizontal and vertical spacing in-between // Gap controls the amount of horizontal and vertical spacing in-between
// child Boxes. // child Boxes.
Gap image.Point Gap image.Point
@ -308,43 +324,44 @@ type Layout interface {
// LayoutHints.Bounds needed to properly lay out all child Boxes. // LayoutHints.Bounds needed to properly lay out all child Boxes.
MinimumSize (LayoutHints, []Box) image.Point MinimumSize (LayoutHints, []Box) image.Point
// Arrange arranges child boxes according to the given LayoutHints. // Arrange arranges child boxes according to the given LayoutHints.
Arrange (LayoutHints, []Box) Arrange (LayoutHints, []Box)
} }
// Window is an operating system window. It can contain one object. // Window is an operating system window. It can contain one object.
type Window interface { type Window interface {
// SetRoot sets the root child of the window. There can only be one at // SetRoot sets the root child of the window. There can only be one at
// a time, and setting it will remove the current child if there is one. // a time, and setting it will remove the current child if there is one.
SetRoot (Object) SetRoot (Object)
// SetTitle sets the title of the window. // SetTitle sets the title of the window.
SetTitle (string) SetTitle (string)
// SetIcon sets the icon of the window. When multiple icon sizes are // SetIcon sets the icon of the window. When multiple icon sizes are
// provided, the best fitting one is chosen for display. // provided, the best fitting one is chosen for display.
SetIcon (... image.Image) SetIcon (... image.Image)
// Widget returns a window representing a smaller iconified form of this // Widget returns a window representing a smaller iconified form of this
// window. How exactly this window is used depends on the platform. // window. How exactly this window is used depends on the platform.
// Subsequent calls to this method on the same window will return the // Subsequent calls to this method on the same window will return the
// same window object. // same window object.
Widget () (Window, error) Widget () (Window, error)
// NewMenu creates a new menu window. This window is undecorated and // NewMenu creates a new menu window. This window is undecorated and
// will close once the user clicks outside of it. // will close once the user clicks outside of it.
NewMenu (image.Rectangle) (Window, error) NewMenu (image.Rectangle) (Window, error)
// NewModal creates a new modal window that blocks all input to this // NewModal creates a new modal window that blocks all input to this
// window until it is closed. // window until it is closed.
NewModal (image.Rectangle) (Window, error) NewModal (image.Rectangle) (Window, error)
// Copy copies data to the clipboard. // Copy copies data to the clipboard.
Copy (data.Data) Copy (data.Data)
// Paste reads data from the clipboard. When the data is available or an // Paste reads data from the clipboard. When the data is available or an
// error has occurred, the provided function will be called. // error has occurred, the provided function will be called.
Paste (callback func (data.Data, error), accept ...data.Mime) Paste (callback func (data.Data, error), accept ...data.Mime)
// Show shows the window. // SetVisible sets whether or not this window is visible. Windows are
Show () // invisible by default.
// Hide hides the window. SetVisible (bool)
Hide () // Visible returns whether or not this window is visible.
Visible () bool
// Close closes the window. // Close closes the window.
Close () Close ()
// OnClose specifies a function to be called when the window is closed. // OnClose specifies a function to be called when the window is closed.
OnClose (func ()) event.Cookie OnClose (func ()) event.Cookie
} }
// MainWindow is a top-level operating system window. // MainWindow is a top-level operating system window.

187
path.go
View File

@ -1,187 +0,0 @@
package tomo
import "io"
import "os"
import "io/fs"
import "strings"
import "path/filepath"
// FS is Tomo's implementation of fs.FS. It provides access to a specific part
// of the filesystem.
type FS struct {
path string
}
// FileWriter is a writable version of fs.File.
type FileWriter interface {
interface { fs.File; io.Writer }
}
// ApplicationUserDataFS returns an FS that an application can use to store user
// data files.
func ApplicationUserDataFS (app ApplicationDescription) (*FS, error) {
return appFs(userDataDir, app)
}
// ApplicationUserConfigFS returns an FS that an application can use to store
// user configuration files.
func ApplicationUserConfigFS (app ApplicationDescription) (*FS, error) {
configDir, err := os.UserConfigDir()
if err != nil { return nil, err }
return appFs(configDir, app)
}
// ApplicationUserCacheFS returns an FS that an application can use to store
// user cache files.
func ApplicationUserCacheFS (app ApplicationDescription) (*FS, error) {
cacheDir, err := os.UserCacheDir()
if err != nil { return nil, err }
return appFs(cacheDir, app)
}
func pathErr (op, path string, err error) error {
return &fs.PathError {
Op: op,
Path: path,
Err: err,
}
}
func appFs (root string, app ApplicationDescription) (*FS, error) {
// remove slashes
appname := app.String()
appname = strings.ReplaceAll(appname, "/", "-")
appname = strings.ReplaceAll(appname, "\\", "-")
path := filepath.Join(root, appname)
// ensure the directory actually exists
err := os.MkdirAll(path, 755)
if err != nil { return nil, err }
return &FS { path: path }, nil
}
func (this FS) subPath (name string) (string, error) {
if !fs.ValidPath(name) { return "", fs.ErrInvalid }
if strings.Contains(name, "/") { return "", fs.ErrInvalid }
return filepath.Join(this.path, name), nil
}
// Open opens the named file.
func (this FS) Open (name string) (fs.File, error) {
path, err := this.subPath(name)
if err != nil {
return nil, pathErr("open", name, err)
}
return os.Open(path)
}
// Create creates or truncates the named file.
func (this FS) Create (name string) (FileWriter, error) {
path, err := this.subPath(name)
if err != nil {
return nil, pathErr("create", name, err)
}
return os.Create(path)
}
// OpenFile is the generalized open call; most users will use Open or Create
// instead.
func (this FS) OpenFile (
name string,
flag int,
perm os.FileMode,
) (
FileWriter,
error,
) {
path, err := this.subPath(name)
if err != nil {
return nil, pathErr("open", name, err)
}
return os.OpenFile(path, flag, perm)
}
// ReadDir reads the named directory and returns a list of directory entries
// sorted by filename.
func (this FS) ReadDir (name string) ([]fs.DirEntry, error) {
path, err := this.subPath(name)
if err != nil {
return nil, pathErr("readdir", name, err)
}
return os.ReadDir(path)
}
// ReadFile reads the named file and returns its contents.
// A successful call returns a nil error, not io.EOF.
// (Because ReadFile reads the whole file, the expected EOF
// from the final Read is not treated as an error to be reported.)
//
// The caller is permitted to modify the returned byte slice.
func (this FS) ReadFile (name string) ([]byte, error) {
path, err := this.subPath(name)
if err != nil {
return nil, pathErr("readfile", name, err)
}
return os.ReadFile(path)
}
// WriteFile writes data to the named file, creating it if necessary.
func (this FS) WriteFile (name string, data []byte, perm os.FileMode) error {
path, err := this.subPath(name)
if err != nil {
return pathErr("writefile", name, err)
}
return os.WriteFile(path, data, perm)
}
// Stat returns a FileInfo describing the file.
func (this FS) Stat (name string) (fs.FileInfo, error) {
path, err := this.subPath(name)
if err != nil {
return nil, pathErr("stat", name, err)
}
return os.Stat(path)
}
// Remove removes the named file or (empty) directory.
func (this FS) Remove (name string) error {
path, err := this.subPath(name)
if err != nil {
return pathErr("remove", name, err)
}
return os.Remove(path)
}
// RemoveAll removes name and any children it contains.
func (this FS) RemoveAll (name string) error {
path, err := this.subPath(name)
if err != nil {
return pathErr("removeall", name, err)
}
return os.RemoveAll(path)
}
// Rename renames (moves) oldname to newname.
func (this FS) Rename (oldname, newname string) error {
oldpath, err := this.subPath(oldname)
if err != nil {
return pathErr("rename", oldname, err)
}
newpath, err := this.subPath(newname)
if err != nil {
return pathErr("rename", newname, err)
}
return os.Rename(oldpath, newpath)
}

View File

@ -1,55 +0,0 @@
package tomo
import "os"
import "plugin"
import "path/filepath"
var pluginPaths []string
func loadPlugins () {
for _, dir := range pluginPaths {
if dir != "" {
loadPluginsFrom(dir)
}
}
}
func loadPluginsFrom (dir string) {
entries, err := os.ReadDir(dir)
// its no big deal if one of the dirs doesn't exist
if err != nil { return }
for _, entry := range entries {
if entry.IsDir() { continue }
if filepath.Ext(entry.Name()) != ".so" { continue }
pluginPath := filepath.Join(dir, entry.Name())
loadPlugin(pluginPath)
}
}
func loadPlugin (path string) {
die := func (reason string) {
println("tomo: could not load plugin at", path + ":", reason)
}
plugin, err := plugin.Open(path)
if err != nil {
die(err.Error())
return
}
// check for and obtain basic plugin functions
name, ok := extract[func () string](plugin, "Name")
if !ok { die("does not implement Name() string"); return }
_, ok = extract[func () string](plugin, "Description")
if !ok { die("does not implement Description() string"); return }
println("tomo: loaded plugin", name())
}
func extract[T any] (plugin *plugin.Plugin, name string) (value T, ok bool) {
symbol, err := plugin.Lookup(name)
if err != nil { return }
value, ok = symbol.(T)
return
}

View File

@ -1,6 +1,5 @@
package theme package theme
import "git.tebibyte.media/tomo/tomo"
import "git.tebibyte.media/tomo/tomo/data" import "git.tebibyte.media/tomo/tomo/data"
import "git.tebibyte.media/tomo/tomo/canvas" import "git.tebibyte.media/tomo/tomo/canvas"
@ -21,403 +20,251 @@ func (size IconSize) String () string {
} }
} }
// TODO: the Icon type, along with its String method, needs to be codegen'd.
// Icon represents an icon ID. // Icon represents an icon ID.
type Icon int; const ( type Icon string
// --- Objects --- //
// files // A list of standard icon IDs.
IconFile Icon = iota const (
IconDirectory IconUnknown Icon = ""
IconDirectoryFull
// places // objects: files
IconDownloads IconFile Icon = "File" // generic
IconPhotos IconDirectory Icon = "Directory"
IconBooks IconDirectoryFull Icon = "DirectoryFull"
IconDocuments
IconRepositories
IconMusic
IconArchives
IconFonts
IconBinaries
IconVideos
Icon3DObjects
IconHistory
IconPreferences
// storage // objects: places
IconStorage // generic IconPlaceHome Icon = "PlaceHome"
IconMagneticTape IconPlaceDownloads Icon = "PlaceDownloads"
IconFloppyDisk IconPlacePhotos Icon = "PlacePhotos"
IconHardDisk IconPlaceBooks Icon = "PlaceBooks"
IconSolidStateDrive IconPlaceDocuments Icon = "PlaceDocuments"
IconFlashDrive IconPlaceRepositories Icon = "PlaceRepositories"
IconMemoryCard IconPlaceMusic Icon = "PlaceMusic"
IconROMDisk IconPlaceArchives Icon = "PlaceArchives"
IconRAMDisk IconPlaceFonts Icon = "PlaceFonts"
IconCD IconPlaceBinaries Icon = "PlaceBinaries"
IconDVD IconPlaceVideos Icon = "PlaceVideos"
IconPlace3DObjects Icon = "Place3DObjects"
IconPlaceHistory Icon = "PlaceHistory"
IconPlacePreferences Icon = "PlacePreferences"
// network // objects: storage
IconNetwork // generic IconStorage Icon = "Storage" // generic
IconLocalNetwork IconStorageMagneticTape Icon = "StorageMagneticTape"
IconInternet IconStorageFloppyDisk Icon = "StorageFloppyDisk"
IconEthernet IconStorageHardDisk Icon = "StorageHardDisk"
IconWireless IconStorageSolidStateDisk Icon = "StorageSolidState"
IconCell IconStorageFlashStick Icon = "StorageFlashStick"
IconBluetooth IconStorageFlashCard Icon = "StorageFlashCard"
IconRadio IconStorageROM Icon = "StorageROM"
IconStorageRAM Icon = "StorageRAM"
IconStorageCD Icon = "StorageCD"
IconStorageDVD Icon = "StorageDVD"
// devices // objects: applications
IconDevice // generic // Keep these in sync with nasin.ApplicationRole!
IconRouter IconApplication Icon = "Application" // generic
IconServer IconApplicationWebBrowser Icon = "ApplicationWebBrowser"
IconDesktop IconApplicationMesssanger Icon = "ApplicationMesssanger"
IconLaptop IconApplicationPhone Icon = "ApplicationPhone"
IconTablet IconApplicationMail Icon = "ApplicationMail"
IconPhone IconApplicationTerminalEmulator Icon = "ApplicationTerminalEmulator"
IconWatch IconApplicationFileBrowser Icon = "ApplicationFileBrowser"
IconCamera IconApplicationTextEditor Icon = "ApplicationTextEditor"
IconApplicationDocumentViewer Icon = "ApplicationDocumentViewer"
IconApplicationWordProcessor Icon = "ApplicationWordProcessor"
IconApplicationSpreadsheet Icon = "ApplicationSpreadsheet"
IconApplicationSlideshow Icon = "ApplicationSlideshow"
IconApplicationCalculator Icon = "ApplicationCalculator"
IconApplicationPreferences Icon = "ApplicationPreferences"
IconApplicationProcessManager Icon = "ApplicationProcessManager"
IconApplicationSystemInformation Icon = "ApplicationSystemInformation"
IconApplicationManual Icon = "ApplicationManual"
IconApplicationCamera Icon = "ApplicationCamera"
IconApplicationImageViewer Icon = "ApplicationImageViewer"
IconApplicationMediaPlayer Icon = "ApplicationMediaPlayer"
IconApplicationImageEditor Icon = "ApplicationImageEditor"
IconApplicationAudioEditor Icon = "ApplicationAudioEditor"
IconApplicationVideoEditor Icon = "ApplicationVideoEditor"
IconApplicationClock Icon = "ApplicationClock"
IconApplicationCalendar Icon = "ApplicationCalendar"
IconApplicationChecklist Icon = "ApplicationChecklist"
// peripherals // objects: networks
IconPeripheral // generic IconNetwork Icon = "Network" // generic
IconKeyboard IconNetworkLocal Icon = "NetworkLocal"
IconMouse IconNetworkInternet Icon = "NetworkInternet"
IconMonitor IconNetworkEthernet Icon = "NetworkEthernet"
IconWebcam IconNetworkWireless Icon = "NetworkWireless"
IconMicrophone IconNetworkCell Icon = "NetworkCell"
IconSpeaker IconNetworkBluetooth Icon = "NetworkBluetooth"
IconPenTablet IconNetworkRadio Icon = "NetworkRadio"
IconTrackpad
IconController
// i/o // objects: devices
IconPort // generic IconDevice Icon = "Device" // generic
IconEthernetPort IconDeviceRouter Icon = "DeviceRouter"
IconUSBPort IconDeviceServer Icon = "DeviceServer"
IconParallelPort IconDeviceDesktop Icon = "DeviceDesktop"
IconSerialPort IconDeviceLaptop Icon = "DeviceLaptop"
IconPS2Port IconDeviceTablet Icon = "DeviceTablet"
IconDisplayConnector IconDevicePhone Icon = "DevicePhone"
IconCGAPort IconDeviceWatch Icon = "DeviceWatch"
IconVGAPort IconDeviceCamera Icon = "DeviceCamera"
IconHDMIPort
IconDisplayPort
IconInfrared
// --- Actions --- // // objects: peripherals
IconPeripheral Icon = "Peripheral" // generic
IconPeripheralKeyboard Icon = "PeripheralKeyboard"
IconPeripheralMouse Icon = "PeripheralMouse"
IconPeripheralMonitor Icon = "PeripheralMonitor"
IconPeripheralWebcam Icon = "PeripheralWebcam"
IconPeripheralMicrophone Icon = "PeripheralMicrophone"
IconPeripheralSpeaker Icon = "PeripheralSpeaker"
IconPeripheralPenTablet Icon = "PeripheralPenTablet"
IconPeripheralTrackpad Icon = "PeripheralTrackpad"
IconPeripheralController Icon = "PeripheralController"
// files // objects: i/o
IconOpen IconPort Icon = "Port" // generic
IconOpenIn IconPortEthernet Icon = "PortEthernet"
IconSave IconPortUSB Icon = "PortUSB"
IconSaveAs IconPortParallel Icon = "PortParallel"
IconPrint IconPortSerial Icon = "PortSerial"
IconNew IconPortPS2 Icon = "PortPS2"
IconNewDirectory IconPortDisplay Icon = "PortDisplay"
IconDelete IconPortCGA Icon = "PortCGA"
IconRename IconPortVGA Icon = "PortVGA"
IconGetInformation IconPortHDMI Icon = "PortHDMI"
IconChangePermissions IconPortDisplayPort Icon = "PortDisplayPort"
IconRevert IconPortInfrared Icon = "PortInfrared"
// list management // actions: files
IconAdd IconActionOpen Icon = "ActionOpen"
IconRemove IconActionOpenIn Icon = "ActionOpenIn"
IconAddBookmark IconActionSave Icon = "ActionSave"
IconRemoveBookmark IconActionSaveAs Icon = "ActionSaveAs"
IconAddFavorite IconActionPrint Icon = "ActionPrint"
IconRemoveFavorite IconActionNew Icon = "ActionNew"
IconActionNewDirectory Icon = "ActionNewDirectory"
IconActionDelete Icon = "ActionDelete"
IconActionRename Icon = "ActionRename"
IconActionGetInformation Icon = "ActionGetInformation"
IconActionChangePermissions Icon = "ActionChangePermissions"
IconActionRevert Icon = "ActionRevert"
// media // actions: list management
IconPlay IconActionAdd Icon = "ActionAdd"
IconPause IconActionRemove Icon = "ActionRemove"
IconStop IconActionAddBookmark Icon = "ActionAddBookmark"
IconFastForward IconActionRemoveBookmark Icon = "ActionRemoveBookmark"
IconRewind IconActionAddFavorite Icon = "ActionAddFavorite"
IconToBeginning IconActionRemoveFavorite Icon = "ActionRemoveFavorite"
IconToEnd
IconRecord
IconVolumeUp
IconVolumeDown
IconMute
// editing // actions: media
IconUndo IconActionPlay Icon = "ActionPlay"
IconRedo IconActionPause Icon = "ActionPause"
IconCut IconActionStop Icon = "ActionStop"
IconCopy IconActionFastForward Icon = "ActionFastForward"
IconPaste IconActionRewind Icon = "ActionRewind"
IconFind IconActionToBeginning Icon = "ActionToBeginning"
IconReplace IconActionToEnd Icon = "ActionToEnd"
IconSelectAll IconActionRecord Icon = "ActionRecord"
IconSelectNone IconActionVolumeUp Icon = "ActionVolumeUp"
IconIncrement IconActionVolumeDown Icon = "ActionVolumeDown"
IconDecrement IconActionMute Icon = "ActionMute"
// window management // actions: editing
IconClose IconActionUndo Icon = "ActionUndo"
IconQuit IconActionRedo Icon = "ActionRedo"
IconIconify IconActionCut Icon = "ActionCut"
IconShade IconActionCopy Icon = "ActionCopy"
IconMaximize IconActionPaste Icon = "ActionPaste"
IconFullScreen IconActionFind Icon = "ActionFind"
IconRestore IconActionReplace Icon = "ActionReplace"
IconActionSelectAll Icon = "ActionSelectAll"
IconActionSelectNone Icon = "ActionSelectNone"
IconActionIncrement Icon = "ActionIncrement"
IconActionDecrement Icon = "ActionDecrement"
// view controls // actions: window management
IconExpand IconActionClose Icon = "ActionClose"
IconContract IconActionQuit Icon = "ActionQuit"
IconBack IconActionIconify Icon = "ActionIconify"
IconForward IconActionShade Icon = "ActionShade"
IconUp IconActionMaximize Icon = "ActionMaximize"
IconDown IconActionFullScreen Icon = "ActionFullScreen"
IconReload IconActionRestore Icon = "ActionRestore"
IconZoomIn
IconZoomOut
IconZoomReset
IconMove
IconResize
IconGoTo
// tools // actions: view
IconTransform IconActionExpand Icon = "ActionExpand"
IconTranslate IconActionContract Icon = "ActionContract"
IconRotate IconActionBack Icon = "ActionBack"
IconScale IconActionForward Icon = "ActionForward"
IconWarp IconActionUp Icon = "ActionUp"
IconCornerPin IconActionDown Icon = "ActionDown"
IconSelectRectangle IconActionReload Icon = "ActionReload"
IconSelectEllipse IconActionZoomIn Icon = "ActionZoomIn"
IconSelectLasso IconActionZoomOut Icon = "ActionZoomOut"
IconSelectGeometric IconActionZoomReset Icon = "ActionZoomReset"
IconSelectAuto IconActionMove Icon = "ActionMove"
IconCrop IconActionResize Icon = "ActionResize"
IconFill IconActionGoTo Icon = "ActionGoTo"
IconGradient
IconPencil
IconBrush
IconEraser
IconText
IconEyedropper
// --- Status --- // // actions: tools
IconActionTransform Icon = "ActionTransform"
IconActionTranslate Icon = "ActionTranslate"
IconActionRotate Icon = "ActionRotate"
IconActionScale Icon = "ActionScale"
IconActionWarp Icon = "ActionWarp"
IconActionCornerPin Icon = "ActionCornerPin"
IconActionSelectRectangle Icon = "ActionSelectRectangle"
IconActionSelectEllipse Icon = "ActionSelectEllipse"
IconActionSelectLasso Icon = "ActionSelectLasso"
IconActionSelectGeometric Icon = "ActionSelectGeometric"
IconActionSelectAuto Icon = "ActionSelectAuto"
IconActionCrop Icon = "ActionCrop"
IconActionFill Icon = "ActionFill"
IconActionGradient Icon = "ActionGradient"
IconActionPencil Icon = "ActionPencil"
IconActionBrush Icon = "ActionBrush"
IconActionEraser Icon = "ActionEraser"
IconActionText Icon = "ActionText"
IconActionEyedropper Icon = "ActionEyedropper"
// dialogs // status: dialog
IconInformation IconStatusInformation Icon = "StatusInformation"
IconQuestion IconStatusQuestion Icon = "StatusQuestion"
IconWarning IconStatusWarning Icon = "StatusWarning"
IconError IconStatusError Icon = "StatusError"
IconCancel IconStatusCancel Icon = "StatusCancel"
IconOkay IconStatusOkay Icon = "StatusOkay"
// network // status: network
IconCellSignal0 IconStatusCellSignal0 Icon = "StatusCellSignal0"
IconCellSignal1 IconStatusCellSignal1 Icon = "StatusCellSignal1"
IconCellSignal2 IconStatusCellSignal2 Icon = "StatusCellSignal2"
IconCellSignal3 IconStatusCellSignal3 Icon = "StatusCellSignal3"
IconWirelessSignal0 IconStatusWirelessSignal0 Icon = "StatusWirelessSignal0"
IconWirelessSignal1 IconStatusWirelessSignal1 Icon = "StatusWirelessSignal1"
IconWirelessSignal2 IconStatusWirelessSignal2 Icon = "StatusWirelessSignal2"
IconWirelessSignal3 IconStatusWirelessSignal3 Icon = "StatusWirelessSignal3"
// power // status: power
IconBattery0 IconStatusBattery0 Icon = "StatusBattery0"
IconBattery1 IconStatusBattery1 Icon = "StatusBattery1"
IconBattery2 IconStatusBattery2 Icon = "StatusBattery2"
IconBattery3 IconStatusBattery3 Icon = "StatusBattery3"
IconBrightness0 IconStatusBrightness0 Icon = "StatusBrightness0"
IconBrightness1 IconStatusBrightness1 Icon = "StatusBrightness1"
IconBrightness2 IconStatusBrightness2 Icon = "StatusBrightness2"
IconBrightness3 IconStatusBrightness3 Icon = "StatusBrightness3"
// media // status: media
IconVolume0 IconStatusVolume0 Icon = "StatusVolume0"
IconVolume1 IconStatusVolume1 Icon = "StatusVolume1"
IconVolume2 IconStatusVolume2 Icon = "StatusVolume2"
IconVolume3 IconStatusVolume3 Icon = "StatusVolume3"
) )
// String satisfies the fmt.Stringer interface.
func (id Icon) String () string {
switch id {
case IconFile: return "File"
case IconDirectory: return "Directory"
case IconDirectoryFull: return "DirectoryFull"
case IconDownloads: return "Downloads"
case IconPhotos: return "Photos"
case IconBooks: return "Books"
case IconDocuments: return "Documents"
case IconRepositories: return "Repositories"
case IconMusic: return "Music"
case IconArchives: return "Archives"
case IconFonts: return "Fonts"
case IconBinaries: return "Binaries"
case IconVideos: return "Videos"
case Icon3DObjects: return "3DObjects"
case IconHistory: return "History"
case IconPreferences: return "Preferences"
case IconStorage: return "Storage"
case IconMagneticTape: return "MagneticTape"
case IconFloppyDisk: return "FloppyDisk"
case IconHardDisk: return "HardDisk"
case IconSolidStateDrive: return "SolidStateDrive"
case IconFlashDrive: return "FlashDrive"
case IconMemoryCard: return "MemoryCard"
case IconROMDisk: return "ROMDisk"
case IconRAMDisk: return "RAMDisk"
case IconCD: return "CD"
case IconDVD: return "DVD"
case IconNetwork: return "Network"
case IconLocalNetwork: return "LocalNetwork"
case IconInternet: return "Internet"
case IconEthernet: return "Ethernet"
case IconWireless: return "Wireless"
case IconCell: return "Cell"
case IconBluetooth: return "Bluetooth"
case IconRadio: return "Radio"
case IconDevice: return "Device"
case IconRouter: return "Router"
case IconServer: return "Server"
case IconDesktop: return "Desktop"
case IconLaptop: return "Laptop"
case IconTablet: return "Tablet"
case IconPhone: return "Phone"
case IconWatch: return "Watch"
case IconCamera: return "Camera"
case IconPeripheral: return "Peripheral"
case IconKeyboard: return "Keyboard"
case IconMouse: return "Mouse"
case IconMonitor: return "Monitor"
case IconWebcam: return "Webcam"
case IconMicrophone: return "Microphone"
case IconSpeaker: return "Speaker"
case IconPenTablet: return "PenTablet"
case IconTrackpad: return "Trackpad"
case IconController: return "Controller"
case IconPort: return "Port"
case IconEthernetPort: return "EthernetPort"
case IconUSBPort: return "USBPort"
case IconParallelPort: return "ParallelPort"
case IconSerialPort: return "SerialPort"
case IconPS2Port: return "PS2Port"
case IconDisplayConnector: return "DisplayConnector"
case IconCGAPort: return "CGAPort"
case IconVGAPort: return "VGAPort"
case IconHDMIPort: return "HDMIPort"
case IconDisplayPort: return "DisplayPort"
case IconInfrared: return "Infrared"
case IconOpen: return "Open"
case IconOpenIn: return "OpenIn"
case IconSave: return "Save"
case IconSaveAs: return "SaveAs"
case IconPrint: return "Print"
case IconNew: return "New"
case IconNewDirectory: return "NewDirectory"
case IconDelete: return "Delete"
case IconRename: return "Rename"
case IconGetInformation: return "GetInformation"
case IconChangePermissions: return "ChangePermissions"
case IconRevert: return "Revert"
case IconAdd: return "Add"
case IconRemove: return "Remove"
case IconAddBookmark: return "AddBookmark"
case IconRemoveBookmark: return "RemoveBookmark"
case IconAddFavorite: return "AddFavorite"
case IconRemoveFavorite: return "RemoveFavorite"
case IconPlay: return "Play"
case IconPause: return "Pause"
case IconStop: return "Stop"
case IconFastForward: return "FastForward"
case IconRewind: return "Rewind"
case IconToBeginning: return "ToBeginning"
case IconToEnd: return "ToEnd"
case IconRecord: return "Record"
case IconVolumeUp: return "VolumeUp"
case IconVolumeDown: return "VolumeDown"
case IconMute: return "Mute"
case IconUndo: return "Undo"
case IconRedo: return "Redo"
case IconCut: return "Cut"
case IconCopy: return "Copy"
case IconPaste: return "Paste"
case IconFind: return "Find"
case IconReplace: return "Replace"
case IconSelectAll: return "SelectAll"
case IconSelectNone: return "SelectNone"
case IconIncrement: return "Increment"
case IconDecrement: return "Decrement"
case IconClose: return "Close"
case IconQuit: return "Quit"
case IconIconify: return "Iconify"
case IconShade: return "Shade"
case IconMaximize: return "Maximize"
case IconFullScreen: return "FullScreen"
case IconRestore: return "Restore"
case IconExpand: return "Expand"
case IconContract: return "Contract"
case IconBack: return "Back"
case IconForward: return "Forward"
case IconUp: return "Up"
case IconDown: return "Down"
case IconReload: return "Reload"
case IconZoomIn: return "ZoomIn"
case IconZoomOut: return "ZoomOut"
case IconZoomReset: return "ZoomReset"
case IconMove: return "Move"
case IconResize: return "Resize"
case IconGoTo: return "GoTo"
case IconTransform: return "Transform"
case IconTranslate: return "Translate"
case IconRotate: return "Rotate"
case IconScale: return "Scale"
case IconWarp: return "Warp"
case IconCornerPin: return "CornerPin"
case IconSelectRectangle: return "SelectRectangle"
case IconSelectEllipse: return "SelectEllipse"
case IconSelectLasso: return "SelectLasso"
case IconSelectGeometric: return "SelectGeometric"
case IconSelectAuto: return "SelectAuto"
case IconCrop: return "Crop"
case IconFill: return "Fill"
case IconGradient: return "Gradient"
case IconPencil: return "Pencil"
case IconBrush: return "Brush"
case IconEraser: return "Eraser"
case IconText: return "Text"
case IconEyedropper: return "Eyedropper"
case IconInformation: return "Information"
case IconQuestion: return "Question"
case IconWarning: return "Warning"
case IconError: return "Error"
case IconCancel: return "Cancel"
case IconOkay: return "Okay"
case IconCellSignal0: return "CellSignal0"
case IconCellSignal1: return "CellSignal1"
case IconCellSignal2: return "CellSignal2"
case IconCellSignal3: return "CellSignal3"
case IconWirelessSignal0: return "WirelessSignal0"
case IconWirelessSignal1: return "WirelessSignal1"
case IconWirelessSignal2: return "WirelessSignal2"
case IconWirelessSignal3: return "WirelessSignal3"
case IconBattery0: return "Battery0"
case IconBattery1: return "Battery1"
case IconBattery2: return "Battery2"
case IconBattery3: return "Battery3"
case IconBrightness0: return "Brightness0"
case IconBrightness1: return "Brightness1"
case IconBrightness2: return "Brightness2"
case IconBrightness3: return "Brightness3"
case IconVolume0: return "Volume0"
case IconVolume1: return "Volume1"
case IconVolume2: return "Volume2"
case IconVolume3: return "Volume3"
default: return "Unknown"
}
}
// Texture returns a texture of the corresponding icon ID. // Texture returns a texture of the corresponding icon ID.
func (id Icon) Texture (size IconSize) canvas.Texture { func (id Icon) Texture (size IconSize) canvas.Texture {
if current == nil { return nil } if current == nil { return nil }
@ -429,12 +276,3 @@ func MimeIcon (mime data.Mime, size IconSize) canvas.Texture {
if current == nil { return nil } if current == nil { return nil }
return current.MimeIcon(mime, size) return current.MimeIcon(mime, size)
} }
// ApplicationIcon describes the icon of the application.
type ApplicationIcon tomo.ApplicationDescription
// Texture returns a texture of the corresponding icon ID.
func (icon ApplicationIcon) Texture (size IconSize) canvas.Texture {
if current == nil { return nil }
return current.ApplicationIcon(icon, size)
}

View File

@ -65,7 +65,7 @@ func (id Color) RGBA () (r, g, b, a uint32) {
return current.RGBA(id) return current.RGBA(id)
} }
// Theme is an object that can apply a visual style to different objects. // Theme can apply a visual style to different objects.
type Theme interface { type Theme interface {
// A word on textures: // A word on textures:
// //
@ -91,9 +91,6 @@ type Theme interface {
// MimeIcon returns an icon corresponding to a MIME type. // MimeIcon returns an icon corresponding to a MIME type.
MimeIcon (data.Mime, IconSize) canvas.Texture MimeIcon (data.Mime, IconSize) canvas.Texture
// ApplicationIcon returns an icon corresponding to an application.
ApplicationIcon (ApplicationIcon, IconSize) canvas.Texture
} }
var current Theme var current Theme

10
tomo.go
View File

@ -12,8 +12,6 @@ var backend Backend
// event loop in that order. This function blocks until Stop is called, or the // event loop in that order. This function blocks until Stop is called, or the
// backend experiences a fatal error. // backend experiences a fatal error.
func Run (callback func ()) error { func Run (callback func ()) error {
loadPlugins()
if backend != nil { if backend != nil {
return errors.New("there is already a backend running") return errors.New("there is already a backend running")
} }
@ -57,6 +55,14 @@ func NewWindow (bounds image.Rectangle) (MainWindow, error) {
return backend.NewWindow(bounds) return backend.NewWindow(bounds)
} }
// NewPlainWindow is like NewWindow, but it creates an undecorated window that
// does not appear in window lists. It is intended for creating things like
// docks, panels, etc.
func NewPlainWindow (bounds image.Rectangle) (MainWindow, error) {
assertBackend()
return backend.NewPlainWindow(bounds)
}
// NewBox creates and returns a basic Box. // NewBox creates and returns a basic Box.
func NewBox () Box { func NewBox () Box {
assertBackend() assertBackend()

26
unix.go
View File

@ -1,26 +0,0 @@
//go:build linux || darwin || freebsd
package tomo
import "os"
import "strings"
import "path/filepath"
var userDataDir string
func init () {
pathVariable := os.Getenv("TOMO_PLUGIN_PATH")
pluginPaths = strings.Split(pathVariable, ":")
pluginPaths = append (
pluginPaths,
"/usr/lib/tomo/plugins",
"/usr/local/lib/tomo/plugins")
homeDir, err := os.UserHomeDir()
if err == nil {
pluginPaths = append (
pluginPaths,
filepath.Join(homeDir, ".local/lib/tomo/plugins"))
}
userDataDir = filepath.Join(homeDir, ".local/share")
}