gabrielbull / react-desktop

React UI Components for macOS High Sierra and Windows 10
http://reactdesktop.js.org
MIT License
9.52k stars 462 forks source link

Element to Render Window Component to for Styling entire Application #65

Closed erichiller closed 8 years ago

erichiller commented 8 years ago

In going through the samples, it is unclear what element I should render the window component to in order to style the entire application window. Currently my BrowserWindow is:

  mainWindow = new BrowserWindow(
    { 
      width: 800 ,
      height: 600 ,
      //center: false ,
      //title: CONFIG.Title ,
      frame: false,  // causes no title bar on OSX
      //icon: /** see https://github.com/electron/electron/blob/master/docs/api/native-image.md --> The window icon. On Windows it is recommended to use ICO icons to get best visual effects, you can also leave it undefined so the executable's icon will be used. **/ "",
      //backgroundColor: /** String - Window's background color as Hexadecimal value, like #66CD00 or #FFF or #80FFFFFF (alpha is supported). Default is #FFF (white). **/ "#FFF",
      //transparent: false
    });

And my Window class is:

class WindowFrame extends React.Component<any, void> {
    static defaultProps = {
        color: '#cc7f29',
        theme: 'light'
    };

    render() {
        return (
            <Window
                color={this.props.color}
                theme={this.props.theme}
                chrome
                height="300px"
                padding="12px"
                >
                <TitleBar title="This is EDH Title #1" controls/>
                <Menu></Menu>
                <Text color={this.props.theme === 'dark' ? 'white' : '#333'}>HELLO WORLD</Text>
            </Window>
        );
    }
}

When using this code and rendering to the body tag, I yield:

image

My entire codebase is here

gabrielbull commented 8 years ago

You have two approches that works depending on what you want to do.

The first approach is to let Electron handle the chrome and titlebar of the window and just use react-desktop for the content inside that window. In this approach, you wouldn't need the Window component, like this:

            <View
                color={this.props.color}
                theme={this.props.theme}
                height="300px"
                padding="12px"
              >
                <TitleBar title="This is EDH Title #1" controls/>
                <Menu></Menu>
                <Text color={this.props.theme === 'dark' ? 'white' : '#333'}>HELLO WORLD</Text>
            </View>

The second approach is to use react-desktop for the window's chrome and titlebar. In this case, you need to make the electron window frameless, here's a good explanation: http://stackoverflow.com/questions/35876939/frameless-window-with-controls-in-electron-windows

erichiller commented 8 years ago

@gabrielbull Thanks! I did end up getting it running - the issue I'm having now is that this within the component is undefined or null.

window.tsx:43 Uncaught TypeError: Cannot read property 'setState' of null

typescript source

import * as React from 'react';
import { Window, TitleBar, Text } from 'react-desktop/windows';
import { Menu } from './menu';
import { CONFIG } from '../config';

import { elog } from '../lib/elog';

import electron = require("electron");
let remote = electron.remote;
//let BrowserWindow = remote.require('BrowserWindow'); 

export const UIwindow = document.getElementsByTagName("app")[0];

export { WindowFrame as UIlauncher };

class WindowFrame extends React.Component<any, any> {
    static defaultProps = {
        color: '#cc7f29',
        theme: 'light'
    };

    state = {
        isMaximized: false
    }

    constructor() {
        super();
    }

    close(){
        elog('close window');
        let window = remote.BrowserWindow.getFocusedWindow();
        window.close();

    }

    minimize(){
        elog('minimize window');
        let window = remote.BrowserWindow.getFocusedWindow();
        window.minimize();
    }

    maximize(){
        elog('minimize window');
        let window = remote.BrowserWindow.getFocusedWindow();
        window.maximize();
    }

    toggleMaximize(){
        elog('maximize window');
        this.setState({ isMaximized: !this.state.isMaximized });
        elog(`${this.state.isMaximized}`)
    }

/**
 * Setting 
 *  height
 *  width
 *  works in pixels not percentages
 * Not setting them causes them to expand to fit the entire body.
 * 
 * Chrome being set (boolean) means there is a goldish border on focus
 */
    render() {
        return (
            <Window
                color={this.props.color}
                theme={this.props.theme}
                chrome
                padding="12px"
                >
                <TitleBar
                    title={CONFIG.Title}
                    controls
                    isMaximized={this.state.isMaximized}
                    theme={this.props.theme}
                    background={this.props.color}
                    onCloseClick={this.close}
                    onMinimizeClick={this.minimize}
                    onMaximizeClick={this.toggleMaximize}
                    onRestoreDownClick={this.toggleMaximize}
                    />              
                <Menu></Menu>
                <Text color={this.props.theme === 'dark' ? 'white' : '#333'}>HELLO WORLD</Text>
            </Window>
        );
    }
}

compiled javascript:

"use strict";
const React = require('react');
const windows_1 = require('react-desktop/windows');
const menu_1 = require('./menu');
const config_1 = require('../config');
const elog_1 = require('../lib/elog');
const electron = require("electron");
let remote = electron.remote;
//let BrowserWindow = remote.require('BrowserWindow'); 
exports.UIwindow = document.getElementsByTagName("app")[0];
class WindowFrame extends React.Component {
    constructor() {
        super();
        this.state = {
            isMaximized: false
        };
    }
    close() {
        elog_1.elog('close window');
        let window = remote.BrowserWindow.getFocusedWindow();
        window.close();
    }
    minimize() {
        elog_1.elog('minimize window');
        let window = remote.BrowserWindow.getFocusedWindow();
        window.minimize();
    }
    maximize() {
        elog_1.elog('minimize window');
        let window = remote.BrowserWindow.getFocusedWindow();
        window.maximize();
    }
    toggleMaximize() {
        elog_1.elog('maximize window');
        this.setState({ isMaximized: !this.state.isMaximized });
        elog_1.elog(`${this.state.isMaximized}`);
    }
    /**
     * Setting
     *  height
     *  width
     *  works in pixels not percentages
     * Not setting them causes them to expand to fit the entire body.
     *
     * Chrome being set (boolean) means there is a goldish border on focus
     */
    render() {
        return (React.createElement(windows_1.Window, {color: this.props.color, theme: this.props.theme, chrome: true, padding: "12px"}, React.createElement(windows_1.TitleBar, {title: config_1.CONFIG.Title, controls: true, isMaximized: this.state.isMaximized, theme: this.props.theme, background: this.props.color, onCloseClick: this.close, onMinimizeClick: this.minimize, onMaximizeClick: this.toggleMaximize, onRestoreDownClick: this.toggleMaximize}), React.createElement(menu_1.Menu, null), React.createElement(windows_1.Text, {color: this.props.theme === 'dark' ? 'white' : '#333'}, "HELLO WORLD")));
    }
}
WindowFrame.defaultProps = {
    color: '#cc7f29',
    theme: 'light'
};
exports.UIlauncher = WindowFrame;
//# sourceMappingURL=window.js.map

Does your javascript look the same as well?

gabrielbull commented 8 years ago

Yeah, this would be expected. You can declare your functions using the arrow function declaration or provide the this context to the callbacks.

Using arrow functions syntax on the functions:

    close = () => {
        elog('close window');
        let window = remote.BrowserWindow.getFocusedWindow();
        window.close();

    }

Using arrow functions on the callbacks:

                    onCloseClick={() => this.close()}
holgersindbaek commented 5 years ago

@erichiller @gabrielbull Where exactly are you calling "WindowFrame" from?