Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

Commit

Permalink
Restyle wild menu/add commandline cursor (#1191)
Browse files Browse the repository at this point in the history
* Rework styling to match quickopen menu

also add icon - file icon atm ?alternatives

* Render wild menu into the stack layer

* Reduce padding

* Compose wild menu with commandline

* Configure wild menu and commandline

Components now render in the same layer and
can be positioned similarly if both present
or interchangeably if one options is disabled

* Render components separately inside of common

container

* Attempt to manually place external menus not working

* add space to constructor

* Add timeout to prevent flickering of cmdline

Also only render overlay if both elements present

* revert changes to neovim surface

* wire up setcursor actions

* Add a cursor to commandline

* Remove excess space

* Remove refs from commandline components

* re-add focus as this is essential for functionality

* important: fix html trimming whitespace bug

using whitespace: pre-wrap from one of see
facebook/react#4134
html auto removes trailing white space breaking
the cursor's position functionality

* add in the prompt segment

* fix overflow styling

* add pointer events but not selection

* Add overflow handling for command line

* minor change to comment position

* adjust cursor position

* re-add missing max width
to ensure commandline and wild menu have
same width

* re-arrange css to rerun tests

* re-arrange css again..

* reduce timeout to 80ms

* Add spurious CR to rerun test
  • Loading branch information
akinsho authored and bryphe committed Jan 4, 2018
1 parent 7e6954b commit f2d769d
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 115 deletions.
4 changes: 4 additions & 0 deletions browser/src/Editor/NeovimEditor/NeovimEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ export class NeovimEditor extends Editor implements IEditor {
this._actions.hideCommandLine()
})

this._neovimInstance.onCommandLineSetCursorPosition.subscribe(commandLinePos => {
this._actions.setCommandLinePosition(commandLinePos)
})

this._windowManager.onWindowStateChanged.subscribe((tabPageState) => {

const inactiveIds = tabPageState.inactiveWindows.map((w) => w.windowNumber)
Expand Down
10 changes: 8 additions & 2 deletions browser/src/Editor/NeovimEditor/NeovimEditorActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,13 @@ export const setColors = (colors: IThemeColors) => ({
},
})

export const setCommandLinePosition = (position: number, level: number) => ({
export const setCommandLinePosition = ({
pos: position,
level,
}: {
pos: number,
level: number,
}) => ({
type: "SET_COMMAND_LINE_POSITION",
payload: {
position,
Expand All @@ -362,7 +368,7 @@ export const showCommandLine = (
type: "SHOW_COMMAND_LINE",
payload: {
content,
pos,
position: pos,
firstchar,
prompt,
indent,
Expand Down
42 changes: 31 additions & 11 deletions browser/src/Editor/NeovimEditor/NeovimEditorReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function reducer<K extends keyof IConfigurationValues>(s: State.IState, a
return {
...s,
colors: a.payload.colors,
}
}
case "SET_NEOVIM_ERROR":
return { ...s,
neovimError: a.payload.neovimError }
Expand All @@ -55,20 +55,25 @@ export function reducer<K extends keyof IConfigurationValues>(s: State.IState, a
cursorCharacter: a.payload.cursorCharacter,
cursorPixelWidth: a.payload.cursorPixelWidth }
case "SET_IME_ACTIVE":
return { ...s,
imeActive: a.payload.imeActive }
return {
...s,
imeActive: a.payload.imeActive,
}
case "SET_FONT":
return { ...s,
fontFamily: a.payload.fontFamily,
fontSize: a.payload.fontSize }
return {
...s,
fontFamily: a.payload.fontFamily,
fontSize: a.payload.fontSize,
}
case "SET_MODE":
return { ...s, ...{ mode: a.payload.mode } }
case "SET_CONFIGURATION_VALUE":
const obj: Partial<IConfigurationValues> = {}
obj[a.payload.key] = a.payload.value
const newConfig = {...s.configuration, ...obj}
return {...s,
configuration: newConfig,
return {
...s,
configuration: newConfig,
}
case "SHOW_WILDMENU":
return {
Expand Down Expand Up @@ -96,10 +101,13 @@ export function reducer<K extends keyof IConfigurationValues>(s: State.IState, a
},
}
case "SHOW_COMMAND_LINE":
// Array<[any, string]>
const [[, content]] = a.payload.content
return {
...s,
commandLine: {
content: a.payload.content,
content,
visible: true,
position: a.payload.position,
firstchar: a.payload.firstchar,
prompt: a.payload.prompt,
Expand All @@ -110,12 +118,24 @@ export function reducer<K extends keyof IConfigurationValues>(s: State.IState, a
case "HIDE_COMMAND_LINE":
return {
...s,
commandLine: null,
commandLine: {
visible: false,
content: null,
firstchar: "",
position: null,
prompt: "",
indent: null,
level: null,
},
}
case "SET_COMMAND_LINE_POSITION":
return {
...s,
commandLine : {...s.commandLine, position: a.payload.position},
commandLine : {
...s.commandLine,
position: a.payload.position,
level: a.payload.level,
},
}
default:
return {...s,
Expand Down
13 changes: 11 additions & 2 deletions browser/src/Editor/NeovimEditor/NeovimEditorStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ export interface IWildMenu {
}

export interface ICommandLine {
content: Array<[any, string]>,
visible: boolean,
content: string,
firstchar: string,
position: number,
prompt: string,
Expand Down Expand Up @@ -209,7 +210,15 @@ export const createDefaultState = (): IState => ({

errors: {},
toolTips: {},
commandLine: null,
commandLine: {
content: null,
prompt: null,
indent: null,
level: null,
visible: false,
firstchar: "",
position: 0,
},
wildmenu: {
selected: null,
visible: false,
Expand Down
9 changes: 6 additions & 3 deletions browser/src/Editor/NeovimEditor/NeovimSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import { IEvent } from "oni-types"
import { NeovimInstance, NeovimScreen } from "./../../neovim"
import { INeovimRenderer } from "./../../Renderer"

import { CommandLine } from "./../../UI/components/CommandLine"
import CommandLine from "./../../UI/components/CommandLine"
import { Cursor } from "./../../UI/components/Cursor"
import { CursorLine } from "./../../UI/components/CursorLine"
import ExternalMenus from "./../../UI/components/ExternalMenus"
import { InstallHelp } from "./../../UI/components/InstallHelp"
import { TabsContainer } from "./../../UI/components/Tabs"
import { ToolTips } from "./../../UI/components/ToolTip"
Expand Down Expand Up @@ -61,6 +62,10 @@ export class NeovimSurface extends React.PureComponent<INeovimSurfaceProps, {}>
onTabSelect={this.props.onTabSelect}/>
</div>
<div className="container full">
<ExternalMenus>
<CommandLine />
<WildMenu />
</ExternalMenus>
<div className="stack">
<NeovimRenderer renderer={this.props.renderer}
neovimInstance={this.props.neovimInstance}
Expand All @@ -69,8 +74,6 @@ export class NeovimSurface extends React.PureComponent<INeovimSurfaceProps, {}>
<div className="stack layer">
<TypingPrediction typingPrediction={this.props.typingPrediction}/>
<Cursor typingPrediction={this.props.typingPrediction}/>
<CommandLine />
<WildMenu />
<CursorLine lineType={"line"} />
<CursorLine lineType={"column"} />
<NeovimActiveWindowContainer>
Expand Down
120 changes: 68 additions & 52 deletions browser/src/UI/components/CommandLine.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,73 @@
import * as React from "react"
import { connect } from "react-redux"
import styled from "styled-components"

import { fadeInAndDown } from "./animations"
import { boxShadow } from "./common"

import * as State from "./../../Editor/NeovimEditor/NeovimEditorStore"

const CommandLineBackground = styled.div`
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
background-color: rgba(0, 0, 0, 0.25);
display: flex;
flex-direction: column;
align-items: center;
`

const CommandLineBox = styled.div`
position: relative;
margin-top: 16px;
padding: 8px;
width: 75%;
max-width: 900px;
background-color: ${p => p.theme.background};
box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
background-color: ${p => p.theme["menu.background"]};
${boxShadow};
animation: ${fadeInAndDown} 0.08s ease-in;
box-sizing: border-box;
overflow-wrap: break-word;
`
const CommandLineInput = styled.input`
const CommandLineOutput = styled.div`
white-space: pre-wrap; /* CRUCIAL to render white-space correctly */
position: relative;
border: 0px;
background-color: rgba(0, 0, 0, 0.2);
font-size: 1.1em;
box-sizing: border-box;
width: 100%;
height: auto;
padding: 8px;
outline: none;
color: white;
`

const Cursor = styled.span`
background-color: white;
width: 2px;
position: absolute;
bottom: 6px;
height: 1.3em;
`

export interface ICommandLineRendererProps {
visible: boolean,
content: Array<[any, string]> | null
position: number,
visible: boolean
content: string
position: number
firstchar: string
// level: number
level: number
prompt: string
}

interface State {
focused: boolean,
focused: boolean
waiting: boolean
}

class CommandLineRenderer extends React.PureComponent<ICommandLineRendererProps, State> {
class CommandLine extends React.PureComponent<ICommandLineRendererProps, State> {
public state = {
focused: false,
waiting: true,
}

private timer: any
private _inputElement: HTMLInputElement

public handleChange(e: React.ChangeEvent<HTMLInputElement>) {
// UI.Actions.setCommandLinePosition(1, 1)
public componentDidMount() {
this.timer = setTimeout(() => {
this.setState({ waiting: false })
}, 80)
}

public componentWillReceiveProps(nextProps: ICommandLineRendererProps) {
Expand All @@ -66,41 +76,47 @@ class CommandLineRenderer extends React.PureComponent<ICommandLineRendererProps,
}
}

public render(): null | JSX.Element {
if (!this.state.focused && this.props.visible && this._inputElement) {
this._inputElement.focus()
public componentWillUnmount() {
clearTimeout(this.timer)
}

public render(): null | JSX.Element {
const { visible, content, position } = this.props
const { focused, waiting } = this.state
if (!focused && visible && this._inputElement) {
this._inputElement.focus()
}

return this.props.visible && (
<CommandLineBackground>
const segments = content.split("")
const beginning = segments.slice(0, position)
const end = segments.slice(position)

return (
!waiting &&
visible && (
<CommandLineBox>
<CommandLineInput
onChange={this.handleChange}
innerRef={e => (this._inputElement = e)}
value={this.props.firstchar + this.props.content[0][1]}
/>
<CommandLineOutput innerRef={e => (this._inputElement = e)}>
{this.props.firstchar}
{this.props.prompt}
{beginning}
<Cursor />
{end}
</CommandLineOutput>
</CommandLineBox>
</CommandLineBackground>
)
)
}
}

const mapStateToProps = ({ commandLine }: State.IState, props: ICommandLineRendererProps) => {
const commandLineProps: ICommandLineRendererProps = {
content: null,
visible: false,
firstchar: "",
position: 0,
}

if (commandLine) {
commandLineProps.visible = commandLine !== null
commandLineProps.content = commandLine.content
commandLineProps.firstchar = commandLine.firstchar
commandLineProps.position = commandLine !== null ? commandLine.position : 0
}

return commandLineProps
}
const mapStateToProps = ({
commandLine: { visible, position, content, firstchar, level, prompt },
}: State.IState) => ({
visible,
content,
firstchar,
position,
level,
prompt,
})

export const CommandLine = connect<ICommandLineRendererProps>(mapStateToProps)(CommandLineRenderer)
export default connect<ICommandLineRendererProps>(mapStateToProps)(CommandLine)
Loading

0 comments on commit f2d769d

Please sign in to comment.