Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color feature #45

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.idea/
.cache
dist
node_modules
.DS_Store
yarn.lock
97 changes: 97 additions & 0 deletions src/core/color.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
export class Color {
hex: string;

constructor(
hex: string
) {
if (hex.length === 3) {
hex = hex + hex;
}

this.hex = hex;
}

lightenColor(color: string, percentage: number): string {
let r = Math.round(Math.min(255, parseInt(color.substring(1, 3), 16) * (1 + percentage))).toString(16);
let g = Math.round(Math.min(255, parseInt(color.substring(3, 5), 16) * (1 + percentage))).toString(16);
let b = Math.round(Math.min(255, parseInt(color.substring(5, 7), 16) * (1 + percentage))).toString(16);
return "#" + (r.length<2 ? "0" + r : r) + (g.length<2 ? "0" + g : g) + (b.length<2 ? "0" + b : b);
}

hexAlpha(alpha: number): string {
alpha = parseInt((alpha * 255).toFixed(0));

if (alpha <= 0) {
alpha = 0;
} else if (alpha >= 255) {
alpha = 255;
}

return this.hex + alpha.toString(16);
}

hexLighter(): string {
return this.hexAlpha(.7);
}

static default(): Color {
return new Color('#dedede');
}

static white(): Color {
return new Color('#ffffff');
}

static pink(): Color {
return new Color('#ffbefa');
}

static purple(): Color {
return new Color('#e2beff');
}

static brown(): Color {
return new Color('#c9a15f');
}

static red(): Color {
return new Color('#ffbebe');
}

static green(): Color {
return new Color('#c8ffc8');
}

static blue(): Color {
return new Color('#b6b6ff');
}

static cyan(): Color {
return new Color('#beffff');
}

static yellow(): Color {
return new Color('#ffffa1');
}

static magenta(): Color {
return new Color('#ffa6ff');
}

static orange(): Color {
return new Color('#ffcb99');
}

static black(): Color {
return new Color('#868686');
}

equals(color: Color): boolean {
return this.hex === color.hex;
}

isDefault(): boolean {
return this.equals(Color.default());
}

}
12 changes: 12 additions & 0 deletions src/core/range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export class ByteRange {
this.byteLength = byteLength;
}

offset(): number {
return this.byteStart;
}

size(): number {
return this.byteLength;
}
Expand Down Expand Up @@ -153,6 +157,14 @@ export class BitRange {
this.bitLength = bitLength;
}

offset(): number {
return this.bitStart;
}

size(): number {
return this.bitLength;
}

enclosingByteRange(): ByteRange {
let byteStart = Math.floor(this.bitStart / 8);
let byteEnd = Math.floor((this.bitStart + this.bitLength - 1) / 8) + 1;
Expand Down
12 changes: 11 additions & 1 deletion src/core/tree.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { ByteRange, BitRange } from "./range";
import { Color } from "./color";

export class Tree {
label: string;
range: ByteRange | BitRange;
children: Array<Tree>;
error?: Error;
color: Color;

parent?: Tree;

constructor(
label: string,
range: ByteRange | BitRange,
children: Array<Tree> = [],
error?: Error
error?: Error,
color?: Color
) {
this.label = label;
this.range = range;
this.children = children;
this.error = error;
this.color = color || Color.default();

// Set parent pointers for the children tree objects.
for (let child of this.children) {
Expand All @@ -38,4 +42,10 @@ export class Tree {
isParentOf(other: Tree): boolean {
return other.isChildOf(this);
}

withColor(color: Color): Tree {
this.color = color;

return this;
}
}
4 changes: 3 additions & 1 deletion src/inspectors/custom.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ByteRange, BitRange } from "../core/range";
import { Tree } from "../core/tree";
import { Color } from "../core/color";
import { assert } from "chai";

import * as React from "react";
Expand Down Expand Up @@ -93,12 +94,13 @@ Object.assign(window, {
Tree: Tree,
ByteRange: ByteRange,
BitRange: BitRange,
Color: Color,
opus: require("../decoders/opus"),
rtp: require("../decoders/rtp")
});

const DEFAULT_CODE = `((range) => {
return new Tree("Example Tree", range, []);
return new Tree("Example Tree", range, []).withColor(Color.red());
})`;

class CustomInspector extends React.Component<{}, CustomInspectorState> {
Expand Down
13 changes: 7 additions & 6 deletions src/inspectors/png.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { assert } from "chai";
import { ByteRange, BitRange } from "../core/range";
import { SimpleInspector } from "../ui/simpleinspector";
import { Tree } from "../core/tree";
import { Color } from "../core/color";

import { hexEllipsis } from "../core/utils";

Expand Down Expand Up @@ -91,20 +92,20 @@ function inspect(range: ByteRange): Tree {
`Chunk (${type.readUTF8()})`,
ptr.bytes(0, chunkSize),
[
new Tree(`Length: ${byteLen}`, length),
new Tree(`Type: ${type.readUTF8()}`, type)
new Tree(`Length: ${byteLen}`, length).withColor(Color.blue()),
new Tree(`Type: ${type.readUTF8()}`, type).withColor(Color.orange())
]
.concat(chunkElements)
.concat([new Tree(`CRC: ${crc.readUIntBE()}`, crc)])
)
.concat([new Tree(`CRC: ${crc.readUIntBE()}`, crc).withColor(Color.brown())])
).withColor(Color.green())
);

ptr = ptr.bytes(chunkSize);
}

return new Tree("PNG Image", range, [
new Tree(`Signature: ${signature.toHex()}`, signature),
new Tree(`Chunks (${chunks.length})`, range.bytes(8), chunks)
new Tree(`Signature: ${signature.toHex()}`, signature).withColor(Color.red()),
new Tree(`Chunks (${chunks.length})`, range.bytes(8), chunks).withColor(Color.magenta())
]);
}

Expand Down
55 changes: 42 additions & 13 deletions src/ui/binaryview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as React from "react";
import { Col, Form, Row } from "react-bootstrap";

import { ByteRange, BitRange } from "../core/range";
import { Color } from "../core/color";
import { Tree } from "../core/tree";

const HEX_BYTES_PER_ROW = 16;
const HEX_BYTES_PER_GROUP = 8;
Expand All @@ -11,12 +13,10 @@ const BINARY_BYTES_PER_GROUP = 4;

const DEFAULT_MAX_ROWS = 1000;

const SELECTED_COLOR = "#dedede";

type Format = "hex" | "binary";

export class BinaryView extends React.Component<
{ data: ByteRange; selected?: ByteRange | BitRange; maxRows: number },
{ data: ByteRange; selected?: ByteRange | BitRange; maxRows: number; tree: Tree },
{ format: Format }
> {
static defaultProps = {
Expand Down Expand Up @@ -83,6 +83,28 @@ export class BinaryView extends React.Component<
}
}

byteColor(tree: Tree, byteNumber: number, color?: Color) {
if (tree === undefined) {
return Color.default();
}

for (const t of tree.children) {
if (t.range.offset() <= byteNumber && byteNumber < (t.range.offset() + t.range.size())) {
if (!t.color.isDefault()) {
color = t.color;
}

const deepColor = this.byteColor(t, byteNumber, color);

if (deepColor !== undefined) {
color = deepColor;
}
}
}

return color;
}

renderHex() {
let data = this.props.data;

Expand Down Expand Up @@ -153,11 +175,12 @@ export class BinaryView extends React.Component<
</div>
))}
</span>

<span>
{data.chunks(HEX_BYTES_PER_ROW).map((row, i) => (
<div key={i}>
{row.chunks(HEX_BYTES_PER_GROUP).map((group, i) => (
<span style={{ paddingRight: "10px" }} key={i}>
{data.chunks(HEX_BYTES_PER_ROW).map((row, k) => (
<div key={k}>
{row.chunks(HEX_BYTES_PER_GROUP).map((group, j) => (
<span style={{ paddingRight: "10px" }} key={j}>
{group.chunks(1).map((byte, i) => {
let selected = false;
if (this.props.selected) {
Expand All @@ -170,11 +193,15 @@ export class BinaryView extends React.Component<
}
}

const byteNumber = i + (j * HEX_BYTES_PER_GROUP) + (k * HEX_BYTES_PER_ROW);
const color = this.byteColor(this.props.tree, byteNumber, undefined) || this.props.tree.color;

return (
<span
style={{
paddingRight: "5px",
backgroundColor: selected ? SELECTED_COLOR : ""
fontWeight: selected ? 'bold': 'normal',
backgroundColor: selected ? color.hex : (color.isDefault() ? "" : color.hexLighter())
}}
key={i}
>
Expand Down Expand Up @@ -206,8 +233,7 @@ export class BinaryView extends React.Component<
<div key={i}>
{row.chunks(BINARY_BYTES_PER_GROUP).map((group, i) => (
<span style={{ paddingRight: "10px" }} key={i}>
{group.chunks(1).map((byte, i) => {
return (
{group.chunks(1).map((byte, i) => (
<span
style={{
paddingRight: "5px"
Expand All @@ -230,10 +256,14 @@ export class BinaryView extends React.Component<
selected = this.props.selected.contains(b);
}
}

const color = this.byteColor(this.props.tree, Math.floor(b.offset() / HEX_BYTES_PER_GROUP), undefined) || this.props.tree.color;

return (
<span
style={{
backgroundColor: selected ? SELECTED_COLOR : ""
fontWeight: selected ? 'bold': 'normal',
backgroundColor: selected ? color.hex : (color.isDefault() ? "" : color.hexLighter())
}}
key={i}
>
Expand All @@ -242,8 +272,7 @@ export class BinaryView extends React.Component<
);
})}
</span>
);
})}
))}
</span>
))}
</div>
Expand Down
4 changes: 3 additions & 1 deletion src/ui/treebinaryview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export class TreeBinaryView extends React.Component<
super(props);
this.state = {};
}

render() {

return (
<>
<Row style={{ maxHeight: "600px", marginTop: "10px" }}>
Expand All @@ -34,7 +34,9 @@ export class TreeBinaryView extends React.Component<
</div>
</Col>
<Col md={6}>

<BinaryView
tree={this.props.tree}
data={this.props.data}
selected={
this.state.selected ? this.state.selected.range : undefined
Expand Down
Loading
Loading