title: $:/core/macros/sidebar-resizer

\function is.pixel.value(value) [<value>removesuffix[px]]
\function is.percentage.value(value) [<value>removesuffix[%]]
\function is.cm.value(value) [<value>removesuffix[cm]]
\function is.mm.value(value) [<value>removesuffix[mm]]
\function is.Q.value(value) [<value>removesuffix[Q]]
\function is.in.value(value) [<value>removesuffix[in]]
\function is.pc.value(value) [<value>removesuffix[pc]]
\function is.pt.value(value) [<value>removesuffix[pt]]
\function is.em.value(value) [<value>removesuffix[em]]

\function convert.to.percentage(value) [<value>divide<widgetNodeWidth>multiply[100]]
\function convert.to.cm(value) [<value>divide[37.8]]
\function convert.to.mm(value) [convert.to.cm<value>multiply[10]]
\function convert.to.Q(value) [convert.to.cm<value>multiply[40]]
\function convert.to.in(value) [<value>divide[96]]
\function convert.to.pc(value) [convert.to.in<value>multiply[6]]
\function convert.to.pt(value) [convert.to.in<value>multiply[72]]
\function convert.to.em(value) [<value>divide{$:/themes/tiddlywiki/vanilla/metrics/fontsize}]

\function convert.to.percentage.value() [convert.to.percentage<value>]
\function convert.to.cm.value() [convert.to.cm<value>]
\function convert.to.mm.value() [convert.to.mm<value>]
\function convert.to.Q.value() [convert.to.Q<value>]
\function convert.to.in.value() [convert.to.in<value>]
\function convert.to.pc.value() [convert.to.pc<value>]
\function convert.to.pt.value() [convert.to.pt<value>]
\function convert.to.em.value() [convert.to.em<value>]

\function convert.to.pixels(value) [is.pixel.value<value>] [is.percentage.value<value>multiply<widgetNodeWidth>divide[100]] [is.cm.value<value>multiply[37.8]] [is.mm.value<value>multiply[37.8]divide[10]] [is.Q.value<value>multiply[37.8]divide[40]] [is.in.value<value>multiply[96]] [is.pc.value<value>multiply[96]divide[6]] [is.pt.value<value>multiply[96]divide[72]] [is.em.value<value>multiply{$:/themes/tiddlywiki/vanilla/metrics/fontsize}]

\function convert.to.result(value,suffix) [<suffix>match[px]then<value>] [<suffix>match[%]then<convert.to.percentage.value>] [<suffix>match[cm]then<convert.to.cm.value>] [<suffix>match[mm]then<convert.to.mm.value>] [<suffix>match[Q]then<convert.to.Q.value>] [<suffix>match[in]then<convert.to.in.value>] [<suffix>match[pc]then<convert.to.pc.value>] [<suffix>match[pt]then<convert.to.pt.value>] [<suffix>match[em]then<convert.to.em.value>]

\function get.value.metric(value) [<value>suffix[px]then[px]] :else[<value>suffix[%]then[%]] :else[<value>suffix[cm]then[cm]] :else[<value>suffix[mm]then[mm]] :else[<value>suffix[Q]then[Q]] :else[<value>suffix[in]then[in]] :else[<value>suffix[pc]then[pc]] :else[<value>suffix[pt]then[pt]] :else[<value>suffix[em]then[em]]

\procedure set_theme_throttling(metric)
<$set name="metricsTiddler" value={{{ [function[get.theme],<metric>] }}}>
	<%if [<metricsTiddler>!has[throttle.refresh]] %>
		<$action-setfield $tiddler=<<metricsTiddler>> throttle.refresh="yes"/>
	<% endif %>
</$set>
\end

\procedure sidebar-resizer-pointerdown-actions()
<%if [[$:/state/sidebar/resizing]is[missing]then<event-mousebutton>match[left]] %>
	<$let
		startStoryLeft={{{ [<storyLeftTiddler>!is[blank]get[text]] :else[get.theme.metric[storyleft]] }}}
		startStoryRight={{{ [<storyRightTiddler>!is[blank]get[text]] :else[get.theme.metric[storyright]] }}}
		startSidebarWidth={{{ [<sidebarWidthTiddler>!is[blank]get[text]] :else[get.theme.metric[sidebarwidth]] }}}
		startTiddlerWidth={{{ [<tiddlerWidthTiddler>!is[blank]get[text]] :else[get.theme.metric[tiddlerwidth]] }}}
		startStoryWidth={{{ [<storyWidthTiddler>!is[blank]get[text]] :else[get.theme.metric[storywidth]] }}}>
		<$action-setfield $tiddler="$:/state/sidebar/resizing"
			text="yes"
			widget-node-width=<<tv-widgetnode-width>>
			start-posx=<<event-fromcatcher-posx>>
			start-story-left=<<startStoryLeft>>
			story-left-metric={{{ [get.value.metric<startStoryLeft>] }}}
			start-story-right=<<startStoryRight>>
			story-right-metric={{{ [get.value.metric<startStoryRight>] }}}
			start-sidebar-width=<<startSidebarWidth>>
			sidebar-width-metric={{{ [get.value.metric<startSidebarWidth>] }}}
			start-tiddler-width=<<startTiddlerWidth>>
			tiddler-width-metric={{{ [get.value.metric<startTiddlerWidth>] }}}
			start-story-width=<<startStoryWidth>>
			story-width-metric={{{ [get.value.metric<startStoryWidth>] }}}
		/>
	</$let>
<% endif %>
\end

\procedure sidebar-resizer-pointercancel-actions()
<$action-deletetiddler $tiddler="$:/state/sidebar/resizing"/>
\end

\procedure set-storywidth-storyright-actions()
<$let
	storyRightStart={{{ [convert.to.pixels{$:/state/sidebar/resizing!!start-story-right}] }}}
	storyWidthStart={{{ [convert.to.pixels{$:/state/sidebar/resizing!!start-story-width}] }}}
	storyMinWidthValue={{{ [<storyMinWidthTiddler>!is[blank]get[text]] :else[<get.theme.metric storyminwidth>] }}}
	storyMinWidth={{{ [convert.to.pixels<storyMinWidthValue>] }}}
	sidebarMinWidthValue={{{ [<sidebarMinWidthTiddler>!is[blank]get[text]] :else[<get.theme.metric sidebarminwidth>] }}}
	sidebarMinWidth={{{ [convert.to.pixels<sidebarMinWidthValue>] }}}
	storyPaddingLeftValue={{{ [<storyPaddingLeftTiddler>!is[blank]get[text]] :else[get.theme.metric[metrics/storypaddingleft]] }}}
	storyPaddingLeft={{{ [convert.to.pixels<storyPaddingLeftValue>] }}}
	storyPaddingRightValue={{{ [<storyPaddingRightTiddler>!is[blank]get[text]] :else[get.theme.metric[metrics/storypaddingright]] }}}
	storyPaddingRight={{{ [convert.to.pixels<storyPaddingRightValue>] }}}
	storyLeftValue={{{ [<storyLeftTiddler>!is[blank]get[text]] :else[<get.theme.metric storyleft>] }}}
	storyLeft={{{ [convert.to.pixels<storyLeftValue>] }}}
	clampedDiff={{{ [<storyWidthStart>add<storyLeft>add<sidebarMinWidth>subtract<widgetNodeWidth>compare:number:gt[0]] ~0 }}}
	storyWidthStart={{{ [<storyWidthStart>subtract<clampedDiff>] }}}
	storyRightStart={{{ [<storyRightStart>subtract<clampedDiff>] }}}
	storyWidth={{{ [<storyWidthStart>add<dragDiff>] }}}
	innerStoryWidth={{{ [<storyWidth>subtract<storyPaddingLeft>subtract<storyPaddingRight>] }}}
	innerStoryWidthStart={{{ [<storyWidthStart>subtract<storyPaddingLeft>subtract<storyPaddingRight>] }}}
	storyMinWidthAddLeft={{{ [<storyMinWidth>add<storyLeft>] }}}
	storyRiverLimit={{{ [<widgetNodeWidth>subtract<sidebarMinWidth>] }}}
	storyMaxWidth={{{ [<storyRiverLimit>subtract<storyLeft>] }}}
	tiddlerWidthMetric={{$:/state/sidebar/resizing!!tiddler-width-metric}}
	tiddlerWidthStart={{$:/state/sidebar/resizing!!start-tiddler-width}}
	tiddlerWidthStartPixels={{{ [<tiddlerWidthMetric>match[%]then<tiddlerWidthStart>multiply<innerStoryWidthStart>divide[100]] :else[convert.to.pixels<tiddlerWidthStart>] }}}
	tiddlerWidthClampedDiff={{{ [<tiddlerWidthStartPixels>add<storyPaddingLeft>add<storyPaddingRight>add<storyLeft>add<sidebarMinWidth>subtract<widgetNodeWidth>compare:number:gt[0]] ~0 }}}
	tiddlerWidth={{{ [<tiddlerWidthStartPixels>add<dragDiff>subtract<tiddlerWidthClampedDiff>] }}}
	tiddlerWidthDiff={{{ [<storyWidth>subtract<tiddlerWidth>] }}}
	tiddlerMinWidth={{{ [<tiddlerWidthMetric>match[%]then<tiddlerWidth>] :else[<storyMinWidth>subtract<tiddlerWidthDiff>] }}}
	tiddlerMaxWidth={{{ [<tiddlerWidthMetric>match[%]then<tiddlerWidth>] :else[<storyMaxWidth>subtract<tiddlerWidthDiff>] }}}
	storyRiverWidth={{{ [<storyRiverWidth>subtract<clampedDiff>] }}}>

	<$let
		storyWidthMetric={{$:/state/sidebar/resizing!!story-width-metric}}
		storyWidthConverted={{{ [function[convert.to.result],<storyWidth>,<storyWidthMetric>] }}}
		storyMinWidthConverted={{{ [function[convert.to.result],<storyMinWidth>,<storyWidthMetric>] }}}
		storyMaxWidthConverted={{{ [function[convert.to.result],<storyMaxWidth>,<storyWidthMetric>] }}}
		tiddlerWidthConverted={{{ [<tiddlerWidthMetric>match[%]then<tiddlerWidth>multiply[100]divide<innerStoryWidth>] :else[function[convert.to.result],<tiddlerWidth>,<tiddlerWidthMetric>] }}}
		tiddlerMinWidthConverted={{{ [<tiddlerWidthMetric>match[%]then<tiddlerMinWidth>multiply[100]divide<innerStoryWidth>] :else[function[convert.to.result],<tiddlerMinWidth>,<tiddlerWidthMetric>] }}}
		tiddlerMaxWidthConverted={{{ [<tiddlerWidthMetric>match[%]then<tiddlerMaxWidth>multiply[100]divide<innerStoryWidth>] :else[function[convert.to.result],<tiddlerMaxWidth>,<tiddlerWidthMetric>] }}}
		storyWidthSetTiddler={{{ [<storyWidthTiddler>!is[blank]] :else[<set.theme.metric storywidth>] }}}
		tiddlerWidthSetTiddler={{{ [<tiddlerWidthTiddler>!is[blank]] :else[<set.theme.metric tiddlerwidth>] }}}

		storyWidthResult={{{ [<storyWidth>compare:number:lt<storyMinWidth>then<storyMinWidthConverted>addsuffix<storyWidthMetric>] :else[<storyWidth>compare:number:gteq<storyMaxWidth>then<storyMaxWidthConverted>addsuffix<storyWidthMetric>] :else[<storyWidthConverted>addsuffix<storyWidthMetric>] }}}

		tiddlerWidthResult={{{  [<tiddlerWidthMetric>match[%]then<storyWidth>compare:number:lt<storyMinWidth>then<get.theme.metric tiddlerwidth>compare:number:gteq[0]then<get.theme.metric tiddlerwidth>] :else[<tiddlerWidthMetric>match[%]then<storyWidth>compare:number:gt<storyMaxWidth>then<get.theme.metric tiddlerwidth>] :else[<tiddlerWidthMetric>!match[%]then<tiddlerWidth>compare:number:lt<tiddlerMinWidth>then<tiddlerMinWidthConverted>addsuffix<tiddlerWidthMetric>] :else[<tiddlerWidthMetric>!match[%]then<tiddlerWidth>compare:number:gteq<tiddlerMaxWidth>then<tiddlerMaxWidthConverted>addsuffix<tiddlerWidthMetric>] :else[<tiddlerWidth>compare:number:lt[0]then[0]addsuffix<tiddlerWidthMetric>] :else[<tiddlerWidthConverted>addsuffix<tiddlerWidthMetric>] }}}>

		<$action-setfield $tiddler=<<tiddlerWidthSetTiddler>> text=<<tiddlerWidthResult>>/>
		<$action-setfield $tiddler=<<storyWidthSetTiddler>> text=<<storyWidthResult>>/>

	</$let>

	<$let
		storyRightMetric={{$:/state/sidebar/resizing!!story-right-metric}}
		storyRiverWidthConverted={{{ [function[convert.to.result],<storyRiverWidth>,<storyRightMetric>] }}}
		storyRiverLimitConverted={{{ [function[convert.to.result],<storyRiverLimit>,<storyRightMetric>] }}}
		storyMinWidthAddLeftConverted={{{ [function[convert.to.result],<storyMinWidthAddLeft>,<storyRightMetric>] }}}
		storyRightSetTiddler={{{ [<storyRightTiddler>!is[blank]] :else[<set.theme.metric storyright>] }}}

		result={{{ [<storyRiverWidth>compare:number:lt<storyMinWidthAddLeft>then<storyMinWidthAddLeftConverted>addsuffix<storyRightMetric>] :else[<storyRiverWidth>compare:number:gteq<storyRiverLimit>then<storyRiverLimitConverted>addsuffix<storyRightMetric>] :else[<storyRiverWidthConverted>addsuffix<storyRightMetric>] }}}>

		<$action-setfield $tiddler=<<storyRightSetTiddler>> text=<<result>>/>

	</$let>

</$let>
\end

\procedure set-sidebarwidth-actions()
<$let
	sidebarMinWidthValue={{{ [<sidebarMinWidthTiddler>!is[blank]get[text]] :else[<get.theme.metric sidebarminwidth>] }}}
	sidebarWidthMetric={{$:/state/sidebar/resizing!!sidebar-width-metric}}
	sidebarMinWidth={{{ [convert.to.pixels<sidebarMinWidthValue>] }}}
	storyLeftValue={{{ [<storyLeftTiddler>!is[blank]get[text]] :else[<get.theme.metric storyleft>] }}}
	storyLeft={{{ [convert.to.pixels<storyLeftValue>] }}}
	storyMinWidthValue={{{ [<storyMinWidthTiddler>!is[blank]get[text]] :else[<get.theme.metric storyminwidth>] }}}
	storyMinWidth={{{ [convert.to.pixels<storyMinWidthValue>] }}}
	sidebarMaxWidth={{{ [<widgetNodeWidth>subtract<storyLeft>subtract<storyMinWidth>] }}}
	clampedDiff={{{ [<storyLeft>add<storyMinWidth>add<startSidebarWidth>subtract<widgetNodeWidth>compare:number:gt[0]] ~0 }}}
	sidebarWidth={{{ [<sidebarWidth>subtract<clampedDiff>] }}}>
	
	<$let
		sidebarWidthConverted={{{ [function[convert.to.result],<sidebarWidth>,<sidebarWidthMetric>] }}}
		sidebarMaxWidthConverted={{{ [function[convert.to.result],<sidebarMaxWidth>,<sidebarWidthMetric>] }}}
		sidebarMinWidthConverted={{{ [function[convert.to.result],<sidebarMinWidth>,<sidebarWidthMetric>] }}}
		sidebarWidthSetTiddler={{{ [<sidebarWidthTiddler>!is[blank]] :else[<set.theme.metric sidebarwidth>] }}}>
		
		<$action-setfield $tiddler=<<sidebarWidthSetTiddler>> text={{{ [<sidebarWidth>compare:number:gteq<sidebarMaxWidth>then<sidebarMaxWidthConverted>addsuffix<sidebarWidthMetric>] :else[<sidebarWidth>compare:number:lt<sidebarMinWidth>then<sidebarMinWidthConverted>addsuffix<sidebarWidthMetric>] :else[<sidebarWidthConverted>addsuffix<sidebarWidthMetric>] }}}/>
	</$let>
</$let>
\end

\procedure set-centralised-actions()
<$let
	storyMinWidthValue={{{ [<storyMinWidthTiddler>!is[blank]get[text]] :else[{$:/themes/tiddlywiki/centralised/metrics/storyminwidth}] }}}
	storyMinWidth={{{ [convert.to.pixels<storyMinWidthValue>] }}}
	storyWidthStart={{{ [convert.to.pixels{$:/state/sidebar/resizing!!start-story-width}] }}}
	sidebarMinWidthValue={{{ [<sidebarMinWidthTiddler>!is[blank]get[text]] :else[{$:/themes/tiddlywiki/centralised/metrics/sidebarminwidth}] }}}
	sidebarMinWidth={{{ [convert.to.pixels<sidebarMinWidthValue>] }}}
	storyMaxWidth={{{ [<widgetNodeWidth>subtract<sidebarMinWidth>subtract<sidebarMinWidth>] }}}
	dragDiffMultiplied={{{ [<dragDiff>multiply[2]] }}}
	storyWidthClamped={{{ [<storyWidthStart>add<sidebarMinWidth>add<sidebarMinWidth>subtract<widgetNodeWidth>compare:number:gt[0]] ~0 }}}
	storyWidth={{{ [<storyWidthStart>add<dragDiffMultiplied>] }}}
	storyWidth={{{ [<storyWidth>subtract<storyWidthClamped>] }}}>

	<$let
		storyWidthMetric={{$:/state/sidebar/resizing!!story-width-metric}}
		storyWidthConverted={{{ [function[convert.to.result],<storyWidth>,<storyWidthMetric>] }}}
		storyMinWidthConverted={{{ [function[convert.to.result],<storyMinWidth>,<storyWidthMetric>] }}}
		storyMaxWidthConverted={{{ [function[convert.to.result],<storyMaxWidth>,<storyWidthMetric>] }}}
		storyWidthSetTiddler={{{ [<storyWidthTiddler>!is[blank]] :else[<set.theme.metric storywidth>] }}}>

		<$action-setfield $tiddler=<<storyWidthSetTiddler>> text={{{ [<storyWidth>compare:number:lt<storyMinWidth>then<storyMinWidthConverted>addsuffix<storyWidthMetric>] :else[<storyWidth>compare:number:gteq<storyMaxWidth>then<storyMaxWidthConverted>addsuffix<storyWidthMetric>] :else[<storyWidthConverted>addsuffix<storyWidthMetric>] }}}/>

	</$let>

</$let>
\end

\function get.drag.diff() [<event-fromcatcher-posx>subtract{$:/state/sidebar/resizing!!start-posx}] :map[{$:/themes/tiddlywiki/vanilla/options/sidebarposition}match[left]then<currentTiddler>multiply[-1]else<currentTiddler>]

\procedure sidebar-resizer-pointermove-actions()
<%if [[$:/state/sidebar/resizing]!is[missing]] %>
	<$let widgetNodeWidth={{$:/state/sidebar/resizing!!widget-node-width}} dragDiff=<<get.drag.diff>> startStoryRight={{{ [convert.to.pixels{$:/state/sidebar/resizing!!start-story-right}] }}} storyRiverWidth={{{ [<startStoryRight>add<dragDiff>] }}} startSidebarWidth={{{ [convert.to.pixels{$:/state/sidebar/resizing!!start-sidebar-width}] }}} sidebarWidth={{{ [<startSidebarWidth>subtract<dragDiff>] }}}>
		<%if [<tv-set-storywidth-storyright>match[yes]] %>
			<<set_theme_throttling storyright>>
			<<set_theme_throttling tiddlerwidth>>
			<<set_theme_throttling storywidth>>
			<<set-storywidth-storyright-actions>>
		<% endif %>
		<%if [<tv-set-sidebarwidth>match[yes]] %>
			<<set_theme_throttling sidebarwidth>>
			<<set-sidebarwidth-actions>>
		<% endif %>
		<%if [<tv-set-centralised>match[yes]] %>
			<<set_theme_throttling storywidth>>
			<<set-centralised-actions>>
		<% endif %>
	</$let>
<% endif %>
\end

\procedure sidebar-resizer()
<$eventcatcher
	tag="div"
	class="tc-sidebar-resizer-pointerdown-eventcatcher"
	selector=".tc-sidebar-resizer"
	matchSelector=".tc-sidebar-resizer"
	$pointerdown=<<sidebar-resizer-pointerdown-actions>>
	$pointerup=<<sidebar-resizer-pointercancel-actions>>>

	<%if [{$:/state/sidebar}!match[no]] %>

		<$eventcatcher
			tag="div"
			class="tc-sidebar-resizer-pointermove-eventcatcher-wrapper"
			selector=".tc-sidebar-resizer"
			matchSelector=".tc-sidebar-resizer"
			$pointerup={{{ [[$:/state/sidebar/resizing]!is[missing]then<sidebar-resizer-pointercancel-actions>] }}}>

			<$eventcatcher
				tag="div"
				selector=".tc-sidebar-resizer-pointermove"
				matchSelector=".tc-sidebar-resizer-pointermove"
				class="tc-sidebar-resizer-pointermove-eventcatcher"
				$pointerup=<<sidebar-resizer-pointercancel-actions>>
				$pointerleave=<<sidebar-resizer-pointercancel-actions>>
				$pointerout=<<sidebar-resizer-pointercancel-actions>>
				$pointercancel=<<sidebar-resizer-pointercancel-actions>>
				$pointerdown=<<sidebar-resizer-pointercancel-actions>>
				$touchstart=<<sidebar-resizer-pointercancel-actions>>
				$pointermove=<<sidebar-resizer-pointermove-actions>>
				$contextmenu=<<sidebar-resizer-pointercancel-actions>>>

				<div class="tc-sidebar-resizer-pointermove"/>

			</$eventcatcher>

			<div class="tc-sidebar-resizer"/>

		</$eventcatcher>

	<% endif %>

</$eventcatcher>
\end
