Skip to content

Commit 09175a3

Browse files
authored
Merge pull request #56 from magjac/visual-feedback-of-focus
Visual feedback of focus
2 parents 0f2f06e + fdb0da4 commit 09175a3

File tree

5 files changed

+114
-13
lines changed

5 files changed

+114
-13
lines changed

src/FormatDrawer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class FormatDrawer extends React.Component {
128128
handleClick = () => {
129129
this.setColorColorPickerOpen(false);
130130
this.setFillColorColorPickerOpen(false);
131+
this.props.onClick();
131132
};
132133

133134
handleDrawerClose = () => {

src/Graph.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ class Graph extends React.Component {
259259
}
260260

261261
handleClickDiv(d, i, nodes) {
262+
this.props.onFocus();
262263
document.activeElement.blur();
263264
var event = d3_event;
264265
event.preventDefault();
@@ -267,6 +268,9 @@ class Graph extends React.Component {
267268
}
268269

269270
handleKeyDownDocument(d, i, nodes) {
271+
if (!this.props.hasFocus) {
272+
return;
273+
}
270274
var event = d3_event;
271275
if (event.target.nodeName !== 'BODY') {
272276
return;
@@ -343,6 +347,7 @@ class Graph extends React.Component {
343347
}
344348

345349
handleClickNode(d, i, nodes) {
350+
this.props.onFocus();
346351
document.activeElement.blur();
347352
var event = d3_event;
348353
event.preventDefault();
@@ -354,6 +359,7 @@ class Graph extends React.Component {
354359
}
355360

356361
handleDblClickNode(d, i, nodes) {
362+
this.props.onFocus();
357363
document.activeElement.blur();
358364
var event = d3_event;
359365
event.preventDefault();
@@ -373,6 +379,7 @@ class Graph extends React.Component {
373379
}
374380

375381
handleRightClickNode(d, i, nodes) {
382+
this.props.onFocus();
376383
document.activeElement.blur();
377384
var event = d3_event;
378385
event.preventDefault();
@@ -394,6 +401,7 @@ class Graph extends React.Component {
394401
}
395402

396403
handleClickEdge(d, i, nodes) {
404+
this.props.onFocus();
397405
document.activeElement.blur();
398406
var event = d3_event;
399407
event.preventDefault();
@@ -403,6 +411,7 @@ class Graph extends React.Component {
403411
}
404412

405413
handleRightClickDiv(d, i, nodes) {
414+
this.props.onFocus();
406415
document.activeElement.blur();
407416
var event = d3_event;
408417
event.preventDefault();
@@ -411,6 +420,7 @@ class Graph extends React.Component {
411420
}
412421

413422
handleMouseDownSvg(d, i, nodes) {
423+
this.props.onFocus();
414424
document.activeElement.blur();
415425
var event = d3_event;
416426
if (event.which !== 1) {
@@ -455,6 +465,7 @@ class Graph extends React.Component {
455465
}
456466

457467
handleMouseUpSvg(d, i, nodes) {
468+
this.props.onFocus();
458469
document.activeElement.blur();
459470
var event = d3_event;
460471
if (event.which === 1 && this.selectArea) {
@@ -543,8 +554,10 @@ class Graph extends React.Component {
543554
unSelectComponents() {
544555
this.selectRects.remove();
545556
this.selectRects = d3_select(null);
546-
this.selectedComponents = d3_selectAll(null);
547-
this.props.onSelect([]);
557+
if (this.selectedComponents.size() > 0) {
558+
this.selectedComponents = d3_selectAll(null);
559+
this.props.onSelect([]);
560+
}
548561
}
549562

550563
deleteSelectedComponents() {

src/InsertPanels.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ class InsertPanels extends React.Component {
130130
expanded: null,
131131
};
132132

133+
handleClick = () => {
134+
this.props.onClick();
135+
};
136+
133137
handleChange = panel => (event, expanded) => {
134138
this.setState({
135139
expanded: expanded ? panel : false,
@@ -153,9 +157,13 @@ class InsertPanels extends React.Component {
153157
const { expanded } = this.state;
154158

155159
return (
156-
<div className={classes.root}>
160+
<div className={classes.root} onClick={this.handleClick}>
157161
{nodeShapeCategories.map((nodeShapeCategory) =>
158-
<ExpansionPanel key={nodeShapeCategory.name} expanded={expanded === nodeShapeCategory} onChange={this.handleChange(nodeShapeCategory)}>
162+
<ExpansionPanel
163+
key={nodeShapeCategory.name}
164+
expanded={expanded === nodeShapeCategory}
165+
onChange={this.handleChange(nodeShapeCategory)}
166+
>
159167
<ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
160168
<Typography className={classes.heading}>{nodeShapeCategory.name}</Typography>
161169
</ExpansionPanelSummary>

src/TextEditor.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ class TextEditor extends React.Component {
103103
onChange={this.handleChange}
104104
onBeforeLoad={this.handleBeforeLoad}
105105
onLoad={this.handleLoad}
106+
onFocus={this.props.onFocus}
107+
onBlur={this.props.onBlur}
106108
name="UNIQUE_ID_OF_DIV"
107109
value={this.props.dotSrc}
108110
// viewport height - app bar - 2 * padding

src/pages/index.js

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ const styles = theme => ({
2929
}
3030
});
3131

32+
const defaultElevation = 2;
33+
const focusedElevation = 8;
34+
3235
class Index extends React.Component {
3336

3437
constructor(props) {
@@ -69,6 +72,14 @@ class Index extends React.Component {
6972
};
7073
}
7174

75+
componentDidMount() {
76+
document.onblur = () => {
77+
// Needed when the user clicks outside the document,
78+
// e.g. the browser address bar
79+
this.setFocus(null);
80+
}
81+
}
82+
7283
setPersistentState = (updater) => {
7384
this.setState(updater, function (updater) {
7485
if (typeof updater === 'function') {
@@ -129,13 +140,15 @@ class Index extends React.Component {
129140
});
130141
}
131142

132-
handleInsertClick = () => {
143+
handleInsertButtonClick = () => {
144+
this.setFocusIf('insertPanelsAreOpen', null, 'InsertPanels')
133145
this.setPersistentState({
134146
insertPanelsAreOpen: !this.state.insertPanelsAreOpen,
135147
});
136148
}
137149

138-
handleNodeFormatClick = () => {
150+
handleNodeFormatButtonClick = () => {
151+
this.setFocusIf('nodeFormatDrawerIsOpen', null, 'NodeFormatDrawer')
139152
this.setPersistentState({
140153
nodeFormatDrawerIsOpen: !this.state.nodeFormatDrawerIsOpen,
141154
edgeFormatDrawerIsOpen: false,
@@ -146,9 +159,11 @@ class Index extends React.Component {
146159
this.setPersistentState({
147160
nodeFormatDrawerIsOpen: false,
148161
});
162+
this.setFocus(null);
149163
}
150164

151-
handleEdgeFormatClick = () => {
165+
handleEdgeFormatButtonClick = () => {
166+
this.setFocusIf('edgeFormatDrawerIsOpen', null, 'EdgeFormatDrawer')
152167
this.setPersistentState({
153168
edgeFormatDrawerIsOpen: !this.state.edgeFormatDrawerIsOpen,
154169
nodeFormatDrawerIsOpen: false,
@@ -159,6 +174,7 @@ class Index extends React.Component {
159174
this.setPersistentState({
160175
edgeFormatDrawerIsOpen: false,
161176
});
177+
this.setFocus(null);
162178
}
163179

164180
handleSettingsClick = () => {
@@ -381,9 +397,65 @@ class Index extends React.Component {
381397
this.redo = redo;
382398
}
383399

400+
handleTextEditorFocus = () => {
401+
this.setFocus('TextEditor');
402+
}
403+
404+
handleTextEditorBlur = () => {
405+
// Needed when the user clicks outside of a pane,
406+
// e.g. the app bar or the background
407+
this.setFocusIfFocusIs('TextEditor', null);
408+
}
409+
410+
handleGraphFocus = () => {
411+
this.setFocus('Graph');
412+
}
413+
414+
handleInsertPanelsClick = () => {
415+
this.setFocus('InsertPanels');
416+
}
417+
418+
handleNodeFormatDrawerClick = () => {
419+
this.setFocusIf('nodeFormatDrawerIsOpen', 'NodeFormatDrawer', null)
420+
}
421+
422+
handleEdgeFormatDrawerClick = () => {
423+
this.setFocus('EdgeFormatDrawer');
424+
this.setFocusIf('edgeFormatDrawerIsOpen', 'EdgeFormatDrawer', null)
425+
}
426+
427+
setFocus = (focusedPane) => {
428+
this.setState((state) => (state.focusedPane !== focusedPane && {
429+
focusedPane: focusedPane,
430+
}) || null);
431+
}
432+
433+
setFocusIfFocusIs = (currentlyFocusedPane, newFocusedPane) => {
434+
this.setState((state) => (state.focusedPane === currentlyFocusedPane && {
435+
focusedPane: newFocusedPane,
436+
}) || null);
437+
}
438+
439+
setFocusIf = (stateProperty, focusedPaneIf, focusedPaneElse) => {
440+
this.setState((state) => {
441+
const focusedPane = state[stateProperty] ? focusedPaneIf: focusedPaneElse;
442+
return (state.focusedPane !== focusedPane && {
443+
focusedPane: focusedPane,
444+
}) || null;
445+
});
446+
}
447+
384448
render() {
385449
const { classes } = this.props;
386450
const editorIsOpen = !this.state.nodeFormatDrawerIsOpen && !this.state.edgeFormatDrawerIsOpen;
451+
const textEditorHasFocus = this.state.focusedPane === 'TextEditor';
452+
const nodeFormatDrawerHasFocus = this.state.focusedPane === 'NodeFormatDrawer';
453+
const edgeFormatDrawerHasFocus = this.state.focusedPane === 'EdgeFormatDrawer';
454+
const insertPanelsHaveFocus = this.state.focusedPane === 'InsertPanels';
455+
const graphHasFocus = this.state.focusedPane === 'Graph';
456+
const leftPaneElevation = textEditorHasFocus || nodeFormatDrawerHasFocus || edgeFormatDrawerHasFocus? focusedElevation : defaultElevation;
457+
const rightPaneElevation = graphHasFocus ? focusedElevation : defaultElevation;
458+
const midPaneElevation = insertPanelsHaveFocus ? focusedElevation : defaultElevation;
387459

388460
var columns;
389461
if (this.state.insertPanelsAreOpen && this.state.graphInitialized) {
@@ -407,9 +479,9 @@ class Index extends React.Component {
407479
onMenuButtonClick={this.handleMainMenuButtonClick}
408480
onUndoButtonClick={this.handleUndoButtonClick}
409481
onRedoButtonClick={this.handleRedoButtonClick}
410-
onInsertClick={this.handleInsertClick}
411-
onNodeFormatClick={this.handleNodeFormatClick}
412-
onEdgeFormatClick={this.handleEdgeFormatClick}
482+
onInsertClick={this.handleInsertButtonClick}
483+
onNodeFormatClick={this.handleNodeFormatButtonClick}
484+
onEdgeFormatClick={this.handleEdgeFormatButtonClick}
413485
onZoomInButtonClick={this.handleZoomInButtonClick}
414486
onZoomOutButtonClick={this.handleZoomOutButtonClick}
415487
onZoomOutMapButtonClick={this.handleZoomOutMapButtonClick}
@@ -454,11 +526,12 @@ class Index extends React.Component {
454526
}}
455527
>
456528
<Grid item xs={columns.textEditor}>
457-
<Paper className={classes.paper}>
529+
<Paper elevation={leftPaneElevation} className={classes.paper}>
458530
<FormatDrawer
459531
type='node'
460532
open={this.state.nodeFormatDrawerIsOpen}
461533
defaultAttributes={this.state.defaultNodeAttributes}
534+
onClick={this.handleNodeFormatDrawerClick}
462535
onFormatDrawerClose={this.handleNodeFormatDrawerClose}
463536
onStyleChange={this.handleNodeStyleChange}
464537
onColorChange={this.handleNodeColorChange}
@@ -468,6 +541,7 @@ class Index extends React.Component {
468541
type='edge'
469542
open={this.state.edgeFormatDrawerIsOpen}
470543
defaultAttributes={this.state.defaultEdgeAttributes}
544+
onClick={this.handleEdgeFormatDrawerClick}
471545
onFormatDrawerClose={this.handleEdgeFormatDrawerClose}
472546
onStyleChange={this.handleEdgeStyleChange}
473547
onColorChange={this.handleEdgeColorChange}
@@ -494,8 +568,9 @@ class Index extends React.Component {
494568
</Grid>
495569
{this.state.insertPanelsAreOpen && this.state.graphInitialized && (
496570
<Grid item xs={columns.insertPanels}>
497-
<Paper className={classes.paper}>
571+
<Paper elevation={midPaneElevation} className={classes.paper}>
498572
<InsertPanels
573+
onClick={this.handleInsertPanelsClick}
499574
onNodeShapeClick={this.handleNodeShapeClick}
500575
onNodeShapeDragStart={this.handleNodeShapeDragStart}
501576
onNodeShapeDragEnd={this.handleNodeShapeDragEnd}
@@ -504,8 +579,9 @@ class Index extends React.Component {
504579
</Grid>
505580
)}
506581
<Grid item xs={columns.graph}>
507-
<Paper className={classes.paper}>
582+
<Paper elevation={rightPaneElevation} className={classes.paper}>
508583
<Graph
584+
hasFocus={graphHasFocus}
509585
dotSrc={this.state.dotSrc}
510586
engine={this.state.engine}
511587
fit={this.state.fitGraph}
@@ -515,6 +591,7 @@ class Index extends React.Component {
515591
tweenPrecision={this.state.tweenPrecision}
516592
defaultNodeAttributes={this.state.defaultNodeAttributes}
517593
defaultEdgeAttributes={this.state.defaultEdgeAttributes}
594+
onFocus={this.handleGraphFocus}
518595
onTextChange={this.handleTextChange}
519596
onHelp={this.handleKeyboardShortcutsClick}
520597
onSelect={this.handleGraphComponentSelect}

0 commit comments

Comments
 (0)