Skip to content

Commit

Permalink
Allow to customize toolbars with any UI components
Browse files Browse the repository at this point in the history
  • Loading branch information
mattpap committed Feb 7, 2024
1 parent 28ec01b commit c46660b
Show file tree
Hide file tree
Showing 21 changed files with 320 additions and 145 deletions.
19 changes: 19 additions & 0 deletions bokehjs/src/less/divider.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
:host {
// TODO: shared with tool_button.less
--button-color: lightgray;
}

:host {
flex: 0 0 auto;
background-color: var(--button-color);
}

:host(.bk-horizontal) {
height: 10px;
width: 1px;
}

:host(.bk-vertical) {
height: 1px;
width: 10px;
}
26 changes: 16 additions & 10 deletions bokehjs/src/less/logo.less
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
.bk-logo {
margin: 5px;
position: relative;
display: block;
:host {
// TODO: shared with tool_button.less
--button-width: 30px;
--button-height: 30px;
}

:host {
flex: 0 0 auto;
background-repeat: no-repeat;
&.bk-grey {
filter: grayscale(100%);
}
background-position: center;
}

:host(.bk-grey) {
filter: grayscale(100%);
}

.bk-logo-small {
width: 20px;
height: 20px;
:host(.bk-small) {
width: var(--button-width);
height: var(--button-width);
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==);
}
1 change: 1 addition & 0 deletions bokehjs/src/less/tool_button.less
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

:host {
position: relative;
flex: 0 0 auto;

width: var(--button-width);
height: var(--button-height);
Expand Down
38 changes: 0 additions & 38 deletions bokehjs/src/less/toolbar.less
Original file line number Diff line number Diff line change
Expand Up @@ -25,52 +25,14 @@
transition: visibility 0.3s linear, opacity 0.3s linear;
}

.bk-logo {
flex-shrink: 0;
}

:host(.bk-above), :host(.bk-below) {
flex-direction: row;
justify-content: flex-end;

.bk-logo {
order: 1;
margin-left: 5px;
margin-right: 0px;
}
}

:host(.bk-left), :host(.bk-right) {
flex-direction: column;
justify-content: flex-start;

.bk-logo {
order: 0;
margin-bottom: 5px;
margin-top: 0px;
}
}

/// Dividier

.bk-divider {
content: " ";
display: inline-block;
background-color: var(--button-color);
}

:host(.bk-above), :host(.bk-below) {
.bk-divider {
height: 10px;
width: 1px;
}
}

:host(.bk-left), :host(.bk-right) {
.bk-divider {
height: 1px;
width: 10px;
}
}

/// Overflow button
Expand Down
4 changes: 2 additions & 2 deletions bokehjs/src/lib/core/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ export const LinePolicy = Enum("prev", "next", "nearest", "interp", "none")
export type Location = "above" | "below" | "left" | "right"
export const Location = Enum("above", "below", "left", "right")

export type Logo = "normal" | "grey"
export const Logo = Enum("normal", "grey")
export type LogoStyle = "normal" | "grey"
export const LogoStyle = Enum("normal", "grey")

export type MapType = typeof MapType["__type__"]
export const MapType = Enum("satellite", "roadmap", "terrain", "hybrid")
Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/annotations/toolbar_panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class ToolbarPanelView extends AnnotationView {
this.el.style.position = "absolute"

const {style} = this.toolbar_view.el
if (this.toolbar_view.model.horizontal) {
if (this.toolbar_view.horizontal) {
style.width = "100%"
style.height = "unset"
} else {
Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/layouts/flex_box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export abstract class FlexBoxView extends LayoutDOMView {

view.style.append(":host", {flex, align_self})

// undo `width/height: 100%` and let `align-self: strech` do the work
// undo `width/height: 100%` and let `align-self: stretch` do the work
if (this._direction == "row") {
if (sizing.height_policy == "max") {
view.style.append(":host", {height: "auto"})
Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/plots/plot_canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ export class PlotView extends LayoutDOMView implements Renderable {
}

async build_tool_views(): Promise<void> {
const tool_models = flat_map(this.model.toolbar.tools, (item) => item instanceof ToolProxy ? item.tools : [item])
const tool_models = flat_map(this.model.toolbar.computed_tools, (item) => item instanceof ToolProxy ? item.tools : [item])
const {created} = await build_views(this.tool_views, [...tool_models], {parent: this})
created.map((tool_view) => this.canvas_view.ui_event_bus.register_tool(tool_view))
}
Expand Down
39 changes: 39 additions & 0 deletions bokehjs/src/lib/models/tools/divider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {UIElement, UIElementView} from "../ui/ui_element"
import type {ToolbarView} from "./toolbar"
import type {StyleSheetLike} from "core/dom"
import * as divider_css from "styles/divider.css"
import type * as p from "core/properties"

export class DividerView extends UIElementView {
declare model: Divider
declare parent: ToolbarView

override stylesheets(): StyleSheetLike[] {
return [...super.stylesheets(), divider_css.default]
}

override render(): void {
super.render()
this.class_list.add(divider_css[this.parent.orientation])
}
}

export namespace Divider {
export type Attrs = p.AttrsOf<Props>
export type Props = UIElement.Props
}

export interface Divider extends Divider.Attrs {}

export class Divider extends UIElement {
declare properties: Divider.Props
declare __view_type__: DividerView

constructor(attrs?: Partial<Divider.Attrs>) {
super(attrs)
}

static {
this.prototype.default_view = DividerView
}
}
53 changes: 53 additions & 0 deletions bokehjs/src/lib/models/tools/logo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {UIElement, UIElementView} from "../ui/ui_element"
import type {ToolbarView} from "./toolbar"
import {LogoStyle as LogoStyle} from "core/enums"
import type {StyleSheetLike} from "core/dom"
import {a} from "core/dom"
import * as logo_css from "styles/logo.css"
import type * as p from "core/properties"

export class LogoView extends UIElementView {
declare model: Logo
declare parent: ToolbarView

override stylesheets(): StyleSheetLike[] {
return [...super.stylesheets(), logo_css.default]
}

override render(): void {
super.render()

this.class_list.add(logo_css.small)
this.class_list.toggle(logo_css.grey, this.model.style == "grey")

const logo_el = a({href: "https://bokeh.org/", target: "_blank"})
this.shadow_el.append(logo_el)
}
}

export namespace Logo {
export type Attrs = p.AttrsOf<Props>

export type Props = UIElement.Props & {
style: p.Property<LogoStyle>
}
}

export interface Logo extends Logo.Attrs {}

export class Logo extends UIElement {
declare properties: Logo.Props
declare __view_type__: LogoView

constructor(attrs?: Partial<Logo.Attrs>) {
super(attrs)
}

static {
this.prototype.default_view = LogoView

this.define<Logo.Props>(() => ({
style: [ LogoStyle, "normal" ],
}))
}
}
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/tools/tool_button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export abstract class ToolButtonView extends UIElementView {

const {location} = this.parent.model
const reverse = location == "left" || location == "above"
const orientation = this.parent.model.horizontal ? "vertical" : "horizontal"
const orientation = this.parent.horizontal ? "vertical" : "horizontal"
const items = this.model.tool.menu ?? []
this._menu = new ContextMenu(!reverse ? items : reversed(items), {
target: this.root.el,
Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/tools/tool_proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {InspectTool} from "./inspectors/inspect_tool"
import type {MenuItem} from "core/util/menus"
import {enumerate, some} from "core/util/iterator"

export type ToolLike<T extends Tool> = T | ToolProxy<T>
export type ToolLike<T extends Tool = Tool> = T | ToolProxy<T>

export namespace ToolProxy {
export type Attrs<T extends Tool> = p.AttrsOf<Props<T>>
Expand Down

0 comments on commit c46660b

Please sign in to comment.