build(deps): vendor JUCE 7.0.12

This commit is contained in:
2026-09-08 14:55:21 +02:00
parent 5b99f51bd1
commit d6705ab29f
3591 changed files with 1218267 additions and 0 deletions
@@ -0,0 +1,301 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "jucer_CodeHelpers.h"
//==============================================================================
namespace CodeHelpers
{
String indent (const String& code, const int numSpaces, bool indentFirstLine)
{
if (numSpaces == 0)
return code;
auto space = String::repeatedString (" ", numSpaces);
auto lines = StringArray::fromLines (code);
for (auto& line : lines)
{
if (! indentFirstLine)
{
indentFirstLine = true;
continue;
}
if (line.trimEnd().isNotEmpty())
line = space + line;
}
return lines.joinIntoString (newLine);
}
String unindent (const String& code, const int numSpaces)
{
if (numSpaces == 0)
return code;
auto space = String::repeatedString (" ", numSpaces);
auto lines = StringArray::fromLines (code);
for (auto& line : lines)
if (line.startsWith (space))
line = line.substring (numSpaces);
return lines.joinIntoString (newLine);
}
String createIncludeStatement (const File& includeFile, const File& targetFile)
{
return createIncludeStatement (build_tools::unixStylePath (build_tools::getRelativePathFrom (includeFile, targetFile.getParentDirectory())));
}
String createIncludeStatement (const String& includePath)
{
if (includePath.startsWithChar ('<') || includePath.startsWithChar ('"'))
return "#include " + includePath;
return "#include \"" + includePath + "\"";
}
String createIncludePathIncludeStatement (const String& includedFilename)
{
return "#include <" + includedFilename + ">";
}
String stringLiteral (const String& text, int maxLineLength)
{
if (text.isEmpty())
return "juce::String()";
StringArray lines;
{
auto t = text.getCharPointer();
bool finished = t.isEmpty();
while (! finished)
{
for (auto startOfLine = t;;)
{
switch (t.getAndAdvance())
{
case 0: finished = true; break;
case '\n': break;
case '\r': if (*t == '\n') ++t; break;
default: continue;
}
lines.add (String (startOfLine, t));
break;
}
}
}
if (maxLineLength > 0)
{
for (int i = 0; i < lines.size(); ++i)
{
auto& line = lines.getReference (i);
if (line.length() > maxLineLength)
{
const String start (line.substring (0, maxLineLength));
const String end (line.substring (maxLineLength));
line = start;
lines.insert (i + 1, end);
}
}
}
for (int i = 0; i < lines.size(); ++i)
lines.getReference (i) = CppTokeniserFunctions::addEscapeChars (lines.getReference (i));
lines.removeEmptyStrings();
for (int i = 0; i < lines.size(); ++i)
lines.getReference (i) = "\"" + lines.getReference (i) + "\"";
String result (lines.joinIntoString (newLine));
if (! CharPointer_ASCII::isValidString (text.toUTF8(), std::numeric_limits<int>::max()))
result = "juce::CharPointer_UTF8 (" + result + ")";
return result;
}
String alignFunctionCallParams (const String& call, const StringArray& parameters, const int maxLineLength)
{
String result, currentLine (call);
for (int i = 0; i < parameters.size(); ++i)
{
if (currentLine.length() >= maxLineLength)
{
result += currentLine.trimEnd() + newLine;
currentLine = String::repeatedString (" ", call.length()) + parameters[i];
}
else
{
currentLine += parameters[i];
}
if (i < parameters.size() - 1)
currentLine << ", ";
}
return result + currentLine.trimEnd() + ")";
}
String floatLiteral (double value, int numDecPlaces)
{
String s (value, numDecPlaces);
if (s.containsChar ('.'))
s << 'f';
else
s << ".0f";
return s;
}
String boolLiteral (bool value)
{
return value ? "true" : "false";
}
String colourToCode (Colour col)
{
const Colour colours[] =
{
#define COL(col) Colours::col,
#include "jucer_Colours.h"
#undef COL
Colours::transparentBlack
};
static const char* colourNames[] =
{
#define COL(col) #col,
#include "jucer_Colours.h"
#undef COL
nullptr
};
for (int i = 0; i < numElementsInArray (colourNames) - 1; ++i)
if (col == colours[i])
return "juce::Colours::" + String (colourNames[i]);
return "juce::Colour (0x" + build_tools::hexString8Digits ((int) col.getARGB()) + ')';
}
String justificationToCode (Justification justification)
{
switch (justification.getFlags())
{
case Justification::centred: return "juce::Justification::centred";
case Justification::centredLeft: return "juce::Justification::centredLeft";
case Justification::centredRight: return "juce::Justification::centredRight";
case Justification::centredTop: return "juce::Justification::centredTop";
case Justification::centredBottom: return "juce::Justification::centredBottom";
case Justification::topLeft: return "juce::Justification::topLeft";
case Justification::topRight: return "juce::Justification::topRight";
case Justification::bottomLeft: return "juce::Justification::bottomLeft";
case Justification::bottomRight: return "juce::Justification::bottomRight";
case Justification::left: return "juce::Justification::left";
case Justification::right: return "juce::Justification::right";
case Justification::horizontallyCentred: return "juce::Justification::horizontallyCentred";
case Justification::top: return "juce::Justification::top";
case Justification::bottom: return "juce::Justification::bottom";
case Justification::verticallyCentred: return "juce::Justification::verticallyCentred";
case Justification::horizontallyJustified: return "juce::Justification::horizontallyJustified";
default: break;
}
jassertfalse;
return "Justification (" + String (justification.getFlags()) + ")";
}
//==============================================================================
String getLeadingWhitespace (String line)
{
line = line.removeCharacters (line.endsWith ("\r\n") ? "\r\n" : "\n");
auto endOfLeadingWS = line.getCharPointer().findEndOfWhitespace();
return String (line.getCharPointer(), endOfLeadingWS);
}
int getBraceCount (String::CharPointerType line)
{
int braces = 0;
for (;;)
{
const juce_wchar c = line.getAndAdvance();
if (c == 0) break;
else if (c == '{') ++braces;
else if (c == '}') --braces;
else if (c == '/') { if (*line == '/') break; }
else if (c == '"' || c == '\'') { while (! (line.isEmpty() || line.getAndAdvance() == c)) {} }
}
return braces;
}
bool getIndentForCurrentBlock (CodeDocument::Position pos, const String& tab,
String& blockIndent, String& lastLineIndent)
{
int braceCount = 0;
bool indentFound = false;
while (pos.getLineNumber() > 0)
{
pos = pos.movedByLines (-1);
auto line = pos.getLineText();
auto trimmedLine = line.trimStart();
braceCount += getBraceCount (trimmedLine.getCharPointer());
if (braceCount > 0)
{
blockIndent = getLeadingWhitespace (line);
if (! indentFound)
lastLineIndent = blockIndent + tab;
return true;
}
if ((! indentFound) && trimmedLine.isNotEmpty())
{
indentFound = true;
lastLineIndent = getLeadingWhitespace (line);
}
}
return false;
}
}
@@ -0,0 +1,52 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
namespace CodeHelpers
{
String indent (const String& code, int numSpaces, bool indentFirstLine);
String unindent (const String& code, int numSpaces);
String createIncludeStatement (const File& includedFile, const File& targetFile);
String createIncludeStatement (const String& includePath);
String createIncludePathIncludeStatement (const String& includedFilename);
String stringLiteral (const String& text, int maxLineLength = -1);
String floatLiteral (double value, int numDecPlaces);
String boolLiteral (bool value);
String colourToCode (Colour);
String justificationToCode (Justification);
String alignFunctionCallParams (const String& call, const StringArray& parameters, int maxLineLength);
String getLeadingWhitespace (String line);
int getBraceCount (String::CharPointerType line);
bool getIndentForCurrentBlock (CodeDocument::Position pos, const String& tab,
String& blockIndent, String& lastLineIndent);
}
@@ -0,0 +1,162 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
COL (black)
COL (white)
COL (blue)
COL (grey)
COL (green)
COL (red)
COL (yellow)
COL (aliceblue)
COL (antiquewhite)
COL (aqua)
COL (aquamarine)
COL (azure)
COL (beige)
COL (bisque)
COL (blanchedalmond)
COL (blueviolet)
COL (brown)
COL (burlywood)
COL (cadetblue)
COL (chartreuse)
COL (chocolate)
COL (coral)
COL (cornflowerblue)
COL (cornsilk)
COL (crimson)
COL (cyan)
COL (darkblue)
COL (darkcyan)
COL (darkgoldenrod)
COL (darkgrey)
COL (darkgreen)
COL (darkkhaki)
COL (darkmagenta)
COL (darkolivegreen)
COL (darkorange)
COL (darkorchid)
COL (darkred)
COL (darksalmon)
COL (darkseagreen)
COL (darkslateblue)
COL (darkslategrey)
COL (darkturquoise)
COL (darkviolet)
COL (deeppink)
COL (deepskyblue)
COL (dimgrey)
COL (dodgerblue)
COL (firebrick)
COL (floralwhite)
COL (forestgreen)
COL (fuchsia)
COL (gainsboro)
COL (gold)
COL (goldenrod)
COL (greenyellow)
COL (honeydew)
COL (hotpink)
COL (indianred)
COL (indigo)
COL (ivory)
COL (khaki)
COL (lavender)
COL (lavenderblush)
COL (lemonchiffon)
COL (lightblue)
COL (lightcoral)
COL (lightcyan)
COL (lightgoldenrodyellow)
COL (lightgreen)
COL (lightgrey)
COL (lightpink)
COL (lightsalmon)
COL (lightseagreen)
COL (lightskyblue)
COL (lightslategrey)
COL (lightsteelblue)
COL (lightyellow)
COL (lime)
COL (limegreen)
COL (linen)
COL (magenta)
COL (maroon)
COL (mediumaquamarine)
COL (mediumblue)
COL (mediumorchid)
COL (mediumpurple)
COL (mediumseagreen)
COL (mediumslateblue)
COL (mediumspringgreen)
COL (mediumturquoise)
COL (mediumvioletred)
COL (midnightblue)
COL (mintcream)
COL (mistyrose)
COL (navajowhite)
COL (navy)
COL (oldlace)
COL (olive)
COL (olivedrab)
COL (orange)
COL (orangered)
COL (orchid)
COL (palegoldenrod)
COL (palegreen)
COL (paleturquoise)
COL (palevioletred)
COL (papayawhip)
COL (peachpuff)
COL (peru)
COL (pink)
COL (plum)
COL (powderblue)
COL (purple)
COL (rosybrown)
COL (royalblue)
COL (saddlebrown)
COL (salmon)
COL (sandybrown)
COL (seagreen)
COL (seashell)
COL (sienna)
COL (silver)
COL (skyblue)
COL (slateblue)
COL (slategrey)
COL (snow)
COL (springgreen)
COL (steelblue)
COL (tan)
COL (teal)
COL (thistle)
COL (tomato)
COL (turquoise)
COL (violet)
COL (wheat)
COL (whitesmoke)
COL (yellowgreen)
@@ -0,0 +1,107 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "jucer_CodeHelpers.h"
//==============================================================================
namespace FileHelpers
{
bool containsAnyNonHiddenFiles (const File& folder)
{
for (const auto& di : RangedDirectoryIterator (folder, false))
if (! di.getFile().isHidden())
return true;
return false;
}
bool shouldPathsBeRelative (String path1, String path2)
{
path1 = build_tools::unixStylePath (path1);
path2 = build_tools::unixStylePath (path2);
const int len = jmin (path1.length(), path2.length());
int commonBitLength = 0;
for (int i = 0; i < len; ++i)
{
if (CharacterFunctions::toLowerCase (path1[i]) != CharacterFunctions::toLowerCase (path2[i]))
break;
++commonBitLength;
}
return path1.substring (0, commonBitLength).removeCharacters ("/:").isNotEmpty();
}
// removes "/../" bits from the middle of the path
String simplifyPath (String::CharPointerType p)
{
#if JUCE_WINDOWS
if (CharacterFunctions::indexOf (p, CharPointer_ASCII ("/../")) >= 0
|| CharacterFunctions::indexOf (p, CharPointer_ASCII ("\\..\\")) >= 0)
#else
if (CharacterFunctions::indexOf (p, CharPointer_ASCII ("/../")) >= 0)
#endif
{
StringArray toks;
#if JUCE_WINDOWS
toks.addTokens (p, "\\/", StringRef());
#else
toks.addTokens (p, "/", StringRef());
#endif
while (toks[0] == ".")
toks.remove (0);
for (int i = 1; i < toks.size(); ++i)
{
if (toks[i] == ".." && toks [i - 1] != "..")
{
toks.removeRange (i - 1, 2);
i = jmax (0, i - 2);
}
}
return toks.joinIntoString ("/");
}
return p;
}
String simplifyPath (const String& path)
{
#if JUCE_WINDOWS
if (path.contains ("\\..\\") || path.contains ("/../"))
#else
if (path.contains ("/../"))
#endif
return simplifyPath (path.getCharPointer());
return path;
}
}
@@ -0,0 +1,79 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
namespace FileHelpers
{
bool containsAnyNonHiddenFiles (const File& folder);
bool shouldPathsBeRelative (String path1, String path2);
// removes "/../" bits from the middle of the path
String simplifyPath (String::CharPointerType path);
String simplifyPath (const String& path);
}
//==============================================================================
const char* const sourceFileExtensions = "cpp;mm;m;metal;c;cc;cxx;swift;s;asm;r";
const char* const headerFileExtensions = "h;hpp;hxx;hh;inl";
const char* const cOrCppFileExtensions = "cpp;cc;cxx;c";
const char* const cppFileExtensions = "cpp;cc;cxx";
const char* const objCFileExtensions = "mm;m";
const char* const asmFileExtensions = "s;S;asm";
const char* const sourceOrHeaderFileExtensions = "cpp;mm;m;metal;c;cc;cxx;swift;s;S;asm;h;hpp;hxx;hh;inl";
const char* const browseableFileExtensions = "cpp;mm;m;metal;c;cc;cxx;swift;s;S;asm;h;hpp;hxx;hh;inl;txt;md;rtf";
const char* const fileTypesToCompileByDefault = "cpp;mm;m;metal;c;cc;cxx;swift;s;S;asm;r";
//==============================================================================
struct FileModificationDetector
{
FileModificationDetector (const File& f) : file (f) {}
const File& getFile() const { return file; }
void fileHasBeenRenamed (const File& newFile) { file = newFile; }
bool hasBeenModified() const
{
return fileModificationTime != file.getLastModificationTime()
&& (fileSize != file.getSize()
|| build_tools::calculateFileHashCode (file) != fileHashCode);
}
void updateHash()
{
fileModificationTime = file.getLastModificationTime();
fileSize = file.getSize();
fileHashCode = build_tools::calculateFileHashCode (file);
}
private:
File file;
Time fileModificationTime;
uint64 fileHashCode = 0;
int64 fileSize = -1;
};
@@ -0,0 +1,502 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
//==============================================================================
String joinLinesIntoSourceFile (StringArray& lines)
{
while (lines.size() > 10 && lines [lines.size() - 1].isEmpty())
lines.remove (lines.size() - 1);
return lines.joinIntoString (getPreferredLineFeed()) + getPreferredLineFeed();
}
String replaceLineFeeds (const String& content, const String& lineFeed)
{
StringArray lines;
lines.addLines (content);
return lines.joinIntoString (lineFeed);
}
String getLineFeedForFile (const String& fileContent)
{
auto t = fileContent.getCharPointer();
while (! t.isEmpty())
{
switch (t.getAndAdvance())
{
case 0: break;
case '\n': return "\n";
case '\r': if (*t == '\n') return "\r\n";
default: continue;
}
}
return {};
}
String trimCommentCharsFromStartOfLine (const String& line)
{
return line.trimStart().trimCharactersAtStart ("*/").trimStart();
}
String createAlphaNumericUID()
{
String uid;
const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random r;
uid << chars[r.nextInt (52)]; // make sure the first character is always a letter
for (int i = 5; --i >= 0;)
{
r.setSeedRandomly();
uid << chars [r.nextInt (62)];
}
return uid;
}
String createGUID (const String& seed)
{
auto hex = MD5 ((seed + "_guidsalt").toUTF8()).toHexString().toUpperCase();
return "{" + hex.substring (0, 8)
+ "-" + hex.substring (8, 12)
+ "-" + hex.substring (12, 16)
+ "-" + hex.substring (16, 20)
+ "-" + hex.substring (20, 32)
+ "}";
}
String escapeSpaces (const String& s)
{
return s.replace (" ", "\\ ");
}
String escapeQuotesAndSpaces (const String& s)
{
return escapeSpaces (s).replace ("'", "\\'").replace ("\"", "\\\"");
}
String addQuotesIfContainsSpaces (const String& text)
{
return (text.containsChar (' ') && ! text.isQuotedString()) ? text.quoted() : text;
}
void setValueIfVoid (Value value, const var& defaultValue)
{
if (value.getValue().isVoid())
value = defaultValue;
}
//==============================================================================
StringPairArray parsePreprocessorDefs (const String& text)
{
StringPairArray result;
auto s = text.getCharPointer();
while (! s.isEmpty())
{
String token, value;
s.incrementToEndOfWhitespace();
while ((! s.isEmpty()) && *s != '=' && ! s.isWhitespace())
token << s.getAndAdvance();
s.incrementToEndOfWhitespace();
if (*s == '=')
{
++s;
while ((! s.isEmpty()) && *s == ' ')
++s;
while ((! s.isEmpty()) && ! s.isWhitespace())
{
if (*s == ',')
{
++s;
break;
}
if (*s == '\\' && (s[1] == ' ' || s[1] == ','))
++s;
value << s.getAndAdvance();
}
}
if (token.isNotEmpty())
result.set (token, value);
}
return result;
}
StringPairArray mergePreprocessorDefs (StringPairArray inheritedDefs, const StringPairArray& overridingDefs)
{
for (int i = 0; i < overridingDefs.size(); ++i)
inheritedDefs.set (overridingDefs.getAllKeys()[i], overridingDefs.getAllValues()[i]);
return inheritedDefs;
}
String createGCCPreprocessorFlags (const StringPairArray& defs)
{
String s;
for (int i = 0; i < defs.size(); ++i)
{
auto def = defs.getAllKeys()[i];
auto value = defs.getAllValues()[i];
if (value.isNotEmpty())
def << "=" << value;
s += " \"" + ("-D" + def).replace ("\"", "\\\"") + "\"";
}
return s;
}
StringArray getSearchPathsFromString (const String& searchPath)
{
StringArray s;
s.addTokens (searchPath, ";\r\n", StringRef());
return getCleanedStringArray (s);
}
StringArray getCommaOrWhitespaceSeparatedItems (const String& sourceString)
{
StringArray s;
s.addTokens (sourceString, ", \t\r\n", StringRef());
return getCleanedStringArray (s);
}
StringArray getCleanedStringArray (StringArray s)
{
s.trim();
s.removeEmptyStrings();
return s;
}
//==============================================================================
void autoScrollForMouseEvent (const MouseEvent& e, bool scrollX, bool scrollY)
{
if (Viewport* const viewport = e.eventComponent->findParentComponentOfClass<Viewport>())
{
const MouseEvent e2 (e.getEventRelativeTo (viewport));
viewport->autoScroll (scrollX ? e2.x : 20, scrollY ? e2.y : 20, 8, 16);
}
}
//==============================================================================
int indexOfLineStartingWith (const StringArray& lines, const String& text, int index)
{
const int len = text.length();
for (const String* i = lines.begin() + index, * const e = lines.end(); i < e; ++i)
{
if (CharacterFunctions::compareUpTo (i->getCharPointer().findEndOfWhitespace(),
text.getCharPointer(), len) == 0)
return index;
++index;
}
return -1;
}
//==============================================================================
bool fileNeedsCppSyntaxHighlighting (const File& file)
{
if (file.hasFileExtension (sourceOrHeaderFileExtensions))
return true;
// This is a bit of a bodge to deal with libc++ headers with no extension..
char fileStart[128] = { 0 };
FileInputStream fin (file);
fin.read (fileStart, sizeof (fileStart) - 4);
return CharPointer_UTF8::isValidString (fileStart, sizeof (fileStart))
&& String (fileStart).trimStart().startsWith ("// -*- C++ -*-");
}
//==============================================================================
void writeAutoGenWarningComment (OutputStream& outStream)
{
outStream << "/*" << newLine << newLine
<< " IMPORTANT! This file is auto-generated each time you save your" << newLine
<< " project - if you alter its contents, your changes may be overwritten!" << newLine
<< newLine;
}
//==============================================================================
StringArray getJUCEModules() noexcept
{
static StringArray juceModuleIds =
{
"juce_analytics",
"juce_audio_basics",
"juce_audio_devices",
"juce_audio_formats",
"juce_audio_plugin_client",
"juce_audio_processors",
"juce_audio_utils",
"juce_box2d",
"juce_core",
"juce_cryptography",
"juce_data_structures",
"juce_dsp",
"juce_events",
"juce_graphics",
"juce_gui_basics",
"juce_gui_extra",
"juce_opengl",
"juce_osc",
"juce_product_unlocking",
"juce_video",
"juce_midi_ci"
};
return juceModuleIds;
}
bool isJUCEModule (const String& moduleID) noexcept
{
return getJUCEModules().contains (moduleID);
}
StringArray getModulesRequiredForConsole() noexcept
{
return
{
"juce_core",
"juce_data_structures",
"juce_events"
};
}
StringArray getModulesRequiredForComponent() noexcept
{
return
{
"juce_core",
"juce_data_structures",
"juce_events",
"juce_graphics",
"juce_gui_basics"
};
}
StringArray getModulesRequiredForAudioProcessor() noexcept
{
return
{
"juce_audio_basics",
"juce_audio_devices",
"juce_audio_formats",
"juce_audio_plugin_client",
"juce_audio_processors",
"juce_audio_utils",
"juce_core",
"juce_data_structures",
"juce_events",
"juce_graphics",
"juce_gui_basics",
"juce_gui_extra"
};
}
bool isPIPFile (const File& file) noexcept
{
for (auto line : StringArray::fromLines (file.loadFileAsString()))
{
auto trimmedLine = trimCommentCharsFromStartOfLine (line);
if (trimmedLine.startsWith ("BEGIN_JUCE_PIP_METADATA"))
return true;
}
return false;
}
bool isValidJUCEExamplesDirectory (const File& directory) noexcept
{
if (! directory.exists() || ! directory.isDirectory() || ! directory.containsSubDirectories())
return false;
return directory.getChildFile ("Assets").getChildFile ("juce_icon.png").existsAsFile();
}
bool isJUCEFolder (const File& f)
{
return isJUCEModulesFolder (f.getChildFile ("modules"));
}
bool isJUCEModulesFolder (const File& f)
{
return f.isDirectory() && f.getChildFile ("juce_core").isDirectory();
}
//==============================================================================
static bool isDivider (const String& line)
{
auto afterIndent = line.trim();
if (afterIndent.startsWith ("//") && afterIndent.length() > 20)
{
afterIndent = afterIndent.substring (5);
if (afterIndent.containsOnly ("=")
|| afterIndent.containsOnly ("/")
|| afterIndent.containsOnly ("-"))
{
return true;
}
}
return false;
}
static int getIndexOfCommentBlockStart (const StringArray& lines, int endIndex)
{
auto endLine = lines[endIndex];
if (endLine.contains ("*/"))
{
for (int i = endIndex; i >= 0; --i)
if (lines[i].contains ("/*"))
return i;
}
if (endLine.trim().startsWith ("//") && ! isDivider (endLine))
{
for (int i = endIndex; i >= 0; --i)
if (! lines[i].startsWith ("//") || isDivider (lines[i]))
return i + 1;
}
return -1;
}
int findBestLineToScrollToForClass (StringArray lines, const String& className, bool isPlugin)
{
for (auto line : lines)
{
if (line.contains ("struct " + className) || line.contains ("class " + className)
|| (isPlugin && line.contains ("public AudioProcessor") && ! line.contains ("AudioProcessorEditor")))
{
auto index = lines.indexOf (line);
auto commentBlockStartIndex = getIndexOfCommentBlockStart (lines, index - 1);
if (commentBlockStartIndex != -1)
index = commentBlockStartIndex;
if (isDivider (lines[index - 1]))
index -= 1;
return index;
}
}
return 0;
}
//==============================================================================
static var parseJUCEHeaderMetadata (const StringArray& lines)
{
auto* o = new DynamicObject();
var result (o);
for (auto& line : lines)
{
auto trimmedLine = trimCommentCharsFromStartOfLine (line);
auto colon = trimmedLine.indexOfChar (':');
if (colon >= 0)
{
auto key = trimmedLine.substring (0, colon).trim();
auto value = trimmedLine.substring (colon + 1).trim();
o->setProperty (key, value);
}
}
return result;
}
static String parseMetadataItem (const StringArray& lines, int& index)
{
String result = lines[index++];
while (index < lines.size())
{
auto continuationLine = trimCommentCharsFromStartOfLine (lines[index]);
if (continuationLine.isEmpty() || continuationLine.indexOfChar (':') != -1
|| continuationLine.startsWith ("END_JUCE_"))
break;
result += " " + continuationLine;
++index;
}
return result;
}
var parseJUCEHeaderMetadata (const File& file)
{
StringArray lines;
file.readLines (lines);
for (int i = 0; i < lines.size(); ++i)
{
auto trimmedLine = trimCommentCharsFromStartOfLine (lines[i]);
if (trimmedLine.startsWith ("BEGIN_JUCE_"))
{
StringArray desc;
auto j = i + 1;
while (j < lines.size())
{
if (trimCommentCharsFromStartOfLine (lines[j]).startsWith ("END_JUCE_"))
return parseJUCEHeaderMetadata (desc);
desc.add (parseMetadataItem (lines, j));
}
}
}
return {};
}
@@ -0,0 +1,138 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
const char* getPreferredLineFeed();
String joinLinesIntoSourceFile (StringArray& lines);
String replaceLineFeeds (const String& content, const String& lineFeed);
String getLineFeedForFile (const String& fileContent);
var parseJUCEHeaderMetadata (const File&);
String trimCommentCharsFromStartOfLine (const String& line);
String createAlphaNumericUID();
String createGUID (const String& seed); // Turns a seed into a windows GUID
String escapeSpaces (const String& text); // replaces spaces with blackslash-space
String escapeQuotesAndSpaces (const String& text);
String addQuotesIfContainsSpaces (const String& text);
StringPairArray parsePreprocessorDefs (const String& defs);
StringPairArray mergePreprocessorDefs (StringPairArray inheritedDefs, const StringPairArray& overridingDefs);
String createGCCPreprocessorFlags (const StringPairArray& defs);
StringArray getCleanedStringArray (StringArray);
StringArray getSearchPathsFromString (const String& searchPath);
StringArray getCommaOrWhitespaceSeparatedItems (const String&);
void setValueIfVoid (Value value, const var& defaultValue);
bool fileNeedsCppSyntaxHighlighting (const File& file);
void writeAutoGenWarningComment (OutputStream& outStream);
StringArray getJUCEModules() noexcept;
bool isJUCEModule (const String& moduleID) noexcept;
StringArray getModulesRequiredForConsole() noexcept;
StringArray getModulesRequiredForComponent() noexcept;
StringArray getModulesRequiredForAudioProcessor() noexcept;
bool isPIPFile (const File&) noexcept;
int findBestLineToScrollToForClass (StringArray, const String&, bool isPlugin = false);
bool isValidJUCEExamplesDirectory (const File&) noexcept;
bool isJUCEModulesFolder (const File&);
bool isJUCEFolder (const File&);
//==============================================================================
int indexOfLineStartingWith (const StringArray& lines, const String& text, int startIndex);
void autoScrollForMouseEvent (const MouseEvent& e, bool scrollX = true, bool scrollY = true);
//==============================================================================
struct PropertyListBuilder
{
void add (PropertyComponent* propertyComp)
{
components.add (propertyComp);
}
void add (PropertyComponent* propertyComp, const String& tooltip)
{
propertyComp->setTooltip (tooltip);
add (propertyComp);
}
void addSearchPathProperty (const Value& value,
const String& name,
const String& mainHelpText)
{
add (new TextPropertyComponent (value, name, 16384, true),
mainHelpText + " Use semi-colons or new-lines to separate multiple paths.");
}
void addSearchPathProperty (const ValueTreePropertyWithDefault& value,
const String& name,
const String& mainHelpText)
{
add (new TextPropertyComponent (value, name, 16384, true),
mainHelpText + " Use semi-colons or new-lines to separate multiple paths.");
}
void setPreferredHeight (int height)
{
for (int j = components.size(); --j >= 0;)
components.getUnchecked (j)->setPreferredHeight (height);
}
Array<PropertyComponent*> components;
};
//==============================================================================
// A ValueSource which takes an input source, and forwards any changes in it.
// This class is a handy way to create sources which re-map a value.
class ValueSourceFilter : public Value::ValueSource,
private Value::Listener
{
public:
ValueSourceFilter (const Value& source) : sourceValue (source)
{
sourceValue.addListener (this);
}
protected:
Value sourceValue;
private:
void valueChanged (Value&) override { sendChangeMessage (true); }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueSourceFilter)
};
@@ -0,0 +1,296 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "jucer_NewFileWizard.h"
//==============================================================================
namespace
{
static String fillInBasicTemplateFields (const File& file, const Project::Item& item, const char* templateName)
{
int dataSize;
if (auto* data = BinaryData::getNamedResource (templateName, dataSize))
{
auto fileTemplate = String::fromUTF8 (data, dataSize);
return replaceLineFeeds (fileTemplate.replace ("%%filename%%", file.getFileName(), false)
.replace ("%%date%%", Time::getCurrentTime().toString (true, true, true), false)
.replace ("%%author%%", SystemStats::getFullUserName(), false)
.replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (file.withFileExtension (".h"), file)),
item.project.getProjectLineFeed());
}
jassertfalse;
return {};
}
static bool fillInNewCppFileTemplate (const File& file, const Project::Item& item, const char* templateName)
{
return build_tools::overwriteFileWithNewDataIfDifferent (file, fillInBasicTemplateFields (file, item, templateName));
}
const int menuBaseID = 0x12d83f0;
}
//==============================================================================
class NewCppFileWizard final : public NewFileWizard::Type
{
public:
String getName() override { return "CPP File"; }
void createNewFile (Project&, Project::Item parent) override
{
askUserToChooseNewFile ("SourceCode.cpp", "*.cpp", parent, [this, parent] (File newFile)
{
if (newFile != File())
create (*this, parent, newFile, "jucer_NewCppFileTemplate_cpp");
});
}
static bool create (NewFileWizard::Type& wizard, Project::Item parent, const File& newFile, const char* templateName)
{
if (fillInNewCppFileTemplate (newFile, parent, templateName))
{
parent.addFileRetainingSortOrder (newFile, true);
return true;
}
wizard.showFailedToWriteMessage (newFile);
return false;
}
};
//==============================================================================
class NewHeaderFileWizard final : public NewFileWizard::Type
{
public:
String getName() override { return "Header File"; }
void createNewFile (Project&, Project::Item parent) override
{
askUserToChooseNewFile ("SourceCode.h", "*.h", parent, [this, parent] (File newFile)
{
if (newFile != File())
create (*this, parent, newFile, "jucer_NewCppFileTemplate_h");
});
}
static bool create (NewFileWizard::Type& wizard, Project::Item parent, const File& newFile, const char* templateName)
{
if (fillInNewCppFileTemplate (newFile, parent, templateName))
{
parent.addFileRetainingSortOrder (newFile, true);
return true;
}
wizard.showFailedToWriteMessage (newFile);
return false;
}
};
//==============================================================================
class NewCppAndHeaderFileWizard : public NewFileWizard::Type
{
public:
String getName() override { return "CPP & Header File"; }
void createNewFile (Project&, Project::Item parent) override
{
askUserToChooseNewFile ("SourceCode.h", "*.h;*.cpp", parent, [this, parent] (File newFile)
{
if (NewCppFileWizard::create (*this, parent, newFile.withFileExtension ("h"), "jucer_NewCppFileTemplate_h"))
NewCppFileWizard::create (*this, parent, newFile.withFileExtension ("cpp"), "jucer_NewCppFileTemplate_cpp");
});
}
};
//==============================================================================
class NewComponentFileWizard : public NewFileWizard::Type
{
public:
String getName() override { return "Component class (split between a CPP & header)"; }
void createNewFile (Project&, Project::Item parent) override
{
createNewFileInternal (parent);
}
static bool create (NewFileWizard::Type& wizard, const String& className, Project::Item parent,
const File& newFile, const char* templateName)
{
auto content = fillInBasicTemplateFields (newFile, parent, templateName)
.replace ("%%component_class%%", className)
.replace ("%%include_juce%%", CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename()));
content = replaceLineFeeds (content, parent.project.getProjectLineFeed());
if (build_tools::overwriteFileWithNewDataIfDifferent (newFile, content))
{
parent.addFileRetainingSortOrder (newFile, true);
return true;
}
wizard.showFailedToWriteMessage (newFile);
return false;
}
private:
virtual void createFiles (Project::Item parent, const String& className, const File& newFile)
{
if (create (*this, className, parent, newFile.withFileExtension ("h"), "jucer_NewComponentTemplate_h"))
create (*this, className, parent, newFile.withFileExtension ("cpp"), "jucer_NewComponentTemplate_cpp");
}
static String getClassNameFieldName() { return "Class Name"; }
void createNewFileInternal (Project::Item parent)
{
asyncAlertWindow = std::make_unique<AlertWindow> (TRANS ("Create new Component class"),
TRANS ("Please enter the name for the new class"),
MessageBoxIconType::NoIcon, nullptr);
asyncAlertWindow->addTextEditor (getClassNameFieldName(), String(), String(), false);
asyncAlertWindow->addButton (TRANS ("Create Files"), 1, KeyPress (KeyPress::returnKey));
asyncAlertWindow->addButton (TRANS ("Cancel"), 0, KeyPress (KeyPress::escapeKey));
auto resultCallback = [safeThis = WeakReference<NewComponentFileWizard> { this }, parent] (int result)
{
if (safeThis == nullptr)
return;
auto& aw = *(safeThis->asyncAlertWindow);
aw.exitModalState (result);
aw.setVisible (false);
if (result == 0)
return;
const String className (aw.getTextEditorContents (getClassNameFieldName()).trim());
if (className == build_tools::makeValidIdentifier (className, false, true, false))
{
safeThis->askUserToChooseNewFile (className + ".h", "*.h;*.cpp",
parent,
[safeThis, parent, className] (File newFile)
{
if (safeThis == nullptr)
return;
if (newFile != File())
safeThis->createFiles (parent, className, newFile);
});
return;
}
safeThis->createNewFileInternal (parent);
};
asyncAlertWindow->enterModalState (true, ModalCallbackFunction::create (std::move (resultCallback)), false);
}
std::unique_ptr<AlertWindow> asyncAlertWindow;
JUCE_DECLARE_WEAK_REFERENCEABLE (NewComponentFileWizard)
};
//==============================================================================
class NewSingleFileComponentFileWizard final : public NewComponentFileWizard
{
public:
String getName() override { return "Component class (in a single source file)"; }
void createFiles (Project::Item parent, const String& className, const File& newFile) override
{
create (*this, className, parent, newFile.withFileExtension ("h"), "jucer_NewInlineComponentTemplate_h");
}
};
//==============================================================================
void NewFileWizard::Type::showFailedToWriteMessage (const File& file)
{
auto options = MessageBoxOptions::makeOptionsOk (MessageBoxIconType::WarningIcon,
"Failed to Create File!",
"Couldn't write to the file: " + file.getFullPathName());
messageBox = AlertWindow::showScopedAsync (options, nullptr);
}
void NewFileWizard::Type::askUserToChooseNewFile (const String& suggestedFilename, const String& wildcard,
const Project::Item& projectGroupToAddTo,
std::function<void (File)> callback)
{
chooser = std::make_unique<FileChooser> ("Select File to Create",
projectGroupToAddTo.determineGroupFolder()
.getChildFile (suggestedFilename)
.getNonexistentSibling(),
wildcard);
auto flags = FileBrowserComponent::saveMode
| FileBrowserComponent::canSelectFiles
| FileBrowserComponent::warnAboutOverwriting;
chooser->launchAsync (flags, [callback] (const FileChooser& fc)
{
callback (fc.getResult());
});
}
//==============================================================================
NewFileWizard::NewFileWizard()
{
registerWizard (new NewCppFileWizard());
registerWizard (new NewHeaderFileWizard());
registerWizard (new NewCppAndHeaderFileWizard());
registerWizard (new NewComponentFileWizard());
registerWizard (new NewSingleFileComponentFileWizard());
}
NewFileWizard::~NewFileWizard()
{
}
void NewFileWizard::addWizardsToMenu (PopupMenu& m) const
{
for (int i = 0; i < wizards.size(); ++i)
m.addItem (menuBaseID + i, "Add New " + wizards.getUnchecked (i)->getName() + "...");
}
bool NewFileWizard::runWizardFromMenu (int chosenMenuItemID, Project& project, const Project::Item& projectGroupToAddTo) const
{
if (Type* wiz = wizards [chosenMenuItemID - menuBaseID])
{
wiz->createNewFile (project, projectGroupToAddTo);
return true;
}
return false;
}
void NewFileWizard::registerWizard (Type* newWizard)
{
wizards.add (newWizard);
}
@@ -0,0 +1,70 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "../../Project/jucer_Project.h"
//==============================================================================
class NewFileWizard
{
public:
//==============================================================================
NewFileWizard();
~NewFileWizard();
//==============================================================================
class Type
{
public:
virtual ~Type() = default;
//==============================================================================
virtual String getName() = 0;
virtual void createNewFile (Project&, Project::Item projectGroupToAddTo) = 0;
void showFailedToWriteMessage (const File& file);
protected:
//==============================================================================
void askUserToChooseNewFile (const String& suggestedFilename, const String& wildcard,
const Project::Item& projectGroupToAddTo,
std::function<void (File)> callback);
private:
std::unique_ptr<FileChooser> chooser;
ScopedMessageBox messageBox;
};
//==============================================================================
void addWizardsToMenu (PopupMenu&) const;
bool runWizardFromMenu (int chosenMenuItemID, Project&,
const Project::Item& projectGroupToAddTo) const;
void registerWizard (Type*);
private:
OwnedArray<Type> wizards;
};
@@ -0,0 +1,408 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
// Handy list of static Identifiers..
namespace Ids
{
#define DECLARE_ID(name) const Identifier name (#name)
DECLARE_ID (name);
DECLARE_ID (file);
DECLARE_ID (path);
DECLARE_ID (text);
DECLARE_ID (vendor);
DECLARE_ID (version);
DECLARE_ID (license);
DECLARE_ID (minimumCppStandard);
DECLARE_ID (include);
DECLARE_ID (info);
DECLARE_ID (description);
DECLARE_ID (companyName);
DECLARE_ID (companyCopyright);
DECLARE_ID (companyWebsite);
DECLARE_ID (companyEmail);
DECLARE_ID (useAppConfig);
DECLARE_ID (addUsingNamespaceToJuceHeader);
DECLARE_ID (usePrecompiledHeaderFile);
DECLARE_ID (precompiledHeaderFile);
DECLARE_ID (displaySplashScreen);
DECLARE_ID (splashScreenColour);
DECLARE_ID (position);
DECLARE_ID (source);
DECLARE_ID (width);
DECLARE_ID (height);
DECLARE_ID (bounds);
DECLARE_ID (background);
DECLARE_ID (initialState);
DECLARE_ID (targetFolder);
DECLARE_ID (intermediatesPath);
DECLARE_ID (modulePaths);
DECLARE_ID (searchpaths);
DECLARE_ID (osxFallback);
DECLARE_ID (windowsFallback);
DECLARE_ID (linuxFallback);
DECLARE_ID (jucePath);
DECLARE_ID (defaultJuceModulePath);
DECLARE_ID (defaultUserModulePath);
DECLARE_ID (vstLegacyFolder);
DECLARE_ID (vst3Folder);
DECLARE_ID (auFolder);
DECLARE_ID (vstLegacyPath);
DECLARE_ID (aaxPath);
DECLARE_ID (araPath);
DECLARE_ID (flags);
DECLARE_ID (line);
DECLARE_ID (index);
DECLARE_ID (type);
DECLARE_ID (time);
DECLARE_ID (extraCompilerFlags);
DECLARE_ID (extraLinkerFlags);
DECLARE_ID (externalLibraries);
DECLARE_ID (extraDefs);
DECLARE_ID (projectType);
DECLARE_ID (isDebug);
DECLARE_ID (alwaysGenerateDebugSymbols);
DECLARE_ID (targetName);
DECLARE_ID (binaryPath);
DECLARE_ID (recommendedWarnings);
DECLARE_ID (optimisation);
DECLARE_ID (defines);
DECLARE_ID (headerPath);
DECLARE_ID (systemHeaderPath);
DECLARE_ID (liveWindowsTargetPlatformVersion);
DECLARE_ID (libraryPath);
DECLARE_ID (customXcodeFlags);
DECLARE_ID (customXcassetsFolder);
DECLARE_ID (customLaunchStoryboard);
DECLARE_ID (customXcodeResourceFolders);
DECLARE_ID (plistPreprocessorDefinitions);
DECLARE_ID (applicationCategory);
DECLARE_ID (customPList);
DECLARE_ID (pListPrefixHeader);
DECLARE_ID (pListPreprocess);
DECLARE_ID (UIFileSharingEnabled);
DECLARE_ID (UISupportsDocumentBrowser);
DECLARE_ID (UIStatusBarHidden);
DECLARE_ID (UIRequiresFullScreen);
DECLARE_ID (documentExtensions);
DECLARE_ID (keepCustomXcodeSchemes);
DECLARE_ID (useHeaderMap);
DECLARE_ID (cppLanguageStandard);
DECLARE_ID (enableGNUExtensions);
DECLARE_ID (cppLibType);
DECLARE_ID (codeSigningIdentity);
DECLARE_ID (fastMath);
DECLARE_ID (linkTimeOptimisation);
DECLARE_ID (vstBinaryLocation);
DECLARE_ID (vst3BinaryLocation);
DECLARE_ID (auBinaryLocation);
DECLARE_ID (aaxBinaryLocation);
DECLARE_ID (unityPluginBinaryLocation);
DECLARE_ID (enablePluginBinaryCopyStep);
DECLARE_ID (stripLocalSymbols);
DECLARE_ID (macOSBaseSDK);
DECLARE_ID (macOSDeploymentTarget);
DECLARE_ID (osxArchitecture);
DECLARE_ID (iosBaseSDK);
DECLARE_ID (iosDeploymentTarget);
DECLARE_ID (xcodeSubprojects);
DECLARE_ID (extraFrameworks);
DECLARE_ID (frameworkSearchPaths);
DECLARE_ID (extraCustomFrameworks);
DECLARE_ID (embeddedFrameworks);
DECLARE_ID (extraDLLs);
DECLARE_ID (winArchitecture);
DECLARE_ID (winWarningLevel);
DECLARE_ID (msvcManifestFile);
DECLARE_ID (warningsAreErrors);
DECLARE_ID (linuxArchitecture);
DECLARE_ID (linuxCodeBlocksArchitecture);
DECLARE_ID (windowsCodeBlocksArchitecture);
DECLARE_ID (codeBlocksWindowsTarget);
DECLARE_ID (toolset);
DECLARE_ID (windowsTargetPlatformVersion);
DECLARE_ID (debugInformationFormat);
DECLARE_ID (IPPLibrary);
DECLARE_ID (IPP1ALibrary);
DECLARE_ID (MKL1ALibrary);
DECLARE_ID (msvcModuleDefinitionFile);
DECLARE_ID (bigIcon);
DECLARE_ID (smallIcon);
DECLARE_ID (prebuildCommand);
DECLARE_ID (postbuildCommand);
DECLARE_ID (generateManifest);
DECLARE_ID (useRuntimeLibDLL);
DECLARE_ID (multiProcessorCompilation);
DECLARE_ID (enableIncrementalLinking);
DECLARE_ID (bundleIdentifier);
DECLARE_ID (aaxIdentifier);
DECLARE_ID (araFactoryID);
DECLARE_ID (araDocumentArchiveID);
DECLARE_ID (araCompatibleArchiveIDs);
DECLARE_ID (aaxFolder);
DECLARE_ID (araFolder);
DECLARE_ID (compile);
DECLARE_ID (noWarnings);
DECLARE_ID (skipPCH);
DECLARE_ID (resource);
DECLARE_ID (xcodeResource);
DECLARE_ID (xcodeValidArchs);
DECLARE_ID (className);
DECLARE_ID (classDesc);
DECLARE_ID (controlPoint);
DECLARE_ID (createCallback);
DECLARE_ID (parentClasses);
DECLARE_ID (constructorParams);
DECLARE_ID (objectConstructionArgs);
DECLARE_ID (memberInitialisers);
DECLARE_ID (canBeAggregated);
DECLARE_ID (rootItemVisible);
DECLARE_ID (openByDefault);
DECLARE_ID (locked);
DECLARE_ID (tooltip);
DECLARE_ID (memberName);
DECLARE_ID (markerName);
DECLARE_ID (focusOrder);
DECLARE_ID (hidden);
DECLARE_ID (useStdCall);
DECLARE_ID (useGlobalPath);
DECLARE_ID (showAllCode);
DECLARE_ID (useLocalCopy);
DECLARE_ID (overwriteOnSave);
DECLARE_ID (appSandbox);
DECLARE_ID (appSandboxInheritance);
DECLARE_ID (appSandboxOptions);
DECLARE_ID (appSandboxHomeDirRO);
DECLARE_ID (appSandboxHomeDirRW);
DECLARE_ID (appSandboxAbsDirRO);
DECLARE_ID (appSandboxAbsDirRW);
DECLARE_ID (appSandboxExceptionIOKit);
DECLARE_ID (hardenedRuntime);
DECLARE_ID (hardenedRuntimeOptions);
DECLARE_ID (microphonePermissionNeeded);
DECLARE_ID (microphonePermissionsText);
DECLARE_ID (cameraPermissionNeeded);
DECLARE_ID (cameraPermissionText);
DECLARE_ID (sendAppleEventsPermissionNeeded);
DECLARE_ID (sendAppleEventsPermissionText);
DECLARE_ID (androidJavaLibs);
DECLARE_ID (androidAdditionalJavaFolders);
DECLARE_ID (androidAdditionalResourceFolders);
DECLARE_ID (androidProjectRepositories);
DECLARE_ID (androidRepositories);
DECLARE_ID (androidDependencies);
DECLARE_ID (androidCustomAppBuildGradleContent);
DECLARE_ID (androidBuildConfigRemoteNotifsConfigFile);
DECLARE_ID (androidAdditionalXmlValueResources);
DECLARE_ID (androidAdditionalDrawableResources);
DECLARE_ID (androidAdditionalRawValueResources);
// DECLARE_ID (androidActivityClass); // DEPRECATED!
const Identifier androidCustomActivityClass ("androidActivitySubClassName"); // old name is very confusing, but we need to remain backward compatible
// DECLARE_ID (androidActivityBaseClassName); // DEPRECATED!
DECLARE_ID (androidCustomApplicationClass);
DECLARE_ID (androidVersionCode);
DECLARE_ID (androidSDKPath);
DECLARE_ID (androidOboeRepositoryPath);
DECLARE_ID (androidInternetNeeded);
DECLARE_ID (androidArchitectures);
DECLARE_ID (androidManifestCustomXmlElements);
DECLARE_ID (androidGradleSettingsContent);
DECLARE_ID (androidCustomStringXmlElements);
DECLARE_ID (androidBluetoothNeeded);
DECLARE_ID (androidBluetoothScanNeeded);
DECLARE_ID (androidBluetoothAdvertiseNeeded);
DECLARE_ID (androidBluetoothConnectNeeded);
DECLARE_ID (androidExternalReadNeeded);
DECLARE_ID (androidReadMediaAudioPermission);
DECLARE_ID (androidReadMediaImagesPermission);
DECLARE_ID (androidReadMediaVideoPermission);
DECLARE_ID (androidExternalWriteNeeded);
DECLARE_ID (androidInAppBilling);
DECLARE_ID (androidVibratePermissionNeeded);
DECLARE_ID (androidPushNotifications);
DECLARE_ID (androidEnableRemoteNotifications);
DECLARE_ID (androidRemoteNotificationsConfigFile);
DECLARE_ID (androidEnableContentSharing);
DECLARE_ID (androidMinimumSDK);
DECLARE_ID (androidTargetSDK);
DECLARE_ID (androidOtherPermissions);
DECLARE_ID (androidKeyStore);
DECLARE_ID (androidKeyStorePass);
DECLARE_ID (androidKeyAlias);
DECLARE_ID (androidKeyAliasPass);
DECLARE_ID (androidTheme);
DECLARE_ID (androidStaticLibraries);
DECLARE_ID (androidSharedLibraries);
DECLARE_ID (androidScreenOrientation);
DECLARE_ID (androidExtraAssetsFolder);
DECLARE_ID (androidStudioExePath);
DECLARE_ID (iosDeviceFamily);
const Identifier iPhoneScreenOrientation ("iosScreenOrientation"); // old name is confusing
DECLARE_ID (iPadScreenOrientation);
DECLARE_ID (iosScreenOrientation);
DECLARE_ID (iosInAppPurchases);
DECLARE_ID (iosContentSharing);
DECLARE_ID (iosBackgroundAudio);
DECLARE_ID (iosBackgroundBle);
DECLARE_ID (iosPushNotifications);
DECLARE_ID (iosAppGroups);
DECLARE_ID (iCloudPermissions);
DECLARE_ID (networkingMulticast);
DECLARE_ID (iosDevelopmentTeamID);
DECLARE_ID (iosAppGroupsId);
DECLARE_ID (iosBluetoothPermissionNeeded);
DECLARE_ID (iosBluetoothPermissionText);
DECLARE_ID (duplicateAppExResourcesFolder);
DECLARE_ID (buildToolsVersion);
DECLARE_ID (gradleVersion);
const Identifier androidPluginVersion ("gradleWrapperVersion"); // old name is very confusing, but we need to remain backward compatible
DECLARE_ID (gradleToolchain);
DECLARE_ID (gradleToolchainVersion);
DECLARE_ID (gradleClangTidy);
DECLARE_ID (linuxExtraPkgConfig);
DECLARE_ID (font);
DECLARE_ID (colour);
DECLARE_ID (userNotes);
DECLARE_ID (maxBinaryFileSize);
DECLARE_ID (includeBinaryInJuceHeader);
DECLARE_ID (binaryDataNamespace);
DECLARE_ID (characterSet);
DECLARE_ID (JUCERPROJECT);
DECLARE_ID (MAINGROUP);
DECLARE_ID (EXPORTFORMATS);
DECLARE_ID (GROUP);
DECLARE_ID (FILE);
DECLARE_ID (MODULES);
DECLARE_ID (MODULE);
DECLARE_ID (JUCEOPTIONS);
DECLARE_ID (CONFIGURATIONS);
DECLARE_ID (CONFIGURATION);
DECLARE_ID (MODULEPATHS);
DECLARE_ID (MODULEPATH);
DECLARE_ID (PATH);
DECLARE_ID (userpath);
DECLARE_ID (systempath);
DECLARE_ID (utilsCppInclude);
DECLARE_ID (juceModulesFolder);
DECLARE_ID (parentActive);
DECLARE_ID (message);
DECLARE_ID (start);
DECLARE_ID (end);
DECLARE_ID (range);
DECLARE_ID (location);
DECLARE_ID (key);
DECLARE_ID (list);
DECLARE_ID (METADATA);
DECLARE_ID (DEPENDENCIES);
DECLARE_ID (CLASSLIST);
DECLARE_ID (CLASS);
DECLARE_ID (MEMBER);
DECLARE_ID (METHOD);
DECLARE_ID (LITERALS);
DECLARE_ID (LITERAL);
DECLARE_ID (abstract);
DECLARE_ID (anonymous);
DECLARE_ID (noDefConstructor);
DECLARE_ID (returnType);
DECLARE_ID (numArgs);
DECLARE_ID (declaration);
DECLARE_ID (definition);
DECLARE_ID (classDecl);
DECLARE_ID (initialisers);
DECLARE_ID (destructors);
DECLARE_ID (pluginFormats);
DECLARE_ID (buildVST);
DECLARE_ID (buildVST3);
DECLARE_ID (buildAU);
DECLARE_ID (buildAUv3);
DECLARE_ID (buildAAX);
DECLARE_ID (buildStandalone);
DECLARE_ID (buildUnity);
DECLARE_ID (buildLV2);
DECLARE_ID (enableIAA);
DECLARE_ID (enableARA);
DECLARE_ID (pluginName);
DECLARE_ID (pluginDesc);
DECLARE_ID (pluginManufacturer);
DECLARE_ID (pluginManufacturerCode);
DECLARE_ID (pluginCode);
DECLARE_ID (pluginChannelConfigs);
DECLARE_ID (pluginCharacteristicsValue);
DECLARE_ID (pluginCharacteristics);
DECLARE_ID (extraPluginFormats);
DECLARE_ID (pluginIsSynth);
DECLARE_ID (pluginWantsMidiIn);
DECLARE_ID (pluginProducesMidiOut);
DECLARE_ID (pluginIsMidiEffectPlugin);
DECLARE_ID (pluginEditorRequiresKeys);
DECLARE_ID (pluginVSTCategory);
DECLARE_ID (pluginVST3Category);
DECLARE_ID (pluginAUExportPrefix);
DECLARE_ID (pluginAUMainType);
DECLARE_ID (pluginAUIsSandboxSafe);
DECLARE_ID (pluginAAXCategory);
DECLARE_ID (pluginAAXDisableBypass);
DECLARE_ID (pluginAAXDisableMultiMono);
DECLARE_ID (pluginARAAnalyzableContent);
DECLARE_ID (pluginARATransformFlags);
DECLARE_ID (pluginVSTNumMidiInputs);
DECLARE_ID (pluginVSTNumMidiOutputs);
DECLARE_ID (suppressPlistResourceUsage);
DECLARE_ID (useLegacyBuildSystem);
DECLARE_ID (exporters);
DECLARE_ID (website);
DECLARE_ID (mainClass);
DECLARE_ID (documentControllerClass);
DECLARE_ID (moduleFlags);
DECLARE_ID (projectLineFeed);
DECLARE_ID (compilerFlagSchemes);
DECLARE_ID (compilerFlagScheme);
DECLARE_ID (dontQueryForUpdate);
DECLARE_ID (dontAskAboutJUCEPath);
DECLARE_ID (postExportShellCommandPosix);
DECLARE_ID (postExportShellCommandWin);
DECLARE_ID (guiEditorEnabled);
DECLARE_ID (jucerFormatVersion);
DECLARE_ID (buildNumber);
DECLARE_ID (lv2Uri);
DECLARE_ID (lv2UriUi);
DECLARE_ID (lv2BinaryLocation);
DECLARE_ID (vst3ManifestEnabled);
DECLARE_ID (osxSDK);
DECLARE_ID (osxCompatibility);
DECLARE_ID (iosCompatibility);
const Identifier ID ("id");
const Identifier ID_uppercase ("ID");
const Identifier class_ ("class");
const Identifier dependencies_ ("dependencies");
#undef DECLARE_ID
}
@@ -0,0 +1,324 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
struct TranslationHelpers
{
static void addString (StringArray& strings, const String& s)
{
if (s.isNotEmpty() && ! strings.contains (s))
strings.add (s);
}
static void scanFileForTranslations (StringArray& strings, const File& file)
{
auto content = file.loadFileAsString();
auto p = content.getCharPointer();
for (;;)
{
p = CharacterFunctions::find (p, CharPointer_ASCII ("TRANS"));
if (p.isEmpty())
break;
p += 5;
p.incrementToEndOfWhitespace();
if (*p == '(')
{
++p;
MemoryOutputStream text;
parseStringLiteral (p, text);
addString (strings, text.toString());
}
}
}
static void parseStringLiteral (String::CharPointerType& p, MemoryOutputStream& out) noexcept
{
p.incrementToEndOfWhitespace();
if (p.getAndAdvance() == '"')
{
auto start = p;
for (;;)
{
auto c = *p;
if (c == '"')
{
out << String (start, p);
++p;
parseStringLiteral (p, out);
return;
}
if (c == 0)
break;
if (c == '\\')
{
out << String (start, p);
++p;
out << String::charToString (readEscapedChar (p));
start = p + 1;
}
++p;
}
}
}
static juce_wchar readEscapedChar (String::CharPointerType& p)
{
auto c = *p;
switch (c)
{
case '"':
case '\\':
case '/': break;
case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'x':
++p;
c = 0;
for (int i = 4; --i >= 0;)
{
const int digitValue = CharacterFunctions::getHexDigitValue (*p);
if (digitValue < 0)
break;
++p;
c = (c << 4) + (juce_wchar) digitValue;
}
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c = 0;
for (int i = 4; --i >= 0;)
{
const auto digitValue = (int) (*p - '0');
if (digitValue < 0 || digitValue > 7)
break;
++p;
c = (c << 3) + (juce_wchar) digitValue;
}
break;
default:
break;
}
return c;
}
static void scanFilesForTranslations (StringArray& strings, const Project::Item& p)
{
if (p.isFile())
{
const File file (p.getFile());
if (file.hasFileExtension (sourceOrHeaderFileExtensions))
scanFileForTranslations (strings, file);
}
for (int i = 0; i < p.getNumChildren(); ++i)
scanFilesForTranslations (strings, p.getChild (i));
}
static void scanFolderForTranslations (StringArray& strings, const File& root)
{
for (const auto& i : RangedDirectoryIterator (root, true))
{
const auto file = i.getFile();
if (file.hasFileExtension (sourceOrHeaderFileExtensions))
scanFileForTranslations (strings, file);
}
}
static void scanProject (StringArray& strings, Project& project)
{
scanFilesForTranslations (strings, project.getMainGroup());
OwnedArray<LibraryModule> modules;
project.getEnabledModules().createRequiredModules (modules);
for (int j = 0; j < modules.size(); ++j)
{
const File localFolder (modules.getUnchecked (j)->getFolder());
Array<File> files;
modules.getUnchecked (j)->findBrowseableFiles (localFolder, files);
for (int i = 0; i < files.size(); ++i)
scanFileForTranslations (strings, files.getReference (i));
}
}
static const char* getMungingSeparator() { return "JCTRIDX"; }
static StringArray breakApart (const String& munged)
{
StringArray lines, result;
lines.addLines (munged);
String currentItem;
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i].contains (getMungingSeparator()))
{
if (currentItem.isNotEmpty())
result.add (currentItem);
currentItem = String();
}
else
{
if (currentItem.isNotEmpty())
currentItem << newLine;
currentItem << lines[i];
}
}
if (currentItem.isNotEmpty())
result.add (currentItem);
return result;
}
static StringArray withTrimmedEnds (StringArray array)
{
for (auto& s : array)
s = s.trimEnd().removeCharacters ("\r\n");
return array;
}
static String escapeString (const String& s)
{
return s.replace ("\"", "\\\"")
.replace ("\'", "\\\'")
.replace ("\t", "\\t")
.replace ("\r", "\\r")
.replace ("\n", "\\n");
}
static String getPreTranslationText (Project& project)
{
StringArray strings;
scanProject (strings, project);
return mungeStrings (strings);
}
static String getPreTranslationText (const LocalisedStrings& strings)
{
return mungeStrings (strings.getMappings().getAllKeys());
}
static String mungeStrings (const StringArray& strings)
{
MemoryOutputStream s;
for (int i = 0; i < strings.size(); ++i)
{
s << getMungingSeparator() << i << "." << newLine << strings[i];
if (i < strings.size() - 1)
s << newLine;
}
return s.toString();
}
static String createLine (const String& preString, const String& postString)
{
return "\"" + escapeString (preString)
+ "\" = \""
+ escapeString (postString) + "\"";
}
static String createFinishedTranslationFile (StringArray preStrings,
StringArray postStrings,
const LocalisedStrings& original)
{
const StringPairArray& originalStrings (original.getMappings());
StringArray lines;
if (originalStrings.size() > 0)
{
lines.add ("language: " + original.getLanguageName());
lines.add ("countries: " + original.getCountryCodes().joinIntoString (" "));
lines.add (String());
const StringArray& originalKeys (originalStrings.getAllKeys());
const StringArray& originalValues (originalStrings.getAllValues());
for (int i = preStrings.size(); --i >= 0;)
{
if (originalKeys.contains (preStrings[i]))
{
preStrings.remove (i);
postStrings.remove (i);
}
}
for (int i = 0; i < originalStrings.size(); ++i)
lines.add (createLine (originalKeys[i], originalValues[i]));
}
else
{
lines.add ("language: [enter full name of the language here!]");
lines.add ("countries: [enter list of 2-character country codes here!]");
lines.add (String());
}
for (int i = 0; i < preStrings.size(); ++i)
lines.add (createLine (preStrings[i], postStrings[i]));
return lines.joinIntoString (newLine);
}
};
@@ -0,0 +1,50 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
template <typename Type>
class NumericValueSource final : public ValueSourceFilter
{
public:
NumericValueSource (const Value& source) : ValueSourceFilter (source) {}
var getValue() const override
{
return (Type) sourceValue.getValue();
}
void setValue (const var& newValue) override
{
const Type newVal = static_cast<Type> (newValue);
if (newVal != static_cast<Type> (getValue())) // this test is important, because if a property is missing, it won't
sourceValue = newVal; // create it (causing an unwanted undo action) when a control sets it to 0
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NumericValueSource)
};
@@ -0,0 +1,75 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
/**
Wraps a ValueTreePropertyWithDefault object that has a default which depends on a global value.
*/
class ValueTreePropertyWithDefaultWrapper final : private Value::Listener
{
public:
ValueTreePropertyWithDefaultWrapper() = default;
void init (const ValueTreePropertyWithDefault& v,
ValueTreePropertyWithDefault global,
TargetOS::OS targetOS)
{
wrappedValue = v;
globalValue = global.getPropertyAsValue();
globalIdentifier = global.getPropertyID();
os = targetOS;
if (wrappedValue.get() == var())
wrappedValue.resetToDefault();
globalValue.addListener (this);
valueChanged (globalValue);
}
ValueTreePropertyWithDefault& getWrappedValueTreePropertyWithDefault()
{
return wrappedValue;
}
var getCurrentValue() const
{
return wrappedValue.get();
}
private:
void valueChanged (Value&) override
{
wrappedValue.setDefault (getAppSettings().getStoredPath (globalIdentifier, os).get());
}
ValueTreePropertyWithDefault wrappedValue;
Value globalValue;
Identifier globalIdentifier;
TargetOS::OS os;
};
@@ -0,0 +1,126 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "jucer_VersionInfo.h"
VersionInfo::VersionInfo (String versionIn, String releaseNotesIn, std::vector<Asset> assetsIn)
: versionString (std::move (versionIn)),
releaseNotes (std::move (releaseNotesIn)),
assets (std::move (assetsIn))
{}
std::unique_ptr<VersionInfo> VersionInfo::fetchFromUpdateServer (const String& versionString)
{
return fetch ("tags/" + versionString);
}
std::unique_ptr<VersionInfo> VersionInfo::fetchLatestFromUpdateServer()
{
return fetch ("latest");
}
std::unique_ptr<InputStream> VersionInfo::createInputStreamForAsset (const Asset& asset, int& statusCode)
{
URL downloadUrl (asset.url);
StringPairArray responseHeaders;
return std::unique_ptr<InputStream> (downloadUrl.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)
.withExtraHeaders ("Accept: application/octet-stream")
.withConnectionTimeoutMs (5000)
.withResponseHeaders (&responseHeaders)
.withStatusCode (&statusCode)
.withNumRedirectsToFollow (1)));
}
bool VersionInfo::isNewerVersionThanCurrent()
{
jassert (versionString.isNotEmpty());
auto currentTokens = StringArray::fromTokens (ProjectInfo::versionString, ".", {});
auto thisTokens = StringArray::fromTokens (versionString, ".", {});
jassert (thisTokens.size() == 3);
if (currentTokens[0].getIntValue() == thisTokens[0].getIntValue())
{
if (currentTokens[1].getIntValue() == thisTokens[1].getIntValue())
return currentTokens[2].getIntValue() < thisTokens[2].getIntValue();
return currentTokens[1].getIntValue() < thisTokens[1].getIntValue();
}
return currentTokens[0].getIntValue() < thisTokens[0].getIntValue();
}
std::unique_ptr<VersionInfo> VersionInfo::fetch (const String& endpoint)
{
URL latestVersionURL ("https://api.github.com/repos/juce-framework/JUCE/releases/" + endpoint);
std::unique_ptr<InputStream> inStream (latestVersionURL.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)
.withConnectionTimeoutMs (5000)));
if (inStream == nullptr)
return nullptr;
auto content = inStream->readEntireStreamAsString();
auto latestReleaseDetails = JSON::parse (content);
auto* json = latestReleaseDetails.getDynamicObject();
if (json == nullptr)
return nullptr;
auto versionString = json->getProperty ("tag_name").toString();
if (versionString.isEmpty())
return nullptr;
auto* assets = json->getProperty ("assets").getArray();
if (assets == nullptr)
return nullptr;
auto releaseNotes = json->getProperty ("body").toString();
std::vector<VersionInfo::Asset> parsedAssets;
for (auto& asset : *assets)
{
if (auto* assetJson = asset.getDynamicObject())
{
parsedAssets.push_back ({ assetJson->getProperty ("name").toString(),
assetJson->getProperty ("url").toString() });
jassert (parsedAssets.back().name.isNotEmpty());
jassert (parsedAssets.back().url.isNotEmpty());
}
else
{
jassertfalse;
}
}
return std::unique_ptr<VersionInfo> (new VersionInfo { versionString, releaseNotes, std::move (parsedAssets) });
}
@@ -0,0 +1,53 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
class VersionInfo
{
public:
struct Asset
{
const String name;
const String url;
};
static std::unique_ptr<VersionInfo> fetchFromUpdateServer (const String& versionString);
static std::unique_ptr<VersionInfo> fetchLatestFromUpdateServer();
static std::unique_ptr<InputStream> createInputStreamForAsset (const Asset& asset, int& statusCode);
bool isNewerVersionThanCurrent();
const String versionString;
const String releaseNotes;
const std::vector<Asset> assets;
private:
VersionInfo (String version, String releaseNotes, std::vector<Asset> assets);
static std::unique_ptr<VersionInfo> fetch (const String&);
};
@@ -0,0 +1,587 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "../../ProjectSaving/jucer_ProjectExporter.h"
#include "../../ProjectSaving/jucer_ProjectExport_Xcode.h"
#include "../../ProjectSaving/jucer_ProjectExport_Android.h"
#include "../../ProjectSaving/jucer_ProjectExport_MSVC.h"
#include "jucer_PIPGenerator.h"
//==============================================================================
static void ensureSingleNewLineAfterIncludes (StringArray& lines)
{
int lastIncludeIndex = -1;
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i].contains ("#include"))
lastIncludeIndex = i;
}
if (lastIncludeIndex != -1)
{
auto index = lastIncludeIndex;
int numNewLines = 0;
while (++index < lines.size() && lines[index].isEmpty())
++numNewLines;
if (numNewLines > 1)
lines.removeRange (lastIncludeIndex + 1, numNewLines - 1);
}
}
static String ensureCorrectWhitespace (StringRef input)
{
auto lines = StringArray::fromLines (input);
ensureSingleNewLineAfterIncludes (lines);
return joinLinesIntoSourceFile (lines);
}
static bool isJUCEExample (const File& pipFile)
{
const auto numLinesToTest = 10; // license should be at the top of the file so no need to check all lines
const auto lines = StringArray::fromLines (pipFile.loadFileAsString());
return std::any_of (lines.begin(),
lines.begin() + (std::min (lines.size(), numLinesToTest)),
[] (const auto& line)
{
return line.contains ("This file is part of the JUCE examples.");
});
}
static bool isValidExporterIdentifier (const Identifier& exporterIdentifier)
{
return ProjectExporter::getTypeInfoForExporter (exporterIdentifier).identifier.toString().isNotEmpty();
}
static bool exporterRequiresExampleAssets (const Identifier& exporterIdentifier, const String& projectName)
{
return (exporterIdentifier.toString() == XcodeProjectExporter::getValueTreeTypeNameiOS()
|| exporterIdentifier.toString() == AndroidProjectExporter::getValueTreeTypeName())
|| (exporterIdentifier.toString() == XcodeProjectExporter::getValueTreeTypeNameMac() && projectName == "AUv3SynthPlugin");
}
//==============================================================================
PIPGenerator::PIPGenerator (const File& pip, const File& output, const File& jucePath, const File& userPath)
: pipFile (pip),
juceModulesPath (jucePath),
userModulesPath (userPath),
metadata (parseJUCEHeaderMetadata (pipFile))
{
if (output != File())
{
outputDirectory = output;
isTemp = false;
}
else
{
outputDirectory = File::getSpecialLocation (File::SpecialLocationType::tempDirectory).getChildFile ("PIPs");
isTemp = true;
}
auto isClipboard = (pip.getParentDirectory().getFileName() == "Clipboard"
&& pip.getParentDirectory().getParentDirectory().getFileName() == "PIPs");
outputDirectory = outputDirectory.getChildFile (metadata[Ids::name].toString()).getNonexistentSibling();
useLocalCopy = metadata[Ids::useLocalCopy].toString().trim().getIntValue() == 1 || isClipboard;
if (userModulesPath != File())
{
availableUserModules.reset (new AvailableModulesList());
availableUserModules->scanPaths ({ userModulesPath });
}
}
//==============================================================================
Result PIPGenerator::createJucerFile()
{
ValueTree root (Ids::JUCERPROJECT);
auto result = setProjectSettings (root);
if (result != Result::ok())
return result;
addModules (root);
addExporters (root);
createFiles (root);
setModuleFlags (root);
auto outputFile = outputDirectory.getChildFile (metadata[Ids::name].toString() + ".jucer");
if (auto xml = root.createXml())
if (xml->writeTo (outputFile, {}))
return Result::ok();
return Result::fail ("Failed to create .jucer file in " + outputDirectory.getFullPathName());
}
Result PIPGenerator::createMainCpp()
{
auto outputFile = outputDirectory.getChildFile ("Source").getChildFile ("Main.cpp");
if (! outputFile.existsAsFile() && (outputFile.create() != Result::ok()))
return Result::fail ("Failed to create Main.cpp - " + outputFile.getFullPathName());
outputFile.replaceWithText (getMainFileTextForType());
return Result::ok();
}
//==============================================================================
void PIPGenerator::addFileToTree (ValueTree& groupTree, const String& name, bool compile, const String& path)
{
ValueTree file (Ids::FILE);
file.setProperty (Ids::ID, createAlphaNumericUID(), nullptr);
file.setProperty (Ids::name, name, nullptr);
file.setProperty (Ids::compile, compile, nullptr);
file.setProperty (Ids::resource, 0, nullptr);
file.setProperty (Ids::file, path, nullptr);
groupTree.addChild (file, -1, nullptr);
}
void PIPGenerator::createFiles (ValueTree& jucerTree)
{
auto sourceDir = outputDirectory.getChildFile ("Source");
if (! sourceDir.exists())
sourceDir.createDirectory();
if (useLocalCopy)
pipFile.copyFileTo (sourceDir.getChildFile (pipFile.getFileName()));
ValueTree mainGroup (Ids::MAINGROUP);
mainGroup.setProperty (Ids::ID, createAlphaNumericUID(), nullptr);
mainGroup.setProperty (Ids::name, metadata[Ids::name], nullptr);
ValueTree group (Ids::GROUP);
group.setProperty (Ids::ID, createGUID (sourceDir.getFullPathName() + "_guidpathsaltxhsdf"), nullptr);
group.setProperty (Ids::name, "Source", nullptr);
addFileToTree (group, "Main.cpp", true, "Source/Main.cpp");
addFileToTree (group, pipFile.getFileName(), false, useLocalCopy ? "Source/" + pipFile.getFileName()
: pipFile.getFullPathName());
mainGroup.addChild (group, -1, nullptr);
if (useLocalCopy)
{
auto relativeFiles = replaceRelativeIncludesAndGetFilesToMove();
if (relativeFiles.size() > 0)
{
ValueTree assets (Ids::GROUP);
assets.setProperty (Ids::ID, createAlphaNumericUID(), nullptr);
assets.setProperty (Ids::name, "Assets", nullptr);
for (auto& f : relativeFiles)
if (copyRelativeFileToLocalSourceDirectory (f))
addFileToTree (assets, f.getFileName(), f.getFileExtension() == ".cpp", "Source/" + f.getFileName());
mainGroup.addChild (assets, -1, nullptr);
}
}
jucerTree.addChild (mainGroup, 0, nullptr);
}
String PIPGenerator::getDocumentControllerClass() const
{
return metadata.getProperty (Ids::documentControllerClass, "").toString();
}
ValueTree PIPGenerator::createModulePathChild (const String& moduleID)
{
ValueTree modulePath (Ids::MODULEPATH);
modulePath.setProperty (Ids::ID, moduleID, nullptr);
modulePath.setProperty (Ids::path, getPathForModule (moduleID), nullptr);
return modulePath;
}
ValueTree PIPGenerator::createBuildConfigChild (bool isDebug)
{
ValueTree child (Ids::CONFIGURATION);
child.setProperty (Ids::name, isDebug ? "Debug" : "Release", nullptr);
child.setProperty (Ids::isDebug, isDebug ? 1 : 0, nullptr);
child.setProperty (Ids::optimisation, isDebug ? 1 : 3, nullptr);
child.setProperty (Ids::targetName, metadata[Ids::name], nullptr);
return child;
}
ValueTree PIPGenerator::createExporterChild (const Identifier& exporterIdentifier)
{
ValueTree exporter (exporterIdentifier);
exporter.setProperty (Ids::targetFolder, "Builds/" + ProjectExporter::getTypeInfoForExporter (exporterIdentifier).targetFolder, nullptr);
const Identifier vsExporters[] { MSVCProjectExporterVC2017::getValueTreeTypeName(),
MSVCProjectExporterVC2019::getValueTreeTypeName(),
MSVCProjectExporterVC2022::getValueTreeTypeName() };
if (isJUCEExample (pipFile) && std::find (std::begin (vsExporters), std::end (vsExporters), exporterIdentifier) != std::end (vsExporters))
{
exporter.setProperty (Ids::extraCompilerFlags, "/bigobj", nullptr);
}
if (isJUCEExample (pipFile) && exporterRequiresExampleAssets (exporterIdentifier, metadata[Ids::name]))
{
auto examplesDir = getExamplesDirectory();
if (examplesDir != File())
{
auto assetsDirectoryPath = examplesDir.getChildFile ("Assets").getFullPathName();
exporter.setProperty (exporterIdentifier.toString() == AndroidProjectExporter::getValueTreeTypeName() ? Ids::androidExtraAssetsFolder
: Ids::customXcodeResourceFolders,
assetsDirectoryPath, nullptr);
}
else
{
// invalid JUCE path
jassertfalse;
}
}
if (exporterIdentifier.toString() == AndroidProjectExporter::getValueTreeTypeName())
exporter.setProperty (Ids::androidBluetoothNeeded, true, nullptr);
{
ValueTree configs (Ids::CONFIGURATIONS);
configs.addChild (createBuildConfigChild (true), -1, nullptr);
configs.addChild (createBuildConfigChild (false), -1, nullptr);
exporter.addChild (configs, -1, nullptr);
}
{
ValueTree modulePaths (Ids::MODULEPATHS);
auto modules = StringArray::fromTokens (metadata[Ids::dependencies_].toString(), ",", {});
for (auto m : modules)
modulePaths.addChild (createModulePathChild (m.trim()), -1, nullptr);
exporter.addChild (modulePaths, -1, nullptr);
}
return exporter;
}
ValueTree PIPGenerator::createModuleChild (const String& moduleID)
{
ValueTree module (Ids::MODULE);
module.setProperty (Ids::ID, moduleID, nullptr);
module.setProperty (Ids::showAllCode, 1, nullptr);
module.setProperty (Ids::useLocalCopy, 0, nullptr);
module.setProperty (Ids::useGlobalPath, (getPathForModule (moduleID).isEmpty() ? 1 : 0), nullptr);
return module;
}
void PIPGenerator::addExporters (ValueTree& jucerTree)
{
ValueTree exportersTree (Ids::EXPORTFORMATS);
auto exporters = StringArray::fromTokens (metadata[Ids::exporters].toString(), ",", {});
for (auto& e : exporters)
{
e = e.trim().toUpperCase();
if (isValidExporterIdentifier (e))
exportersTree.addChild (createExporterChild (e), -1, nullptr);
}
jucerTree.addChild (exportersTree, -1, nullptr);
}
void PIPGenerator::addModules (ValueTree& jucerTree)
{
ValueTree modulesTree (Ids::MODULES);
auto modules = StringArray::fromTokens (metadata[Ids::dependencies_].toString(), ",", {});
modules.trim();
for (auto& m : modules)
modulesTree.addChild (createModuleChild (m.trim()), -1, nullptr);
jucerTree.addChild (modulesTree, -1, nullptr);
}
Result PIPGenerator::setProjectSettings (ValueTree& jucerTree)
{
auto setPropertyIfNotEmpty = [&jucerTree] (const Identifier& name, const var& value)
{
if (value != var())
jucerTree.setProperty (name, value, nullptr);
};
setPropertyIfNotEmpty (Ids::name, metadata[Ids::name]);
setPropertyIfNotEmpty (Ids::companyName, metadata[Ids::vendor]);
setPropertyIfNotEmpty (Ids::version, metadata[Ids::version]);
setPropertyIfNotEmpty (Ids::userNotes, metadata[Ids::description]);
setPropertyIfNotEmpty (Ids::companyWebsite, metadata[Ids::website]);
auto defines = metadata[Ids::defines].toString();
if (isJUCEExample (pipFile))
{
auto examplesDir = getExamplesDirectory();
if (examplesDir != File())
{
defines += ((defines.isEmpty() ? "" : " ") + String ("PIP_JUCE_EXAMPLES_DIRECTORY=")
+ Base64::toBase64 (examplesDir.getFullPathName()));
}
else
{
return Result::fail (String ("Invalid JUCE path. Set path to JUCE via ") +
(TargetOS::getThisOS() == TargetOS::osx ? "\"Projucer->Global Paths...\""
: "\"File->Global Paths...\"")
+ " menu item.");
}
jucerTree.setProperty (Ids::displaySplashScreen, true, nullptr);
}
setPropertyIfNotEmpty (Ids::defines, defines);
auto type = metadata[Ids::type].toString();
if (type == "Console")
{
jucerTree.setProperty (Ids::projectType, build_tools::ProjectType_ConsoleApp::getTypeName(), nullptr);
}
else if (type == "Component")
{
jucerTree.setProperty (Ids::projectType, build_tools::ProjectType_GUIApp::getTypeName(), nullptr);
}
else if (type == "AudioProcessor")
{
jucerTree.setProperty (Ids::projectType, build_tools::ProjectType_AudioPlugin::getTypeName(), nullptr);
jucerTree.setProperty (Ids::pluginAUIsSandboxSafe, "1", nullptr);
setPropertyIfNotEmpty (Ids::pluginManufacturer, metadata[Ids::vendor]);
StringArray pluginFormatsToBuild (Ids::buildVST3.toString(), Ids::buildAU.toString(), Ids::buildStandalone.toString());
pluginFormatsToBuild.addArray (getExtraPluginFormatsToBuild());
if (getDocumentControllerClass().isNotEmpty())
pluginFormatsToBuild.add (Ids::enableARA.toString());
jucerTree.setProperty (Ids::pluginFormats, pluginFormatsToBuild.joinIntoString (","), nullptr);
const auto characteristics = metadata[Ids::pluginCharacteristics].toString();
if (characteristics.isNotEmpty())
jucerTree.setProperty (Ids::pluginCharacteristicsValue,
characteristics.removeCharacters (" \t\n\r"),
nullptr);
}
jucerTree.setProperty (Ids::useAppConfig, false, nullptr);
jucerTree.setProperty (Ids::addUsingNamespaceToJuceHeader, true, nullptr);
return Result::ok();
}
void PIPGenerator::setModuleFlags (ValueTree& jucerTree)
{
ValueTree options ("JUCEOPTIONS");
for (auto& option : StringArray::fromTokens (metadata[Ids::moduleFlags].toString(), ",", {}))
{
auto name = option.upToFirstOccurrenceOf ("=", false, true).trim();
auto value = option.fromFirstOccurrenceOf ("=", false, true).trim();
options.setProperty (name, (value == "1" ? 1 : 0), nullptr);
}
if (metadata[Ids::type].toString() == "AudioProcessor"
&& options.getPropertyPointer ("JUCE_VST3_CAN_REPLACE_VST2") == nullptr)
options.setProperty ("JUCE_VST3_CAN_REPLACE_VST2", 0, nullptr);
jucerTree.addChild (options, -1, nullptr);
}
String PIPGenerator::getMainFileTextForType()
{
const auto type = metadata[Ids::type].toString();
const auto documentControllerClass = getDocumentControllerClass();
const auto mainTemplate = [&]
{
if (type == "Console")
return String (BinaryData::PIPConsole_cpp_in);
if (type == "Component")
return String (BinaryData::PIPComponent_cpp_in)
.replace ("${JUCE_PIP_NAME}", metadata[Ids::name].toString())
.replace ("${PROJECT_VERSION}", metadata[Ids::version].toString())
.replace ("${JUCE_PIP_MAIN_CLASS}", metadata[Ids::mainClass].toString());
if (type == "AudioProcessor")
{
if (documentControllerClass.isNotEmpty())
{
return String (BinaryData::PIPAudioProcessorWithARA_cpp_in)
.replace ("${JUCE_PIP_MAIN_CLASS}", metadata[Ids::mainClass].toString())
.replace ("${JUCE_PIP_DOCUMENTCONTROLLER_CLASS}", documentControllerClass);
}
return String (BinaryData::PIPAudioProcessor_cpp_in)
.replace ("${JUCE_PIP_MAIN_CLASS}", metadata[Ids::mainClass].toString());
}
return String{};
}();
if (mainTemplate.isEmpty())
return {};
const auto includeFilename = [&]
{
if (useLocalCopy) return pipFile.getFileName();
if (isTemp) return pipFile.getFullPathName();
return build_tools::RelativePath (pipFile,
outputDirectory.getChildFile ("Source"),
build_tools::RelativePath::unknown).toUnixStyle();
}();
return ensureCorrectWhitespace (mainTemplate.replace ("${JUCE_PIP_HEADER}", includeFilename));
}
//==============================================================================
Array<File> PIPGenerator::replaceRelativeIncludesAndGetFilesToMove()
{
StringArray lines;
pipFile.readLines (lines);
Array<File> files;
for (auto& line : lines)
{
if (line.contains ("#include") && ! line.contains ("JuceLibraryCode"))
{
auto path = line.fromFirstOccurrenceOf ("#include", false, false);
path = path.removeCharacters ("\"").trim();
if (path.startsWith ("<") && path.endsWith (">"))
continue;
auto file = pipFile.getParentDirectory().getChildFile (path);
files.add (file);
line = line.replace (path, file.getFileName());
}
}
outputDirectory.getChildFile ("Source")
.getChildFile (pipFile.getFileName())
.replaceWithText (joinLinesIntoSourceFile (lines));
return files;
}
bool PIPGenerator::copyRelativeFileToLocalSourceDirectory (const File& fileToCopy) const noexcept
{
return fileToCopy.copyFileTo (outputDirectory.getChildFile ("Source")
.getChildFile (fileToCopy.getFileName()));
}
StringArray PIPGenerator::getExtraPluginFormatsToBuild() const
{
auto tokens = StringArray::fromTokens (metadata[Ids::extraPluginFormats].toString(), ",", {});
for (auto& token : tokens)
{
token = [&]
{
if (token == "IAA")
return Ids::enableIAA.toString();
return "build" + token;
}();
}
return tokens;
}
String PIPGenerator::getPathForModule (const String& moduleID) const
{
if (isJUCEModule (moduleID))
{
if (juceModulesPath != File())
{
if (isTemp)
return juceModulesPath.getFullPathName();
return build_tools::RelativePath (juceModulesPath,
outputDirectory,
build_tools::RelativePath::projectFolder).toUnixStyle();
}
}
else if (availableUserModules != nullptr)
{
auto moduleRoot = availableUserModules->getModuleWithID (moduleID).second.getParentDirectory();
if (isTemp)
return moduleRoot.getFullPathName();
return build_tools::RelativePath (moduleRoot,
outputDirectory,
build_tools::RelativePath::projectFolder).toUnixStyle();
}
return {};
}
File PIPGenerator::getExamplesDirectory() const
{
if (juceModulesPath != File())
{
auto examples = juceModulesPath.getSiblingFile ("examples");
if (isValidJUCEExamplesDirectory (examples))
return examples;
}
auto examples = File (getAppSettings().getStoredPath (Ids::jucePath, TargetOS::getThisOS()).get().toString()).getChildFile ("examples");
if (isValidJUCEExamplesDirectory (examples))
return examples;
return {};
}
@@ -0,0 +1,87 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "../Helpers/jucer_MiscUtilities.h"
#include "../../Project/Modules/jucer_AvailableModulesList.h"
//==============================================================================
class PIPGenerator
{
public:
PIPGenerator (const File& pipFile, const File& outputDirectory = {},
const File& pathToJUCEModules = {}, const File& pathToUserModules = {});
//==============================================================================
bool hasValidPIP() const noexcept { return ! metadata[Ids::name].toString().isEmpty(); }
File getJucerFile() const noexcept { return outputDirectory.getChildFile (metadata[Ids::name].toString() + ".jucer"); }
File getPIPFile() const noexcept { return useLocalCopy ? outputDirectory.getChildFile ("Source").getChildFile (pipFile.getFileName()) : pipFile; }
String getMainClassName() const noexcept { return metadata[Ids::mainClass]; }
File getOutputDirectory() const noexcept { return outputDirectory; }
//==============================================================================
Result createJucerFile();
Result createMainCpp();
private:
//==============================================================================
void addFileToTree (ValueTree& groupTree, const String& name, bool compile, const String& path);
void createFiles (ValueTree& jucerTree);
String getDocumentControllerClass() const;
ValueTree createModulePathChild (const String& moduleID);
ValueTree createBuildConfigChild (bool isDebug);
ValueTree createExporterChild (const Identifier& exporterIdentifier);
ValueTree createModuleChild (const String& moduleID);
void addExporters (ValueTree& jucerTree);
void addModules (ValueTree& jucerTree);
Result setProjectSettings (ValueTree& jucerTree);
void setModuleFlags (ValueTree& jucerTree);
String getMainFileTextForType();
//==============================================================================
Array<File> replaceRelativeIncludesAndGetFilesToMove();
bool copyRelativeFileToLocalSourceDirectory (const File&) const noexcept;
StringArray getExtraPluginFormatsToBuild() const;
String getPathForModule (const String&) const;
File getExamplesDirectory() const;
//==============================================================================
File pipFile, outputDirectory, juceModulesPath, userModulesPath;
std::unique_ptr<AvailableModulesList> availableUserModules;
var metadata;
bool isTemp = false, useLocalCopy = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PIPGenerator)
};
@@ -0,0 +1,224 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
struct ColourPropertyComponent final : public PropertyComponent
{
ColourPropertyComponent (UndoManager* undoManager, const String& name, const Value& colour,
Colour defaultColour, bool canResetToDefault)
: PropertyComponent (name),
colourEditor (undoManager, colour, defaultColour, canResetToDefault)
{
addAndMakeVisible (colourEditor);
}
void resized() override
{
colourEditor.setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this));
}
void refresh() override {}
private:
/**
A component that shows a colour swatch with hex ARGB value, and which pops up
a colour selector when you click it.
*/
struct ColourEditorComponent final : public Component,
private Value::Listener
{
ColourEditorComponent (UndoManager* um, const Value& colour,
Colour defaultCol, const bool canReset)
: undoManager (um), colourValue (colour), defaultColour (defaultCol),
canResetToDefault (canReset)
{
colourValue.addListener (this);
}
void paint (Graphics& g) override
{
const Colour colour (getColour());
g.fillAll (Colours::grey);
g.fillCheckerBoard (getLocalBounds().reduced (2).toFloat(),
10.0f, 10.0f,
Colour (0xffdddddd).overlaidWith (colour),
Colour (0xffffffff).overlaidWith (colour));
g.setColour (Colours::white.overlaidWith (colour).contrasting());
g.setFont (Font ((float) getHeight() * 0.6f, Font::bold));
g.drawFittedText (colour.toDisplayString (true), getLocalBounds().reduced (2, 1),
Justification::centred, 1);
}
Colour getColour() const
{
if (colourValue.toString().isEmpty())
return defaultColour;
return Colour::fromString (colourValue.toString());
}
void setColour (Colour newColour)
{
if (getColour() != newColour)
{
if (newColour == defaultColour && canResetToDefault)
colourValue = var();
else
colourValue = newColour.toDisplayString (true);
}
}
void resetToDefault()
{
setColour (defaultColour);
}
void refresh()
{
const Colour col (getColour());
if (col != lastColour)
{
lastColour = col;
repaint();
}
}
void mouseDown (const MouseEvent&) override
{
if (undoManager != nullptr)
undoManager->beginNewTransaction();
CallOutBox::launchAsynchronously (std::make_unique<PopupColourSelector> (colourValue,
defaultColour,
canResetToDefault),
getScreenBounds(),
nullptr);
}
private:
void valueChanged (Value&) override
{
refresh();
}
UndoManager* undoManager;
Value colourValue;
Colour lastColour;
const Colour defaultColour;
const bool canResetToDefault;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourEditorComponent)
};
//==============================================================================
struct PopupColourSelector final : public Component,
private ChangeListener,
private Value::Listener
{
PopupColourSelector (const Value& colour,
Colour defaultCol,
const bool canResetToDefault)
: defaultButton ("Reset to Default"),
colourValue (colour),
defaultColour (defaultCol)
{
addAndMakeVisible (selector);
selector.setName ("Colour");
selector.setCurrentColour (getColour());
selector.addChangeListener (this);
if (canResetToDefault)
{
addAndMakeVisible (defaultButton);
defaultButton.onClick = [this]
{
setColour (defaultColour);
selector.setCurrentColour (defaultColour);
};
}
colourValue.addListener (this);
setSize (300, 400);
}
void resized() override
{
if (defaultButton.isVisible())
{
selector.setBounds (0, 0, getWidth(), getHeight() - 30);
defaultButton.changeWidthToFitText (22);
defaultButton.setTopLeftPosition (10, getHeight() - 26);
}
else
{
selector.setBounds (getLocalBounds());
}
}
Colour getColour() const
{
if (colourValue.toString().isEmpty())
return defaultColour;
return Colour::fromString (colourValue.toString());
}
void setColour (Colour newColour)
{
if (getColour() != newColour)
{
if (newColour == defaultColour && defaultButton.isVisible())
colourValue = var();
else
colourValue = newColour.toDisplayString (true);
}
}
private:
void changeListenerCallback (ChangeBroadcaster*) override
{
if (selector.getCurrentColour() != getColour())
setColour (selector.getCurrentColour());
}
void valueChanged (Value&) override
{
selector.setCurrentColour (getColour());
}
StoredSettings::ColourSelectorWithSwatches selector;
TextButton defaultButton;
Value colourValue;
Colour defaultColour;
};
ColourEditorComponent colourEditor;
};
@@ -0,0 +1,259 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
/** A PropertyComponent for selecting files or folders.
The user may drag files over the property box, enter the path manually and/or click
the '...' button to open a file selection dialog box.
*/
class FilePathPropertyComponent : public PropertyComponent,
public FileDragAndDropTarget,
protected Value::Listener
{
public:
FilePathPropertyComponent (Value valueToControl, const String& propertyName, bool isDir, bool thisOS = true,
const String& wildcardsToUse = "*", const File& relativeRoot = File())
: PropertyComponent (propertyName),
text (valueToControl, propertyName, 1024, false),
isDirectory (isDir), isThisOS (thisOS), wildcards (wildcardsToUse), root (relativeRoot)
{
textValue.referTo (valueToControl);
init();
}
/** Displays a default value when no value is specified by the user. */
FilePathPropertyComponent (ValueTreePropertyWithDefault valueToControl,
const String& propertyName,
bool isDir,
bool thisOS = true,
const String& wildcardsToUse = "*",
const File& relativeRoot = File())
: PropertyComponent (propertyName),
text (valueToControl, propertyName, 1024, false),
isDirectory (isDir), isThisOS (thisOS), wildcards (wildcardsToUse), root (relativeRoot)
{
textValue = valueToControl.getPropertyAsValue();
init();
}
//==============================================================================
void refresh() override {}
void resized() override
{
auto bounds = getLocalBounds();
text.setBounds (bounds.removeFromLeft (jmax (400, bounds.getWidth() - 55)));
bounds.removeFromLeft (5);
browseButton.setBounds (bounds);
}
void paintOverChildren (Graphics& g) override
{
if (highlightForDragAndDrop)
{
g.setColour (findColour (defaultHighlightColourId).withAlpha (0.5f));
g.fillRect (getLookAndFeel().getPropertyComponentContentPosition (text));
}
}
//==============================================================================
bool isInterestedInFileDrag (const StringArray&) override { return true; }
void fileDragEnter (const StringArray&, int, int) override { highlightForDragAndDrop = true; repaint(); }
void fileDragExit (const StringArray&) override { highlightForDragAndDrop = false; repaint(); }
void filesDropped (const StringArray& selectedFiles, int, int) override
{
setTo (selectedFiles[0]);
highlightForDragAndDrop = false;
repaint();
}
protected:
void valueChanged (Value&) override
{
updateEditorColour();
}
private:
//==============================================================================
void init()
{
textValue.addListener (this);
text.setInterestedInFileDrag (false);
addAndMakeVisible (text);
browseButton.onClick = [this] { browse(); };
addAndMakeVisible (browseButton);
updateLookAndFeel();
}
void setTo (File f)
{
if (isDirectory && ! f.isDirectory())
f = f.getParentDirectory();
auto pathName = (root == File()) ? f.getFullPathName()
: f.getRelativePathFrom (root);
text.setText (pathName);
updateEditorColour();
}
void browse()
{
File currentFile = {};
if (text.getText().isNotEmpty())
currentFile = root.getChildFile (text.getText());
if (isDirectory)
{
chooser = std::make_unique<FileChooser> ("Select directory", currentFile);
auto chooserFlags = FileBrowserComponent::openMode | FileBrowserComponent::canSelectDirectories;
chooser->launchAsync (chooserFlags, [this] (const FileChooser& fc)
{
if (fc.getResult() == File{})
return;
setTo (fc.getResult());
});
}
else
{
chooser = std::make_unique<FileChooser> ("Select file", currentFile, wildcards);
auto chooserFlags = FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles;
chooser->launchAsync (chooserFlags, [this] (const FileChooser& fc)
{
if (fc.getResult() == File{})
return;
setTo (fc.getResult());
});
}
}
void updateEditorColour()
{
if (isThisOS)
{
text.setColour (TextPropertyComponent::textColourId, findColour (widgetTextColourId));
auto pathToCheck = text.getText();
if (pathToCheck.isNotEmpty())
{
pathToCheck.replace ("${user.home}", "~");
#if JUCE_WINDOWS
if (pathToCheck.startsWith ("~"))
pathToCheck = pathToCheck.replace ("~", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());
#endif
if (! root.getChildFile (pathToCheck).exists())
text.setColour (TextPropertyComponent::textColourId, Colours::red);
}
}
}
void updateLookAndFeel()
{
browseButton.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId));
browseButton.setColour (TextButton::textColourOffId, Colours::white);
updateEditorColour();
}
void lookAndFeelChanged() override
{
updateLookAndFeel();
}
//==============================================================================
Value textValue;
TextPropertyComponent text;
TextButton browseButton { "..." };
bool isDirectory, isThisOS, highlightForDragAndDrop = false;
String wildcards;
File root;
std::unique_ptr<FileChooser> chooser;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilePathPropertyComponent)
};
//==============================================================================
class FilePathPropertyComponentWithEnablement final : public FilePathPropertyComponent
{
public:
FilePathPropertyComponentWithEnablement (const ValueTreePropertyWithDefault& valueToControl,
ValueTreePropertyWithDefault valueToListenTo,
const String& propertyName,
bool isDir,
bool thisOS = true,
const String& wildcardsToUse = "*",
const File& relativeRoot = File())
: FilePathPropertyComponent (valueToControl,
propertyName,
isDir,
thisOS,
wildcardsToUse,
relativeRoot),
propertyWithDefault (valueToListenTo),
value (valueToListenTo.getPropertyAsValue())
{
value.addListener (this);
handleValueChanged (value);
}
~FilePathPropertyComponentWithEnablement() override { value.removeListener (this); }
private:
void handleValueChanged (Value& v)
{
FilePathPropertyComponent::valueChanged (v);
setEnabled (propertyWithDefault.get());
}
void valueChanged (Value& v) override
{
handleValueChanged (v);
}
ValueTreePropertyWithDefault propertyWithDefault;
Value value;
};
@@ -0,0 +1,73 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
class LabelPropertyComponent final : public PropertyComponent
{
public:
LabelPropertyComponent (const String& labelText, int propertyHeight = 25,
Font labelFont = Font (16.0f, Font::bold),
Justification labelJustification = Justification::centred)
: PropertyComponent (labelText),
labelToDisplay ({}, labelText)
{
setPreferredHeight (propertyHeight);
labelToDisplay.setJustificationType (labelJustification);
labelToDisplay.setFont (labelFont);
addAndMakeVisible (labelToDisplay);
setLookAndFeel (&lf);
}
~LabelPropertyComponent() override { setLookAndFeel (nullptr); }
//==============================================================================
void refresh() override {}
void resized() override
{
labelToDisplay.setBounds (getLocalBounds());
}
private:
//==============================================================================
struct LabelLookAndFeel final : public ProjucerLookAndFeel
{
void drawPropertyComponentLabel (Graphics&, int, int, PropertyComponent&) override {}
};
void lookAndFeelChanged() override
{
labelToDisplay.setColour (Label::textColourId, ProjucerApplication::getApp().lookAndFeel.findColour (defaultTextColourId));
}
//==============================================================================
LabelLookAndFeel lf;
Label labelToDisplay;
};
@@ -0,0 +1,165 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
class TextPropertyComponentWithEnablement final : public TextPropertyComponent,
private Value::Listener
{
public:
TextPropertyComponentWithEnablement (const ValueTreePropertyWithDefault& valueToControl,
ValueTreePropertyWithDefault valueToListenTo,
const String& propertyName,
int maxNumChars,
bool multiLine)
: TextPropertyComponent (valueToControl, propertyName, maxNumChars, multiLine),
propertyWithDefault (valueToListenTo),
value (propertyWithDefault.getPropertyAsValue())
{
value.addListener (this);
setEnabled (propertyWithDefault.get());
}
~TextPropertyComponentWithEnablement() override { value.removeListener (this); }
private:
ValueTreePropertyWithDefault propertyWithDefault;
Value value;
void valueChanged (Value&) override { setEnabled (propertyWithDefault.get()); }
};
//==============================================================================
class ChoicePropertyComponentWithEnablement final : public ChoicePropertyComponent,
private Value::Listener
{
public:
ChoicePropertyComponentWithEnablement (const ValueTreePropertyWithDefault& valueToControl,
ValueTreePropertyWithDefault valueToListenTo,
const String& propertyName,
const StringArray& choiceToUse,
const Array<var>& correspondingValues)
: ChoicePropertyComponent (valueToControl, propertyName, choiceToUse, correspondingValues),
propertyWithDefault (valueToListenTo),
value (valueToListenTo.getPropertyAsValue())
{
value.addListener (this);
handleValueChanged();
}
ChoicePropertyComponentWithEnablement (const ValueTreePropertyWithDefault& valueToControl,
ValueTreePropertyWithDefault valueToListenTo,
const Identifier& multiChoiceID,
const String& propertyName,
const StringArray& choicesToUse,
const Array<var>& correspondingValues)
: ChoicePropertyComponentWithEnablement (valueToControl, valueToListenTo, propertyName, choicesToUse, correspondingValues)
{
jassert (valueToListenTo.get().getArray() != nullptr);
isMultiChoice = true;
idToCheck = multiChoiceID;
handleValueChanged();
}
ChoicePropertyComponentWithEnablement (const ValueTreePropertyWithDefault& valueToControl,
ValueTreePropertyWithDefault valueToListenTo,
const String& propertyName)
: ChoicePropertyComponent (valueToControl, propertyName),
propertyWithDefault (valueToListenTo),
value (valueToListenTo.getPropertyAsValue())
{
value.addListener (this);
handleValueChanged();
}
~ChoicePropertyComponentWithEnablement() override { value.removeListener (this); }
private:
ValueTreePropertyWithDefault propertyWithDefault;
Value value;
bool isMultiChoice = false;
Identifier idToCheck;
bool checkMultiChoiceVar() const
{
jassert (isMultiChoice);
auto v = propertyWithDefault.get();
if (auto* varArray = v.getArray())
return varArray->contains (idToCheck.toString());
jassertfalse;
return false;
}
void handleValueChanged()
{
if (isMultiChoice)
setEnabled (checkMultiChoiceVar());
else
setEnabled (propertyWithDefault.get());
}
void valueChanged (Value&) override
{
handleValueChanged();
}
};
//==============================================================================
class MultiChoicePropertyComponentWithEnablement final : public MultiChoicePropertyComponent,
private Value::Listener
{
public:
MultiChoicePropertyComponentWithEnablement (const ValueTreePropertyWithDefault& valueToControl,
ValueTreePropertyWithDefault valueToListenTo,
const String& propertyName,
const StringArray& choices,
const Array<var>& correspondingValues)
: MultiChoicePropertyComponent (valueToControl,
propertyName,
choices,
correspondingValues),
propertyWithDefault (valueToListenTo),
value (valueToListenTo.getPropertyAsValue())
{
value.addListener (this);
valueChanged (value);
}
~MultiChoicePropertyComponentWithEnablement() override { value.removeListener (this); }
private:
void valueChanged (Value&) override { setEnabled (propertyWithDefault.get()); }
ValueTreePropertyWithDefault propertyWithDefault;
Value value;
};
@@ -0,0 +1,136 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
class IconButton final : public Button
{
public:
IconButton (String buttonName, Image imageToDisplay)
: Button (buttonName),
iconImage (imageToDisplay)
{
setTooltip (buttonName);
}
IconButton (String buttonName, Path pathToDisplay)
: Button (buttonName),
iconPath (pathToDisplay),
iconImage (createImageFromPath (iconPath))
{
setTooltip (buttonName);
}
void setImage (Image newImage)
{
iconImage = newImage;
repaint();
}
void setPath (Path newPath)
{
iconImage = createImageFromPath (newPath);
repaint();
}
void setBackgroundColour (Colour backgroundColourToUse)
{
backgroundColour = backgroundColourToUse;
usingNonDefaultBackgroundColour = true;
}
void setIconInset (int newIconInset)
{
iconInset = newIconInset;
repaint();
}
void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) override
{
float alpha = 1.0f;
if (! isEnabled())
{
isMouseOverButton = false;
isButtonDown = false;
alpha = 0.2f;
}
auto fill = isButtonDown ? backgroundColour.darker (0.5f)
: isMouseOverButton ? backgroundColour.darker (0.2f)
: backgroundColour;
auto bounds = getLocalBounds();
if (isButtonDown)
bounds.reduce (2, 2);
Path ellipse;
ellipse.addEllipse (bounds.toFloat());
g.reduceClipRegion (ellipse);
g.setColour (fill.withAlpha (alpha));
g.fillAll();
g.setOpacity (alpha);
g.drawImage (iconImage, bounds.reduced (iconInset).toFloat(), RectanglePlacement::fillDestination, false);
}
private:
void lookAndFeelChanged() override
{
if (! usingNonDefaultBackgroundColour)
backgroundColour = findColour (defaultButtonBackgroundColourId);
if (iconPath != Path())
iconImage = createImageFromPath (iconPath);
repaint();
}
Image createImageFromPath (Path path)
{
Image image (Image::ARGB, 250, 250, true);
Graphics g (image);
g.setColour (findColour (defaultIconColourId));
g.fillPath (path, RectanglePlacement (RectanglePlacement::centred)
.getTransformToFit (path.getBounds(), image.getBounds().toFloat()));
return image;
}
Path iconPath;
Image iconImage;
Colour backgroundColour { findColour (defaultButtonBackgroundColourId) };
bool usingNonDefaultBackgroundColour = false;
int iconInset = 2;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IconButton)
};
@@ -0,0 +1,658 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "../../Application/jucer_Application.h"
#include "jucer_Icons.h"
const Icons& getIcons()
{
return *ProjucerApplication::getApp().icons;
}
namespace IconPathData
{
const uint8 imageDoc[] = { 110,109,255,255,249,67,255,255,249,67,108,0,0,0,0,255,255,249,67,108,0,0,0,0,0,0,0,0,108,255,255,249,67,0,0,0,0,108,255,255,249,67,255,255,249,67,99,109,72,62,243,66,56,152,66,67,98,158,117,31,67,56,152,66,67,82,228,63,67,132,41,34,67,82,228,63,67,12,
166,248,66,98,82,228,63,67,20,249,172,66,158,117,31,67,84,55,88,66,68,62,243,66,84,55,88,66,98,76,145,167,66,84,55,88,66,192,103,77,66,16,249,172,66,192,103,77,66,12,166,248,66,98,200,103,77,66,132,41,34,67,132,41,162,66,56,152,66,67,72,62,243,66,56,
152,66,67,99,109,137,124,236,67,221,96,128,67,108,49,69,170,67,12,166,248,66,108,214,13,26,67,200,103,155,67,108,0,0,200,66,221,96,128,67,108,56,152,194,65,89,55,166,67,108,56,152,194,65,137,124,236,67,108,153,34,235,67,137,124,236,67,108,153,34,235,
67,221,96,128,67,99,101,0,0 };
const uint8 config[] = { 110,109,149,118,142,67,134,71,167,67,108,59,28,135,67,149,118,142,67,98,210,242,136,67,254,159,140,67,104,201,138,67,104,201,138,67,255,159,140,67,209,242,136,67,108,240,112,165,67,43,77,144,67,98,210,50,168,67,254,159,140,67,105,9,170,67,134,7,136,67,
74,203,172,67,89,90,132,67,108,104,105,154,67,238,240,99,67,98,180,84,155,67,42,109,94,67,255,63,156,67,102,233,88,67,255,63,156,67,162,101,83,67,108,240,16,181,67,134,135,70,67,98,240,16,181,67,194,3,65,67,240,16,181,67,148,86,61,67,240,16,181,67,208,
210,55,67,98,240,16,181,67,12,79,50,67,240,16,181,67,224,161,46,67,240,16,181,67,28,30,41,67,108,255,63,156,67,254,63,28,67,98,180,84,155,67,58,188,22,67,180,84,155,67,118,56,17,67,104,105,154,67,178,180,11,67,108,74,203,172,67,223,225,205,66,98,179,
244,170,67,253,127,187,66,210,50,168,67,72,203,172,66,240,112,165,67,147,22,158,66,108,255,159,140,67,253,127,187,66,98,104,201,138,67,163,37,180,66,210,242,136,67,72,203,172,66,59,28,135,67,238,112,165,66,108,149,118,142,67,86,90,4,66,98,104,201,138,
67,144,150,220,65,239,48,134,67,40,45,191,65,195,131,130,67,8,15,147,65,108,195,67,96,67,146,150,92,66,98,255,191,90,67,56,60,85,66,59,60,85,67,222,225,77,66,120,184,79,67,222,225,77,66,108,90,218,66,67,0,75,235,63,98,150,86,61,67,0,75,235,63,105,169,
57,67,0,75,235,63,165,37,52,67,0,75,235,63,98,225,161,46,67,0,75,235,63,180,244,42,67,0,75,235,63,240,112,37,67,0,75,235,63,108,211,146,24,67,222,225,77,66,98,15,15,19,67,56,60,85,66,75,139,13,67,56,60,85,66,136,7,8,67,146,150,92,66,108,136,135,198,66,
8,15,147,65,98,254,127,187,66,44,45,191,65,74,203,172,66,152,150,220,65,148,22,158,66,90,90,4,66,108,254,127,187,66,240,112,165,66,98,118,120,176,66,75,203,172,66,28,30,169,66,165,37,180,66,194,195,161,66,45,45,191,66,108,250,255,249,65,195,195,161,66,
98,222,225,205,65,119,120,176,66,116,120,176,65,45,45,191,66,86,90,132,65,15,143,209,66,108,59,60,85,66,74,139,13,67,98,225,225,77,66,14,15,19,67,135,135,70,66,210,146,24,67,135,135,70,66,148,22,30,67,108,0,0,0,0,178,244,42,67,98,0,0,0,0,118,120,48,67,
0,0,0,0,164,37,52,67,0,0,0,0,104,169,57,67,98,0,0,0,0,44,45,63,67,0,0,0,0,88,218,66,67,0,0,0,0,28,94,72,67,108,135,135,70,66,58,60,85,67,98,225,225,77,66,254,191,90,67,225,225,77,66,194,67,96,67,59,60,85,66,134,199,101,67,108,88,90,132,65,164,69,133,
67,98,194,195,161,65,29,222,137,67,224,225,205,65,74,139,141,67,254,255,249,65,119,56,145,67,108,194,195,161,66,29,222,137,67,98,28,30,169,66,180,180,139,67,120,120,176,66,74,139,141,67,210,210,183,66,225,97,143,67,108,104,105,154,66,210,50,168,67,98,
28,30,169,66,179,244,170,67,254,127,187,66,74,203,172,67,178,52,202,66,44,141,175,67,108,29,222,9,67,74,43,157,67,98,225,97,15,67,150,22,158,67,165,229,20,67,225,1,159,67,103,105,26,67,225,1,159,67,108,133,71,39,67,210,210,183,67,98,73,203,44,67,210,
210,183,67,118,120,48,67,210,210,183,67,58,252,53,67,210,210,183,67,98,254,127,59,67,210,210,183,67,43,45,63,67,210,210,183,67,239,176,68,67,210,210,183,67,108,13,143,81,67,225,1,159,67,98,209,18,87,67,150,22,158,67,148,150,92,67,150,22,158,67,87,26,
98,67,74,43,157,67,108,13,111,131,67,44,141,175,67,98,239,48,134,67,255,223,171,67,104,201,138,67,105,9,170,67,149,118,142,67,134,71,167,67,99,109,59,252,53,67,210,82,118,67,98,15,15,19,67,210,82,118,67,118,248,238,66,0,192,90,67,118,248,238,66,210,210,
55,67,98,118,248,238,66,166,229,20,67,13,15,19,67,167,165,242,66,58,252,53,67,167,165,242,66,98,102,233,88,67,167,165,242,66,57,124,116,67,166,229,20,67,57,124,116,67,210,210,55,67,98,57,124,116,67,0,192,90,67,104,233,88,67,210,82,118,67,59,252,53,67,
210,82,118,67,99,109,178,116,233,67,75,107,188,67,98,178,116,233,67,210,210,183,67,103,137,232,67,14,79,178,67,27,158,231,67,74,203,172,67,108,163,165,242,67,0,64,156,67,98,11,207,240,67,211,146,152,67,117,248,238,67,240,208,149,67,223,33,237,67,15,15,
147,67,108,178,212,217,67,60,188,150,67,98,133,39,214,67,15,15,147,67,12,143,209,67,120,56,145,67,148,246,204,67,150,118,142,67,108,208,114,199,67,210,82,118,67,98,163,197,195,67,60,124,116,67,118,24,192,67,60,124,116,67,72,107,188,67,60,124,116,67,108,
87,58,179,67,180,180,139,67,98,118,120,176,67,255,159,140,67,147,182,173,67,255,159,140,67,253,223,171,67,75,139,141,67,98,28,30,169,67,150,118,142,67,133,71,167,67,226,97,143,67,238,112,165,67,120,56,145,67,108,194,35,146,67,180,180,139,67,98,224,97,
143,67,149,118,142,67,254,159,140,67,44,77,144,67,104,201,138,67,89,250,147,67,108,13,15,147,67,59,92,166,67,98,44,77,144,67,179,244,170,67,224,97,143,67,44,141,175,67,149,118,142,67,240,16,181,67,108,255,255,121,67,44,45,191,67,98,255,255,121,67,89,
218,194,67,149,214,123,67,134,135,198,67,43,173,125,67,180,52,202,67,108,194,35,146,67,44,205,206,67,98,89,250,147,67,165,101,211,67,58,188,150,67,29,254,215,67,103,105,154,67,74,171,219,67,108,58,188,150,67,120,248,238,67,98,28,126,153,67,14,207,240,
67,74,43,157,67,164,165,242,67,43,237,159,67,60,124,244,67,108,43,141,175,67,105,137,232,67,98,164,37,180,67,181,116,233,67,104,169,185,67,0,96,234,67,44,45,191,67,0,96,234,67,108,149,246,204,67,182,20,249,67,98,44,205,206,67,106,41,248,67,194,163,208,
67,106,41,248,67,89,122,210,67,30,62,247,67,98,240,80,212,67,210,82,246,67,58,60,213,67,210,82,246,67,209,18,215,67,136,103,245,67,108,209,18,215,67,14,47,225,67,98,74,171,219,67,45,109,222,67,43,109,222,67,255,191,218,67,89,26,226,67,134,39,214,67,108,
211,82,246,67,59,60,213,67,98,105,41,248,67,14,143,209,67,179,20,249,67,43,205,206,67,255,255,249,67,254,31,203,67,108,178,116,233,67,75,107,188,67,99,109,89,218,194,67,44,205,206,67,98,209,210,183,67,165,101,211,67,254,223,171,67,225,225,205,67,134,
71,167,67,90,218,194,67,98,14,175,162,67,211,210,183,67,210,50,168,67,0,224,171,67,88,58,179,67,136,71,167,67,98,224,65,190,67,15,175,162,67,178,52,202,67,211,50,168,67,43,205,206,67,90,58,179,67,98,163,101,211,67,225,65,190,67,223,225,205,67,180,52,
202,67,89,218,194,67,44,205,206,67,99,101,0,0 };
const uint8 graph[] = { 110,109,166,158,186,66,184,11,143,67,108,113,151,95,67,98,243,92,67,108,113,151,95,67,228,55,54,67,108,206,129,81,67,228,55,54,67,98,253,118,74,67,228,55,54,67,44,108,67,67,47,117,52,67,91,97,60,67,123,178,50,67,108,91,97,60,67,239,210,71,67,108,245,
100,104,66,127,123,132,67,108,245,100,104,66,181,2,158,67,108,166,158,186,66,181,2,158,67,108,166,158,186,66,184,11,143,67,99,109,97,243,220,67,180,2,158,67,108,97,243,220,67,126,123,132,67,108,83,207,155,67,238,210,71,67,108,83,207,155,67,122,178,50,
67,98,235,73,152,67,227,55,54,67,130,196,148,67,227,55,54,67,25,63,145,67,227,55,54,67,108,72,52,138,67,227,55,54,67,108,72,52,138,67,97,243,92,67,108,87,88,203,67,184,11,143,67,108,87,88,203,67,181,2,158,67,108,97,243,220,67,181,2,158,67,99,109,133,
205,133,67,180,2,158,67,108,133,205,133,67,150,250,55,67,108,247,100,104,67,150,250,55,67,108,247,100,104,67,180,2,158,67,108,133,205,133,67,180,2,158,67,99,109,245,100,232,67,57,208,166,67,108,194,230,191,67,57,208,166,67,98,226,55,182,67,57,208,166,
67,183,75,174,67,100,188,174,67,183,75,174,67,68,107,184,67,108,183,75,174,67,119,233,224,67,98,183,75,174,67,87,152,234,67,226,55,182,67,130,132,242,67,194,230,191,67,130,132,242,67,108,245,100,232,67,130,132,242,67,98,213,19,242,67,130,132,242,67,255,
255,249,67,87,152,234,67,255,255,249,67,119,233,224,67,108,255,255,249,67,68,107,184,67,98,255,255,249,67,100,188,174,67,213,19,242,67,57,208,166,67,245,100,232,67,57,208,166,67,99,109,246,100,232,66,57,208,166,67,108,83,216,12,66,57,208,166,67,98,92,
133,125,65,57,208,166,67,0,0,128,183,100,188,174,67,0,0,128,183,68,107,184,67,108,0,0,128,183,119,233,224,67,98,0,0,128,183,87,152,234,67,92,133,125,65,130,132,242,67,83,216,12,66,130,132,242,67,108,246,100,232,66,130,132,242,67,98,58,144,7,67,130,132,
242,67,144,104,23,67,87,152,234,67,144,104,23,67,119,233,224,67,108,144,104,23,67,68,107,184,67,98,144,104,23,67,100,188,174,67,57,144,7,67,57,208,166,67,246,100,232,66,57,208,166,67,99,109,205,129,81,67,139,95,38,67,108,25,63,145,67,139,95,38,67,98,
249,237,154,67,139,95,38,67,36,218,162,67,53,135,22,67,36,218,162,67,118,41,3,67,108,36,218,162,67,68,180,72,66,98,36,218,162,67,139,122,246,65,249,237,154,67,176,111,111,65,25,63,145,67,176,111,111,65,108,205,129,81,67,176,111,111,65,98,13,36,62,67,
176,111,111,65,183,75,46,67,139,122,246,65,183,75,46,67,68,180,72,66,108,183,75,46,67,118,41,3,67,98,183,75,46,67,53,135,22,67,15,36,62,67,139,95,38,67,205,129,81,67,139,95,38,67,99,109,25,63,145,67,57,208,166,67,108,205,129,81,67,57,208,166,67,98,13,
36,62,67,57,208,166,67,183,75,46,67,100,188,174,67,183,75,46,67,68,107,184,67,108,183,75,46,67,119,233,224,67,98,183,75,46,67,87,152,234,67,13,36,62,67,130,132,242,67,205,129,81,67,130,132,242,67,108,25,63,145,67,130,132,242,67,98,249,237,154,67,130,
132,242,67,36,218,162,67,87,152,234,67,36,218,162,67,119,233,224,67,108,36,218,162,67,68,107,184,67,98,36,218,162,67,100,188,174,67,249,237,154,67,57,208,166,67,25,63,145,67,57,208,166,67,99,101,0,0 };
const uint8 info[] = { 110,109,0,0,122,67,0,0,0,0,98,79,35,224,66,0,0,0,0,0,0,0,0,79,35,224,66,0,0,0,0,0,0,122,67,98,0,0,0,0,44,247,193,67,79,35,224,66,0,0,250,67,0,0,122,67,0,0,250,67,98,44,247,193,67,0,0,250,67,0,0,250,67,44,247,193,67,0,0,250,67,0,0,122,67,98,0,0,250,67,
79,35,224,66,44,247,193,67,0,0,0,0,0,0,122,67,0,0,0,0,99,109,114,79,101,67,79,35,224,66,108,71,88,135,67,79,35,224,66,108,71,88,135,67,132,229,28,67,108,116,79,101,67,132,229,28,67,108,116,79,101,67,79,35,224,66,99,109,79,35,149,67,106,132,190,67,108,
98,185,123,67,106,132,190,67,98,150,123,106,67,106,132,190,67,176,220,97,67,168,17,187,67,176,220,97,67,18,150,177,67,108,176,220,97,67,248,52,108,67,98,176,220,97,67,212,8,103,67,238,105,94,67,18,150,99,67,204,61,89,67,18,150,99,67,108,98,185,73,67,
18,150,99,67,108,98,185,73,67,88,238,59,67,108,160,70,120,67,88,238,59,67,98,54,194,132,67,88,238,59,67,169,17,137,67,60,141,68,67,169,17,137,67,8,203,85,67,108,169,17,137,67,26,97,166,67,98,169,17,137,67,43,247,168,67,10,203,138,67,141,176,170,67,27,
97,141,67,141,176,170,67,108,80,35,149,67,141,176,170,67,108,80,35,149,67,106,132,190,67,99,101,0,0 };
const uint8 warning[] = { 110,109,211,238,239,67,40,5,203,67,108,193,13,208,67,108,125,148,67,98,86,211,198,67,31,182,131,67,204,226,182,67,70,187,81,67,98,168,173,67,172,44,48,67,108,79,199,141,67,106,58,134,66,98,228,140,132,67,104,58,6,66,182,56,105,67,104,58,6,66,225,195,
86,67,106,58,134,66,108,185,1,23,67,171,44,48,67,98,228,140,4,67,69,187,81,67,161,87,201,66,30,182,131,67,247,109,164,66,108,125,148,67,108,170,166,147,65,40,5,203,67,98,0,0,0,0,118,204,219,67,89,156,113,65,180,56,233,67,222,195,86,66,180,56,233,67,108,
133,39,223,67,180,56,233,67,98,90,156,241,67,180,56,233,67,1,0,250,67,178,245,218,67,211,238,239,67,40,5,203,67,99,109,167,99,133,67,206,104,211,67,108,165,221,101,67,206,104,211,67,108,165,221,101,67,248,243,192,67,108,167,99,133,67,248,243,192,67,108,
167,99,133,67,206,104,211,67,99,109,227,140,132,67,186,135,179,67,108,44,139,103,67,186,135,179,67,108,29,48,100,67,174,178,76,67,108,107,58,134,67,174,178,76,67,108,227,140,132,67,186,135,179,67,99,101,0,0 };
const uint8 user[] = { 110,109,0,0,128,65,0,0,160,65,98,0,0,128,65,0,0,112,65,68,177,70,65,0,0,48,65,0,0,0,65,0,0,48,65,98,238,58,101,64,0,0,48,65,0,0,0,0,0,0,120,65,0,0,0,0,0,0,160,65,108,0,0,128,65,0,0,160,65,99,109,0,0,80,65,0,0,160,64,108,0,0,80,65,0,0,160,64,108,104,230,
79,65,38,255,167,64,108,176,153,79,65,45,249,175,64,108,8,26,79,65,251,232,183,64,108,196,103,78,65,125,201,191,64,108,84,131,77,65,168,149,199,64,108,75,109,76,65,128,72,207,64,108,91,38,75,65,21,221,214,64,108,85,175,73,65,144,78,222,64,108,40,9,72,
65,46,152,229,64,108,229,52,70,65,66,181,236,64,108,180,51,68,65,66,161,243,64,108,225,6,66,65,190,87,250,64,108,205,175,63,65,54,106,0,65,108,250,47,61,65,146,137,3,65,108,255,136,58,65,244,135,6,65,108,144,188,55,65,114,99,9,65,108,119,204,52,65,54,
26,12,65,108,150,186,49,65,135,170,14,65,108,226,136,46,65,190,18,17,65,108,104,57,43,65,81,81,19,65,108,69,206,39,65,210,100,21,65,108,170,73,36,65,235,75,23,65,108,215,173,32,65,102,5,25,65,108,27,253,28,65,39,144,26,65,108,210,57,25,65,50,235,27,65,
108,102,102,21,65,170,21,29,65,108,72,133,17,65,207,14,30,65,108,243,152,13,65,2,214,30,65,108,236,163,9,65,194,106,31,65,108,185,168,5,65,178,204,31,65,108,232,169,1,65,146,251,31,65,108,255,255,255,64,0,0,32,65,108,0,0,0,65,0,0,32,65,108,255,255,255,
64,0,0,32,65,108,218,0,248,64,104,230,31,65,108,211,6,240,64,176,153,31,65,108,4,23,232,64,8,26,31,65,108,130,54,224,64,196,103,30,65,108,87,106,216,64,84,131,29,65,108,128,183,208,64,75,109,28,65,108,234,34,201,64,91,38,27,65,108,112,177,193,64,85,175,
25,65,108,211,103,186,64,41,9,24,65,108,190,74,179,64,229,52,22,65,108,191,94,172,64,181,51,20,65,108,67,168,165,64,225,6,18,65,108,149,43,159,64,206,175,15,65,108,220,236,152,64,250,47,13,65,108,24,240,146,64,255,136,10,65,108,29,57,141,64,144,188,7,
65,108,147,203,135,64,119,204,4,65,108,242,170,130,64,149,186,1,65,108,4,181,123,64,192,17,253,64,108,180,186,114,64,202,114,246,64,108,176,108,106,64,130,156,239,64,108,72,208,98,64,74,147,232,64,108,92,234,91,64,161,91,225,64,108,86,191,85,64,38,250,
217,64,108,40,83,80,64,146,115,210,64,108,76,169,75,64,182,204,202,64,108,184,196,71,64,120,10,195,64,108,240,167,68,64,204,49,187,64,108,240,84,66,64,187,71,179,64,108,52,205,64,64,83,81,171,64,108,182,17,64,64,173,83,163,64,108,0,0,64,64,0,0,160,64,
108,0,0,64,64,0,0,160,64,108,0,0,64,64,0,0,160,64,108,96,102,64,64,216,0,152,64,108,68,153,65,64,207,6,144,64,108,226,151,67,64,254,22,136,64,108,246,96,70,64,121,54,128,64,108,182,242,73,64,152,212,112,64,108,220,74,78,64,229,110,97,64,108,160,102,83,
64,181,69,82,64,108,188,66,89,64,188,98,67,64,108,112,219,95,64,127,207,52,64,108,130,44,103,64,82,149,38,64,108,72,49,111,64,80,189,24,64,108,156,228,119,64,85,80,11,64,108,120,160,128,64,240,173,252,63,108,34,160,133,64,8,179,227,63,108,27,238,138,
64,246,191,203,63,108,252,134,144,64,8,228,180,63,108,48,103,150,64,220,45,159,63,108,248,138,156,64,94,171,138,63,108,98,238,162,64,80,211,110,63,108,90,141,169,64,32,234,74,63,108,162,99,176,64,32,178,41,63,108,220,108,183,64,144,64,11,63,108,133,164,
190,64,224,81,223,62,108,0,6,198,64,192,249,173,62,108,149,140,205,64,112,152,130,62,108,114,51,213,64,64,147,58,62,108,177,245,220,64,0,149,248,61,108,93,206,228,64,64,252,148,61,108,111,184,236,64,128,57,21,61,108,215,174,244,64,0,44,77,60,108,125,
172,252,64,0,160,141,58,108,1,0,0,65,0,0,0,0,108,0,0,0,65,0,0,0,0,108,0,0,0,65,0,0,0,0,108,147,255,3,65,0,192,204,59,108,151,252,7,65,0,161,204,60,108,126,244,11,65,0,248,101,61,108,191,228,15,65,64,30,204,61,108,213,202,19,65,32,43,31,62,108,65,164,
23,65,96,173,100,62,108,140,110,27,65,176,52,155,62,108,74,39,31,65,128,21,202,62,108,24,204,34,65,0,219,254,62,108,163,90,38,65,192,177,28,63,108,163,208,41,65,200,196,60,63,108,225,43,45,65,8,146,95,63,108,56,106,48,65,164,129,130,63,108,148,137,51,
65,70,128,150,63,108,246,135,54,65,28,184,171,63,108,116,99,57,65,152,27,194,63,108,58,26,60,65,96,156,217,63,108,138,170,62,65,112,43,242,63,108,192,18,65,65,136,220,5,64,108,84,81,67,65,113,26,19,64,108,212,100,69,65,252,198,32,64,108,238,75,71,65,
105,217,46,64,108,104,5,73,65,181,72,61,64,108,41,144,74,65,166,11,76,64,108,52,235,75,65,200,24,91,64,108,172,21,77,65,124,102,106,64,108,208,14,78,65,244,234,121,64,108,2,214,78,65,35,206,132,64,108,195,106,79,65,50,184,140,64,108,178,204,79,65,151,
174,148,64,108,146,251,79,65,58,172,156,64,108,0,0,80,65,0,0,160,64,108,0,0,80,65,0,0,160,64,99,101,0,0 };
const uint8 closedFolder[] = { 110,109,0,0,0,65,0,0,0,0,108,0,0,0,65,0,0,128,63,108,0,0,0,65,0,0,0,64,108,0,0,0,0,0,0,0,64,108,0,0,0,0,0,0,96,65,108,0,0,144,65,0,0,96,65,108,0,0,144,65,0,0,0,64,108,0,0,128,65,0,0,0,64,108,0,0,128,65,0,0,0,0,108,0,0,0,65,0,0,0,0,99,101,0,0 };
const uint8 exporter[] = { 110,109,0,120,99,65,0,128,94,63,108,0,40,88,65,0,192,201,63,108,0,232,42,65,0,240,140,64,108,0,80,251,64,0,192,201,63,108,0,128,72,63,0,88,10,65,108,0,192,190,63,0,168,21,65,108,0,32,103,64,0,152,55,65,108,0,128,67,63,0,40,101,65,108,0,0,104,61,0,120,
112,65,108,0,64,188,63,0,140,131,65,108,0,96,11,64,0,200,123,65,108,0,208,160,64,0,56,78,65,108,0,80,251,64,0,128,123,65,108,0,208,110,65,0,88,10,65,108,0,136,65,65,0,48,186,64,108,0,200,110,65,0,96,63,64,108,0,24,122,65,0,32,18,64,108,0,120,99,65,0,
128,94,63,99,109,0,80,251,64,0,240,140,64,108,0,72,20,65,0,48,186,64,108,0,248,19,65,0,208,186,64,108,0,152,42,65,0,16,232,64,108,0,232,42,65,0,112,231,64,108,0,144,65,65,0,88,10,65,108,0,80,251,64,0,56,78,65,108,0,16,206,64,0,152,55,65,108,0,208,160,
64,0,248,32,65,108,0,32,103,64,0,88,10,65,108,0,80,251,64,0,240,140,64,99,101,0,0 };
const uint8 fileExplorer[] = { 110,109,0,0,0,65,0,0,0,0,108,0,0,0,65,0,0,192,64,108,0,0,32,65,0,0,192,64,108,0,0,32,65,0,0,208,64,108,0,0,32,65,0,0,0,65,108,0,0,0,64,0,0,0,65,108,0,0,0,64,0,0,64,65,108,0,0,0,0,0,0,64,65,108,0,0,0,0,0,0,144,65,108,0,0,192,64,0,0,144,65,108,0,0,192,
64,0,0,64,65,108,0,0,128,64,0,0,64,65,108,0,0,128,64,0,0,32,65,108,0,0,32,65,0,0,32,65,108,0,0,32,65,0,0,56,65,108,0,0,32,65,0,0,64,65,108,0,0,0,65,0,0,64,65,108,0,0,0,65,0,0,144,65,108,0,0,96,65,0,0,144,65,108,0,0,96,65,0,0,64,65,108,0,0,64,65,0,0,64,
65,108,0,0,64,65,0,0,56,65,108,0,0,64,65,0,0,32,65,108,0,0,144,65,0,0,32,65,108,0,0,144,65,0,0,56,65,108,0,0,144,65,0,0,64,65,108,0,0,128,65,0,0,64,65,108,0,0,128,65,0,0,144,65,108,0,0,176,65,0,0,144,65,108,0,0,176,65,0,0,64,65,108,0,0,160,65,0,0,64,
65,108,0,0,160,65,0,0,56,65,108,0,0,160,65,0,0,0,65,108,0,0,64,65,0,0,0,65,108,0,0,64,65,0,0,208,64,108,0,0,64,65,0,0,192,64,108,0,0,96,65,0,0,192,64,108,0,0,96,65,0,0,0,0,108,0,0,0,65,0,0,0,0,99,101,0,0 };
const uint8 file[] = { 110,109,0,0,0,0,0,0,0,0,108,0,0,0,0,0,0,144,65,108,0,0,96,65,0,0,144,65,108,0,0,96,65,0,0,136,65,108,0,0,96,65,0,0,0,65,108,0,0,96,65,0,112,212,64,108,0,128,7,65,0,0,0,0,108,0,0,0,65,0,0,0,0,108,0,0,0,0,0,0,0,0,99,109,0,0,0,64,0,0,0,64,108,0,176,234,
64,0,0,0,64,108,0,0,192,64,0,0,192,64,108,0,0,64,65,0,0,240,64,108,0,0,64,65,0,0,128,65,108,0,0,0,64,0,0,128,65,108,0,0,0,64,0,0,0,64,99,101,0,0 };
const uint8 modules[] = { 110,109,193,202,222,64,80,50,21,64,108,0,0,48,65,0,0,0,0,108,160,154,112,65,80,50,21,64,108,0,0,48,65,80,50,149,64,108,193,202,222,64,80,50,21,64,99,109,0,0,192,64,251,220,127,64,108,160,154,32,65,165,135,202,64,108,160,154,32,65,250,220,47,65,108,0,
0,192,64,102,144,10,65,108,0,0,192,64,251,220,127,64,99,109,0,0,128,65,251,220,127,64,108,0,0,128,65,103,144,10,65,108,96,101,63,65,251,220,47,65,108,96,101,63,65,166,135,202,64,108,0,0,128,65,251,220,127,64,99,109,96,101,79,65,148,76,69,65,108,0,0,136,
65,0,0,32,65,108,80,77,168,65,148,76,69,65,108,0,0,136,65,40,153,106,65,108,96,101,79,65,148,76,69,65,99,109,0,0,64,65,63,247,95,65,108,80,77,128,65,233,161,130,65,108,80,77,128,65,125,238,167,65,108,0,0,64,65,51,72,149,65,108,0,0,64,65,63,247,95,65,
99,109,0,0,176,65,63,247,95,65,108,0,0,176,65,51,72,149,65,108,176,178,143,65,125,238,167,65,108,176,178,143,65,233,161,130,65,108,0,0,176,65,63,247,95,65,99,109,12,86,118,63,148,76,69,65,108,0,0,160,64,0,0,32,65,108,159,154,16,65,148,76,69,65,108,0,
0,160,64,40,153,106,65,108,12,86,118,63,148,76,69,65,99,109,0,0,0,0,63,247,95,65,108,62,53,129,64,233,161,130,65,108,62,53,129,64,125,238,167,65,108,0,0,0,0,51,72,149,65,108,0,0,0,0,63,247,95,65,99,109,0,0,32,65,63,247,95,65,108,0,0,32,65,51,72,149,65,
108,193,202,190,64,125,238,167,65,108,193,202,190,64,233,161,130,65,108,0,0,32,65,63,247,95,65,99,101,0,0 };
const uint8 openFolder[] = { 110,109,0,0,32,65,0,0,0,0,108,0,0,32,65,0,0,0,64,108,0,0,0,64,0,0,0,64,108,0,0,0,64,0,0,192,64,108,0,0,0,0,0,0,192,64,108,0,0,0,64,0,0,128,65,108,0,0,152,65,0,0,128,65,108,0,0,160,65,0,0,128,65,108,0,0,160,65,0,0,112,65,108,0,0,160,65,0,0,0,64,108,0,
0,144,65,0,0,0,64,108,0,0,144,65,0,0,0,0,108,0,0,32,65,0,0,0,0,99,109,0,0,64,65,0,0,0,64,108,0,0,128,65,0,0,0,64,108,0,0,128,65,0,0,128,64,108,0,0,144,65,0,0,128,64,108,0,0,144,65,0,0,48,65,108,0,0,136,65,0,0,192,64,108,0,0,128,64,0,0,192,64,108,0,0,
128,64,0,0,128,64,108,0,0,64,65,0,0,128,64,108,0,0,64,65,0,0,0,64,99,101,0,0 };
const uint8 settings[] = { 110,109,202,111,210,64,243,226,61,64,108,0,0,224,64,0,0,0,0,108,0,0,48,65,0,0,0,0,108,27,200,54,65,243,226,61,64,98,91,248,63,65,174,170,76,64,95,130,72,65,231,138,96,64,46,46,80,65,180,163,120,64,108,42,181,124,65,20,38,49,64,108,149,90,142,65,246,108,
199,64,108,68,249,118,65,2,85,1,65,98,112,166,119,65,201,31,6,65,0,0,120,65,111,5,11,65,0,0,120,65,0,0,16,65,98,0,0,120,65,145,250,20,65,108,166,119,65,55,224,25,65,72,249,118,65,254,170,30,65,108,151,90,142,65,133,73,60,65,108,46,181,124,65,123,182,
115,65,108,50,46,80,65,18,215,97,65,98,99,130,72,65,70,221,103,65,96,248,63,65,83,213,108,65,32,200,54,65,66,135,112,65,108,0,0,48,65,0,0,144,65,108,0,0,224,64,0,0,144,65,108,202,111,210,64,67,135,112,65,98,74,15,192,64,84,213,108,65,65,251,174,64,70,
221,103,65,164,163,159,64,19,215,97,65,108,92,43,13,64,123,182,115,65,108,187,181,82,62,133,73,60,65,108,244,26,36,64,254,170,30,65,98,64,102,33,64,55,224,25,65,0,0,32,64,145,250,20,65,0,0,32,64,0,0,16,65,98,0,0,32,64,111,5,11,65,64,102,33,64,201,31,
6,65,244,26,36,64,2,85,1,65,108,187,181,82,62,246,108,199,64,108,92,43,13,64,20,38,49,64,108,164,163,159,64,180,163,120,64,98,65,251,174,64,231,138,96,64,74,15,192,64,175,170,76,64,202,111,210,64,243,226,61,64,99,109,0,0,16,65,0,0,64,65,98,121,130,42,
65,0,0,64,65,0,0,64,65,121,130,42,65,0,0,64,65,0,0,16,65,98,0,0,64,65,13,251,234,64,121,130,42,65,0,0,192,64,0,0,16,65,0,0,192,64,98,13,251,234,64,0,0,192,64,0,0,192,64,13,251,234,64,0,0,192,64,0,0,16,65,98,0,0,192,64,121,130,42,65,13,251,234,64,0,0,
64,65,0,0,16,65,0,0,64,65,99,101,0,0 };
const uint8 singleModule[] = { 110,109,165,48,137,63,179,12,91,64,108,0,0,224,64,0,0,0,0,108,235,217,78,65,179,12,91,64,108,0,0,224,64,176,12,219,64,108,165,48,137,63,179,12,91,64,99,109,51,10,147,61,80,243,164,64,108,0,0,192,64,211,60,9,65,108,0,0,192,64,45,195,118,65,108,51,10,147,
61,0,0,64,65,108,51,10,147,61,80,243,164,64,99,109,235,217,94,65,80,243,164,64,108,235,217,94,65,0,0,64,65,108,0,0,0,65,45,195,118,65,108,0,0,0,65,211,60,9,65,108,235,217,94,65,80,243,164,64,99,101,0,0 };
const uint8 plus[] = { 110,109,0,128,223,64,0,0,96,188,108,0,128,223,64,64,0,96,188,108,189,230,221,64,128,185,62,188,108,210,78,220,64,128,42,233,187,108,68,185,218,64,0,32,225,184,108,23,39,217,64,0,118,25,60,108,75,153,215,64,32,88,174,60,108,223,16,214,64,192,219,17,61,
108,206,142,212,64,48,71,86,61,108,16,20,211,64,64,33,146,61,108,151,161,209,64,232,205,189,61,108,79,56,208,64,152,13,238,61,108,32,217,206,64,188,96,17,62,108,235,132,205,64,232,227,45,62,108,137,60,204,64,16,126,76,62,108,204,0,203,64,160,27,109,62,
108,127,210,201,64,220,211,135,62,108,98,178,200,64,30,6,154,62,108,48,161,199,64,242,24,173,62,108,148,159,198,64,38,0,193,62,108,54,174,197,64,248,174,213,62,108,176,205,196,64,52,24,235,62,108,144,254,195,64,14,151,0,63,108,92,65,195,64,76,241,11,
63,108,140,150,194,64,141,147,23,63,108,142,254,193,64,98,118,35,63,108,196,121,193,64,47,146,47,63,108,129,8,193,64,52,223,59,63,108,15,171,192,64,146,85,72,63,108,169,97,192,64,81,237,84,63,108,127,44,192,64,97,158,97,63,108,178,11,192,64,164,96,110,
63,108,87,255,191,64,238,43,123,63,108,0,0,192,64,0,0,128,63,108,0,0,192,64,0,0,128,63,108,0,0,192,64,0,0,192,64,108,0,0,128,63,0,0,192,64,108,0,0,128,63,0,0,192,64,108,104,51,115,63,114,4,192,64,108,176,108,102,63,92,29,192,64,108,4,180,89,63,172,74,
192,64,108,136,17,77,63,71,140,192,64,108,82,141,64,63,1,226,192,64,108,100,47,52,63,165,75,193,64,108,167,255,39,63,238,200,193,64,108,232,5,28,63,140,89,194,64,108,210,73,16,63,36,253,194,64,108,229,210,4,63,76,179,195,64,108,240,80,243,62,143,123,
196,64,108,96,163,221,62,110,85,197,64,108,248,170,200,62,93,64,198,64,108,38,117,180,62,197,59,199,64,108,214,14,161,62,7,71,200,64,108,112,132,142,62,118,97,201,64,108,168,195,121,62,95,138,202,64,108,148,100,88,62,3,193,203,64,108,0,1,57,62,155,4,
205,64,108,0,173,27,62,89,84,206,64,108,88,123,0,62,101,175,207,64,108,224,250,206,61,226,20,209,64,108,136,134,161,61,234,131,210,64,108,128,109,113,61,147,251,211,64,108,64,75,41,61,237,122,213,64,108,32,169,213,60,2,1,215,64,108,0,197,88,60,216,140,
216,64,108,0,51,56,59,115,29,218,64,108,128,212,168,187,210,177,219,64,108,128,75,46,188,242,72,221,64,108,64,94,95,188,206,225,222,64,108,128,130,103,188,98,123,224,64,108,128,179,70,188,167,20,226,64,108,0,12,250,187,151,172,227,64,108,0,148,42,186,
46,66,229,64,108,128,25,16,60,102,212,230,64,108,192,111,169,60,65,98,232,64,108,240,74,15,61,190,234,233,64,108,48,154,83,61,226,108,235,64,108,224,188,144,61,183,231,236,64,108,0,92,188,61,74,90,238,64,108,136,142,236,61,173,195,239,64,108,200,154,
16,62,251,34,241,64,108,188,23,45,62,82,119,242,64,108,228,171,75,62,215,191,243,64,108,172,67,108,62,186,251,244,64,108,30,101,135,62,47,42,246,64,108,188,148,153,62,118,74,247,64,108,18,165,172,62,213,91,248,64,108,232,137,192,62,159,93,249,64,108,
134,54,213,62,45,79,250,64,108,176,157,234,62,230,47,251,64,108,218,88,0,63,57,255,251,64,108,58,178,11,63,163,188,252,64,108,180,83,23,63,169,103,253,64,108,216,53,35,63,222,255,253,64,108,9,81,47,63,225,132,254,64,108,138,157,59,63,94,246,254,64,108,
123,19,72,63,10,84,255,64,108,228,170,84,63,170,157,255,64,108,181,91,97,63,16,211,255,64,108,209,29,110,63,25,244,255,64,108,13,233,122,63,88,0,0,65,108,254,255,127,63,0,0,0,65,108,0,0,128,63,0,0,0,65,108,0,0,192,64,0,0,0,65,108,0,0,192,64,0,0,80,65,
108,0,0,192,64,0,0,80,65,108,114,4,192,64,202,204,80,65,108,92,29,192,64,53,153,81,65,108,172,74,192,64,192,100,82,65,108,70,140,192,64,232,46,83,65,108,1,226,192,64,43,247,83,65,108,164,75,193,64,10,189,84,65,108,238,200,193,64,6,128,85,65,108,140,89,
194,64,161,63,86,65,108,36,253,194,64,99,251,86,65,108,75,179,195,64,210,178,87,65,108,142,123,196,64,120,101,88,65,108,109,85,197,64,229,18,89,65,108,92,64,198,64,168,186,89,65,108,196,59,199,64,87,92,90,65,108,6,71,200,64,137,247,90,65,108,117,97,201,
64,220,139,91,65,108,94,138,202,64,241,24,92,65,108,2,193,203,64,109,158,92,65,108,154,4,205,64,252,27,93,65,108,87,84,206,64,76,145,93,65,108,99,175,207,64,18,254,93,65,108,224,20,209,64,10,98,94,65,108,232,131,210,64,243,188,94,65,108,145,251,211,64,
146,14,95,65,108,235,122,213,64,181,86,95,65,108,0,1,215,64,43,149,95,65,108,214,140,216,64,207,201,95,65,108,113,29,218,64,125,244,95,65,108,208,177,219,64,27,21,96,65,108,240,72,221,64,147,43,96,65,108,204,225,222,64,216,55,96,65,108,96,123,224,64,
225,57,96,65,108,165,20,226,64,173,49,96,65,108,149,172,227,64,66,31,96,65,108,43,66,229,64,171,2,96,65,108,100,212,230,64,250,219,95,65,108,63,98,232,64,73,171,95,65,108,187,234,233,64,182,112,95,65,108,224,108,235,64,102,44,95,65,108,181,231,236,64,
135,222,94,65,108,72,90,238,64,73,135,94,65,108,172,195,239,64,228,38,94,65,108,249,34,241,64,150,189,93,65,108,80,119,242,64,162,75,93,65,108,214,191,243,64,81,209,92,65,108,184,251,244,64,242,78,92,65,108,46,42,246,64,216,196,91,65,108,116,74,247,64,
91,51,91,65,108,212,91,248,64,217,154,90,65,108,158,93,249,64,178,251,89,65,108,44,79,250,64,77,86,89,65,108,230,47,251,64,19,171,88,65,108,57,255,251,64,115,250,87,65,108,163,188,252,64,220,68,87,65,108,169,103,253,64,197,138,86,65,108,223,255,253,64,
162,204,85,65,108,226,132,254,64,239,10,85,65,108,94,246,254,64,39,70,84,65,108,10,84,255,64,199,126,83,65,108,171,157,255,64,80,181,82,65,108,16,211,255,64,67,234,81,65,108,25,244,255,64,33,30,81,65,108,88,0,0,65,109,81,80,65,108,0,0,0,65,0,0,80,65,
108,0,0,0,65,0,0,80,65,108,0,0,0,65,0,0,0,65,108,0,0,80,65,0,0,0,65,108,0,0,80,65,0,0,0,65,108,202,204,80,65,142,251,255,64,108,53,153,81,65,164,226,255,64,108,192,100,82,65,84,181,255,64,108,232,46,83,65,185,115,255,64,108,43,247,83,65,255,29,255,64,
108,10,189,84,65,92,180,254,64,108,6,128,85,65,18,55,254,64,108,162,63,86,65,116,166,253,64,108,99,251,86,65,220,2,253,64,108,210,178,87,65,181,76,252,64,108,120,101,88,65,114,132,251,64,108,229,18,89,65,147,170,250,64,108,168,186,89,65,164,191,249,64,
108,87,92,90,65,60,196,248,64,108,137,247,90,65,250,184,247,64,108,220,139,91,65,139,158,246,64,108,241,24,92,65,162,117,245,64,108,109,158,92,65,254,62,244,64,108,252,27,93,65,102,251,242,64,108,76,145,93,65,169,171,241,64,108,18,254,93,65,157,80,240,
64,108,10,98,94,65,32,235,238,64,108,243,188,94,65,24,124,237,64,108,146,14,95,65,111,4,236,64,108,181,86,95,65,21,133,234,64,108,43,149,95,65,0,255,232,64,108,207,201,95,65,42,115,231,64,108,125,244,95,65,143,226,229,64,108,27,21,96,65,49,78,228,64,
108,147,43,96,65,17,183,226,64,108,216,55,96,65,52,30,225,64,108,225,57,96,65,160,132,223,64,108,173,49,96,65,91,235,221,64,108,66,31,96,65,107,83,220,64,108,171,2,96,65,213,189,218,64,108,250,219,95,65,156,43,217,64,108,73,171,95,65,194,157,215,64,108,
182,112,95,65,69,21,214,64,108,102,44,95,65,32,147,212,64,108,135,222,94,65,75,24,211,64,108,73,135,94,65,184,165,209,64,108,228,38,94,65,84,60,208,64,108,150,189,93,65,7,221,206,64,108,162,75,93,65,176,136,205,64,108,81,209,92,65,42,64,204,64,108,242,
78,92,65,72,4,203,64,108,216,196,91,65,210,213,201,64,108,91,51,91,65,139,181,200,64,108,216,154,90,65,44,164,199,64,108,178,251,89,65,98,162,198,64,108,77,86,89,65,212,176,197,64,108,19,171,88,65,27,208,196,64,108,115,250,87,65,199,0,196,64,108,221,
68,87,65,94,67,195,64,108,197,138,86,65,88,152,194,64,108,163,204,85,65,34,0,194,64,108,240,10,85,65,31,123,193,64,108,40,70,84,65,163,9,193,64,108,201,126,83,65,246,171,192,64,108,82,181,82,65,86,98,192,64,108,69,234,81,65,240,44,192,64,108,35,30,81,
65,231,11,192,64,108,111,81,80,65,81,255,191,64,108,0,0,80,65,0,0,192,64,108,0,0,80,65,0,0,192,64,108,0,0,0,65,0,0,192,64,108,0,0,0,65,0,0,128,63,108,0,0,0,65,0,0,128,63,108,94,251,255,64,110,51,115,63,108,70,226,255,64,205,108,102,63,108,199,180,255,
64,76,180,89,63,108,254,114,255,64,13,18,77,63,108,21,29,255,64,39,142,64,63,108,68,179,254,64,154,48,52,63,108,206,53,254,64,82,1,40,63,108,4,165,253,64,26,8,28,63,108,65,1,253,64,155,76,16,63,108,239,74,252,64,87,214,4,63,108,131,130,251,64,70,89,243,
62,108,124,168,250,64,72,173,221,62,108,103,189,249,64,144,182,200,62,108,217,193,248,64,140,130,180,62,108,115,182,247,64,38,30,161,62,108,226,155,246,64,200,149,142,62,108,217,114,245,64,160,234,121,62,108,22,60,244,64,4,144,88,62,108,97,248,242,64,
24,49,57,62,108,136,168,241,64,236,225,27,62,108,99,77,240,64,64,181,0,62,108,207,231,238,64,240,120,207,61,108,178,120,237,64,40,15,162,61,108,246,0,236,64,96,148,114,61,108,140,129,234,64,32,136,42,61,108,104,251,232,64,160,79,216,60,108,134,111,231,
64,64,109,94,60,108,225,222,229,64,0,67,80,59,108,123,74,228,64,128,17,156,187,108,85,179,226,64,128,140,39,188,108,118,26,225,64,192,64,88,188,108,225,128,223,64,0,7,96,188,108,0,128,223,64,0,0,96,188,108,0,128,223,64,0,0,96,188,99,101,0,0 };
const uint8 android[] = { 110,109,31,179,128,65,235,31,97,65,98,31,179,128,65,216,190,108,65,127,102,133,65,162,42,118,65,26,51,139,65,162,42,118,65,108,26,51,139,65,162,42,118,65,98,153,255,144,65,162,42,118,65,21,179,149,65,216,190,108,65,21,179,149,65,235,31,97,65,108,21,179,
149,65,134,3,12,65,98,21,179,149,65,153,100,0,65,152,255,144,65,158,241,237,64,26,51,139,65,158,241,237,64,108,26,51,139,65,158,241,237,64,98,128,102,133,65,158,241,237,64,31,179,128,65,153,100,0,65,31,179,128,65,134,3,12,65,108,31,179,128,65,234,31,
97,65,99,109,121,61,100,64,184,62,239,64,108,121,61,100,64,168,171,136,65,98,121,61,100,64,44,60,141,65,127,228,128,64,157,239,144,65,141,30,147,64,157,239,144,65,108,175,38,186,64,157,239,144,65,108,175,38,186,64,221,149,168,65,98,175,38,186,64,112,
101,174,65,50,244,204,64,57,27,179,65,156,38,228,64,57,27,179,65,98,6,89,251,64,57,27,179,65,125,19,7,65,112,101,174,65,125,19,7,65,221,149,168,65,108,125,19,7,65,157,239,144,65,108,220,76,39,65,157,239,144,65,108,220,76,39,65,221,149,168,65,98,220,76,
39,65,112,101,174,65,101,179,48,65,57,27,179,65,211,76,60,65,57,27,179,65,98,65,230,71,65,57,27,179,65,202,76,81,65,112,101,174,65,202,76,81,65,221,149,168,65,108,202,76,81,65,157,239,144,65,108,218,208,100,65,157,239,144,65,98,225,237,109,65,157,239,
144,65,52,81,117,65,185,60,141,65,52,81,117,65,168,171,136,65,108,52,81,117,65,184,62,239,64,108,124,61,100,64,184,62,239,64,99,109,106,232,51,64,234,31,97,65,98,106,232,51,64,215,190,108,65,130,76,14,64,161,42,118,65,91,207,191,63,161,42,118,65,108,
91,207,191,63,161,42,118,65,98,235,14,70,63,161,42,118,65,48,125,62,62,215,190,108,65,48,125,62,62,234,31,97,65,108,48,125,62,62,134,3,12,65,98,48,125,62,62,153,100,0,65,235,14,70,63,158,241,237,64,91,207,191,63,158,241,237,64,108,91,207,191,63,158,241,
237,64,98,130,76,14,64,158,241,237,64,106,232,51,64,153,100,0,65,106,232,51,64,134,3,12,65,108,106,232,51,64,234,31,97,65,99,109,150,130,62,65,58,171,159,64,98,172,194,56,65,58,171,159,64,87,25,52,65,88,83,150,64,87,25,52,65,221,203,138,64,98,87,25,52,
65,226,135,126,64,172,194,56,65,30,216,107,64,150,130,62,65,30,216,107,64,98,10,68,68,65,30,216,107,64,239,236,72,65,168,137,126,64,239,236,72,65,221,203,138,64,98,239,236,72,65,230,82,150,64,153,67,68,65,58,171,159,64,150,130,62,65,58,171,159,64,109,
135,187,223,64,58,171,159,64,98,128,57,212,64,58,171,159,64,100,230,202,64,88,83,150,64,100,230,202,64,221,203,138,64,98,100,230,202,64,167,137,126,64,45,56,212,64,30,216,107,64,136,187,223,64,30,216,107,64,98,90,59,235,64,30,216,107,64,148,141,244,64,
226,135,126,64,148,141,244,64,221,203,138,64,98,5,142,244,64,230,82,150,64,90,59,235,64,58,171,159,64,136,187,223,64,58,171,159,64,109,208,208,67,65,188,224,31,64,108,196,50,85,65,248,218,106,63,98,0,59,86,65,53,205,82,63,56,249,85,65,66,58,51,63,195,
159,84,65,51,76,36,63,98,192,70,83,65,100,115,21,63,214,87,81,65,146,202,28,63,152,81,80,65,106,223,52,63,108,206,64,62,65,202,79,22,64,98,3,89,50,65,182,131,3,64,149,32,37,65,39,20,242,63,99,49,23,65,39,20,242,63,98,48,66,9,65,39,20,242,63,195,17,248,
64,15,129,3,64,158,66,224,64,202,79,22,64,108,100,34,188,64,224,219,52,63,98,43,16,186,64,28,206,28,63,32,52,182,64,219,111,21,63,164,129,179,64,174,72,36,63,98,40,207,176,64,31,44,51,63,9,76,176,64,156,194,82,63,127,92,178,64,115,215,106,63,108,123,
35,213,64,219,223,31,64,98,38,216,157,64,148,108,83,64,182,34,110,64,196,176,154,64,1,65,100,64,77,218,211,64,108,223,79,117,65,77,218,211,64,98,167,217,114,65,196,176,154,64,10,118,95,65,118,109,83,64,207,208,67,65,189,224,31,64,101,0,0 };
const uint8 codeBlocks[] = { 110,109,0,0,0,0,0,0,0,0,108,0,0,0,0,0,208,235,64,108,0,192,134,64,0,152,23,65,108,0,152,23,65,0,152,23,65,108,0,152,23,65,0,192,134,64,108,0,208,235,64,0,0,0,0,108,0,0,0,0,0,0,0,0,99,109,0,24,74,65,0,0,0,0,108,0,104,40,65,0,192,134,64,108,0,104,40,65,
0,152,23,65,108,255,159,124,65,0,152,23,65,108,0,0,160,65,0,208,235,64,108,0,0,160,65,0,0,0,0,108,0,24,74,65,0,0,0,0,99,109,0,192,134,64,0,104,40,65,108,0,0,0,0,0,24,74,65,108,0,0,0,0,0,0,160,65,108,0,208,235,64,0,0,160,65,108,0,152,23,65,255,159,124,
65,108,0,152,23,65,0,104,40,65,108,0,192,134,64,0,104,40,65,99,109,0,104,40,65,0,104,40,65,108,0,104,40,65,255,159,124,65,108,0,24,74,65,0,0,160,65,108,0,0,160,65,0,0,160,65,108,0,0,160,65,0,24,74,65,108,255,159,124,65,0,104,40,65,108,0,104,40,65,0,104,
40,65,99,101,0,0 };
const uint8 linux[] = { 110,109,0,0,124,66,174,71,130,66,108,0,0,124,66,174,71,130,66,108,162,178,123,66,87,5,130,66,108,186,94,123,66,5,197,129,66,108,128,4,123,66,225,134,129,66,108,45,164,122,66,17,75,129,66,108,254,61,122,66,189,17,129,66,108,52,210,121,66,9,219,128,66,
108,22,97,121,66,24,167,128,66,108,234,234,120,66,11,118,128,66,108,143,194,120,66,102,102,128,66,108,143,194,120,66,102,102,128,66,108,143,194,120,66,102,102,128,66,108,167,246,119,66,12,20,128,66,108,198,34,119,66,200,141,127,66,108,114,71,118,66,65,
254,126,66,108,245,40,118,66,132,235,126,66,108,245,40,118,66,132,235,126,66,108,112,61,117,66,234,81,126,66,108,111,61,117,66,234,81,126,66,108,17,6,115,66,5,193,124,66,108,114,227,112,66,69,20,123,66,108,162,112,111,66,9,215,121,66,108,163,112,111,
66,9,215,121,66,108,164,112,111,66,10,215,121,66,108,204,182,109,66,55,99,120,66,108,23,16,108,66,198,217,118,66,108,148,125,106,66,178,59,117,66,108,113,61,106,66,194,245,116,66,108,112,61,106,66,193,245,116,66,108,112,61,106,66,193,245,116,66,108,32,
222,105,66,15,140,116,66,108,56,132,105,66,187,29,116,66,108,239,47,105,66,13,171,115,66,108,125,225,104,66,76,52,115,66,108,20,153,104,66,198,185,114,66,108,225,86,104,66,201,59,114,66,108,15,27,104,66,165,186,113,66,108,197,229,103,66,173,54,113,66,
108,37,183,103,66,54,176,112,66,108,76,143,103,66,149,39,112,66,108,31,133,103,66,255,255,111,66,108,31,133,103,66,0,0,112,66,108,31,133,103,66,1,0,112,66,108,55,95,103,66,33,237,110,66,108,24,71,103,66,180,216,109,66,108,113,61,103,66,133,235,108,66,
108,113,61,103,66,133,235,108,66,108,113,61,103,66,225,122,107,66,108,113,61,103,66,225,122,107,66,108,153,25,103,66,15,82,106,66,108,247,230,102,66,103,43,105,66,108,171,165,102,66,165,7,104,66,108,223,85,102,66,131,231,102,66,108,198,247,101,66,187,
203,101,66,108,144,194,101,66,112,61,101,66,108,144,194,101,66,112,61,101,66,108,144,194,101,66,112,61,101,66,108,66,119,101,66,161,143,100,66,108,93,35,101,66,205,229,99,66,108,21,199,100,66,97,64,99,66,108,166,98,100,66,198,159,98,66,108,81,246,99,
66,100,4,98,66,108,90,130,99,66,158,110,97,66,108,12,7,99,66,211,222,96,66,108,1,0,99,66,10,215,96,66,108,1,0,99,66,10,215,96,66,108,1,0,99,66,10,215,96,66,108,182,121,98,66,28,94,96,66,108,138,237,97,66,11,236,95,66,108,216,91,97,66,32,129,95,66,108,
253,196,96,66,159,29,95,66,108,89,41,96,66,200,193,94,66,108,79,137,95,66,214,109,94,66,108,71,229,94,66,255,33,94,66,108,169,61,94,66,114,222,93,66,108,224,146,93,66,92,163,93,66,108,237,81,93,66,92,143,93,66,108,237,81,93,66,92,143,93,66,108,206,204,
92,66,92,143,93,66,108,206,204,92,66,92,143,93,66,108,206,204,92,66,92,143,93,66,108,124,20,93,66,10,215,92,66,108,124,20,93,66,10,215,92,66,108,104,246,93,66,191,108,91,66,108,240,197,94,66,157,247,89,66,108,144,130,95,66,148,120,88,66,108,207,43,96,
66,151,240,86,66,108,64,193,96,66,162,96,85,66,108,132,66,97,66,182,201,83,66,108,72,175,97,66,213,44,82,66,108,71,7,98,66,9,139,80,66,108,62,10,98,66,225,122,80,66,108,63,10,98,66,225,122,80,66,108,63,10,98,66,225,122,80,66,108,31,110,98,66,238,111,
77,66,108,240,170,98,66,246,96,74,66,108,141,192,98,66,239,79,71,66,108,231,174,98,66,207,62,68,66,108,8,118,98,66,139,47,65,66,108,22,22,98,66,26,36,62,66,108,94,143,97,66,184,30,59,66,108,94,143,97,66,184,30,59,66,108,94,143,97,66,184,30,59,66,108,
246,32,96,66,254,27,52,66,108,81,89,94,66,212,45,45,66,108,146,57,92,66,166,88,38,66,108,21,195,89,66,213,160,31,66,108,94,143,89,66,184,30,31,66,108,94,143,89,66,184,30,31,66,108,94,143,89,66,184,30,31,66,108,240,13,88,66,120,66,27,66,108,152,91,86,
66,184,122,23,66,108,111,121,84,66,226,201,19,66,108,166,104,82,66,83,50,16,66,108,145,42,80,66,88,182,12,66,108,145,194,79,66,184,30,12,66,108,145,194,79,66,184,30,12,66,98,145,194,75,66,225,122,6,66,227,122,70,66,143,194,1,66,227,122,66,66,112,61,248,
65,98,247,40,65,66,225,122,244,65,2,0,64,66,112,61,240,65,145,194,62,66,204,204,236,65,98,125,20,61,66,143,194,229,65,104,102,59,66,204,204,222,65,206,204,57,66,20,174,215,65,98,52,51,55,66,143,194,203,65,32,133,52,66,20,174,191,65,104,102,49,66,245,
40,180,65,108,237,81,48,66,235,81,176,65,98,135,235,47,66,235,81,164,65,176,71,47,66,235,81,152,65,196,245,46,66,102,102,140,65,98,42,92,46,66,204,204,108,65,196,245,46,66,224,122,64,65,176,71,44,66,112,61,22,65,108,176,71,44,66,112,61,22,65,108,205,
151,43,66,90,43,12,65,108,236,199,42,66,166,63,2,65,108,146,216,41,66,91,1,241,64,108,88,202,40,66,90,233,221,64,108,235,157,39,66,128,67,203,64,108,11,84,38,66,190,27,185,64,108,0,0,38,66,205,204,180,64,108,0,0,38,66,205,204,180,64,108,0,0,38,66,205,
204,180,64,108,29,150,36,66,8,152,163,64,108,42,17,35,66,117,249,146,64,108,30,114,33,66,184,251,130,64,108,4,186,31,66,24,82,103,64,108,245,233,29,66,124,22,74,64,108,26,3,28,66,84,87,46,64,108,171,6,26,66,92,38,20,64,108,215,163,25,66,40,92,15,64,108,
215,163,25,66,41,92,15,64,108,215,163,25,66,44,92,15,64,108,11,188,23,66,192,97,244,63,108,237,195,21,66,224,36,205,63,108,193,188,19,66,208,26,169,63,108,209,167,17,66,160,90,136,63,108,116,134,15,66,112,242,85,63,108,6,90,13,66,240,18,34,63,108,235,
35,11,66,160,111,234,62,108,142,229,8,66,160,251,158,62,108,93,160,6,66,128,244,67,62,108,206,85,4,66,0,74,206,61,108,86,7,2,66,0,15,31,61,108,225,108,255,65,0,56,191,59,108,205,204,252,65,0,0,0,0,108,205,204,252,65,0,0,0,0,108,205,204,252,65,0,0,0,0,
108,250,164,248,65,0,128,238,57,108,135,126,244,65,0,30,220,60,108,28,92,240,65,128,41,162,61,108,95,64,236,65,128,7,33,62,108,240,45,232,65,128,148,133,62,108,106,39,228,65,192,154,199,62,108,97,47,224,65,0,54,11,63,108,94,72,220,65,16,235,56,63,108,
226,116,216,65,64,207,108,63,108,94,183,212,65,176,96,147,63,108,31,133,211,65,168,112,157,63,108,31,133,211,65,164,112,157,63,108,31,133,211,65,168,112,157,63,108,38,65,208,65,8,197,188,63,108,69,23,205,65,240,171,222,63,108,132,9,202,65,204,135,1,64,
108,214,25,199,65,98,236,20,64,108,29,74,196,65,78,119,41,64,108,37,156,193,65,110,27,63,64,108,164,17,191,65,230,202,85,64,108,60,172,188,65,50,119,109,64,108,117,109,186,65,154,8,131,64,108,190,86,184,65,144,196,143,64,108,110,105,182,65,90,231,156,
64,108,193,166,180,65,143,104,170,64,108,104,102,180,65,225,122,172,64,108,103,102,180,65,225,122,172,64,108,102,102,180,65,227,122,172,64,108,85,58,178,65,2,116,193,64,108,12,82,176,65,151,213,214,64,108,195,174,174,65,242,145,236,64,108,135,81,173,
65,150,77,1,65,108,55,59,172,65,148,113,12,65,108,133,108,171,65,213,173,23,65,108,246,229,170,65,38,251,34,65,108,223,167,170,65,77,82,46,65,108,215,163,170,65,194,245,48,65,108,216,163,170,65,194,245,48,65,98,124,20,170,65,20,174,79,65,165,112,171,
65,122,20,110,65,1,0,172,65,225,122,134,65,98,1,0,172,65,225,122,142,65,103,102,172,65,225,122,150,65,93,143,172,65,225,122,158,65,108,93,143,172,65,41,92,159,65,108,93,143,172,65,41,92,159,65,108,18,0,172,65,14,130,161,65,108,112,140,171,65,110,174,
163,65,108,32,133,171,65,10,215,163,65,108,32,133,171,65,10,215,163,65,98,32,133,171,65,225,122,164,65,32,133,171,65,51,51,165,65,63,10,171,65,123,20,166,65,108,63,10,171,65,123,20,166,65,108,6,199,170,65,61,25,167,65,108,234,144,170,65,8,33,168,65,108,
15,104,170,65,50,43,169,65,108,143,76,170,65,19,55,170,65,108,123,62,170,65,253,67,171,65,108,114,61,170,65,164,112,171,65,108,114,61,170,65,164,112,171,65,108,114,61,170,65,164,112,171,65,108,78,63,170,65,1,44,172,65,108,134,74,170,65,10,231,172,65,
108,20,95,170,65,72,161,173,65,108,234,124,170,65,67,90,174,65,108,245,163,170,65,133,17,175,65,108,28,212,170,65,154,198,175,65,108,65,13,171,65,12,121,176,65,108,63,79,171,65,106,40,177,65,108,235,153,171,65,67,212,177,65,108,145,194,171,65,246,40,
178,65,108,145,194,171,65,246,40,178,65,108,145,194,171,65,246,40,178,65,108,84,42,172,65,73,229,178,65,108,96,155,172,65,48,156,179,65,108,107,21,173,65,55,77,180,65,108,41,152,173,65,235,247,180,65,108,135,235,173,65,41,92,181,65,108,135,235,173,65,
41,92,181,65,98,125,20,176,65,92,143,184,65,135,235,173,65,10,215,181,65,135,235,173,65,123,20,182,65,98,135,235,173,65,51,51,187,65,74,225,174,65,236,81,192,65,74,225,174,65,164,112,197,65,98,74,225,174,65,123,20,200,65,74,225,174,65,215,163,202,65,
74,225,174,65,164,112,205,65,108,2,0,174,65,133,235,207,65,108,2,0,174,65,133,235,207,65,108,178,149,171,65,102,105,213,65,108,229,229,168,65,157,198,218,65,108,82,242,165,65,190,255,223,65,108,156,153,163,65,143,194,227,65,108,156,153,163,65,143,194,
227,65,108,54,51,151,65,143,194,243,65,98,167,112,145,65,184,30,251,65,13,215,139,65,174,71,1,66,3,0,134,65,194,245,4,66,108,3,0,134,65,194,245,4,66,108,1,155,129,65,192,173,7,66,108,241,249,122,65,252,128,10,66,108,26,81,115,65,168,109,13,66,108,98,
64,108,65,228,113,16,66,108,107,102,102,65,112,61,19,66,108,108,102,102,65,112,61,19,66,108,108,102,102,65,113,61,19,66,108,244,218,94,65,104,179,24,66,108,96,105,88,65,195,63,30,66,108,182,71,85,65,102,102,33,66,108,180,71,85,65,102,102,33,66,108,182,
71,85,65,102,102,33,66,108,64,151,79,65,169,248,37,66,108,168,254,72,65,67,119,42,66,108,38,130,65,65,84,223,46,66,108,180,71,61,65,184,30,49,66,108,180,71,61,65,184,30,49,66,113,61,10,47,65,0,0,56,66,0,0,32,65,195,245,62,66,108,255,255,31,65,195,245,
62,66,108,88,123,28,65,150,155,64,66,108,36,76,25,65,35,76,66,66,108,111,116,22,65,85,6,68,66,108,9,246,19,65,18,201,69,66,108,141,210,17,65,56,147,71,66,108,86,11,16,65,163,99,73,66,108,255,255,15,65,164,112,73,66,108,0,0,16,65,164,112,73,66,108,0,0,
16,65,164,112,73,66,108,14,114,15,65,220,116,74,66,108,80,24,15,65,135,122,75,66,108,254,242,14,65,254,128,76,66,108,49,2,15,65,152,135,77,66,108,222,69,15,65,173,141,78,66,108,219,189,15,65,150,146,79,66,108,0,0,16,65,0,0,80,66,108,0,0,16,65,0,0,80,
66,108,0,0,16,65,0,0,80,66,108,19,74,12,65,237,88,81,66,108,75,218,8,65,74,189,82,66,108,246,40,8,65,61,10,83,66,108,246,40,8,65,61,10,83,66,108,246,40,8,65,61,10,83,66,108,62,245,3,65,173,219,84,66,108,164,203,254,64,22,159,86,66,108,226,122,252,64,
61,10,87,66,108,226,122,252,64,61,10,87,66,108,226,122,252,64,61,10,87,66,108,195,132,250,64,133,102,87,66,108,95,106,248,64,141,191,87,66,108,14,45,246,64,27,21,88,66,108,64,206,243,64,249,102,88,66,108,120,79,241,64,242,180,88,66,108,80,178,238,64,
213,254,88,66,108,114,248,235,64,114,68,89,66,108,160,35,233,64,156,133,89,66,108,166,53,230,64,43,194,89,66,108,184,30,229,64,10,215,89,66,108,185,30,229,64,10,215,89,66,108,185,30,229,64,10,215,89,66,108,77,200,225,64,107,14,90,66,108,206,92,222,64,
101,64,90,66,108,108,222,218,64,214,108,90,66,108,100,79,215,64,162,147,90,66,108,251,177,211,64,177,180,90,66,108,131,8,208,64,238,207,90,66,108,82,85,204,64,70,229,90,66,108,200,154,200,64,173,244,90,66,108,71,219,196,64,24,254,90,66,108,32,133,195,
64,0,0,91,66,108,32,133,195,64,0,0,91,66,98,114,61,186,64,0,0,91,66,155,153,177,64,0,0,91,66,216,163,168,64,0,0,91,66,108,10,215,155,64,0,0,91,66,108,10,215,155,64,0,0,91,66,108,122,219,147,64,146,239,90,66,108,229,219,139,64,238,235,90,66,108,107,221,
131,64,22,245,90,66,108,82,202,119,64,4,11,91,66,108,112,240,103,64,169,45,91,66,108,30,133,91,64,236,81,91,66,108,30,133,91,64,236,81,91,66,108,30,133,91,64,236,81,91,66,108,35,147,82,64,205,112,91,66,108,183,188,73,64,203,150,91,66,108,128,7,65,64,
206,195,91,66,108,16,121,56,64,186,247,91,66,108,227,22,48,64,108,50,92,66,108,84,230,39,64,192,115,92,66,108,162,236,31,64,140,187,92,66,108,230,46,24,64,161,9,93,66,108,20,178,16,64,206,93,93,66,108,249,122,9,64,221,183,93,66,108,49,142,2,64,148,23,
94,66,108,0,0,0,64,113,61,94,66,108,0,0,0,64,113,61,94,66,108,254,255,255,63,113,61,94,66,108,198,203,242,63,227,179,94,66,108,54,89,230,63,118,47,95,66,108,70,176,218,63,219,175,95,66,108,102,216,207,63,193,52,96,66,108,142,216,197,63,211,189,96,66,
108,34,183,188,63,184,74,97,66,108,248,121,180,63,22,219,97,66,108,84,38,173,63,146,110,98,66,108,232,192,166,63,204,4,99,66,108,202,77,161,63,101,157,99,66,108,122,208,156,63,251,55,100,66,108,244,40,156,63,236,81,100,66,108,246,40,156,63,236,81,100,
66,108,244,40,156,63,236,81,100,66,108,112,165,150,63,151,120,101,66,108,248,250,146,63,25,161,102,66,108,224,43,145,63,178,202,103,66,108,84,57,145,63,166,244,104,66,108,72,35,147,63,53,30,106,66,108,224,122,148,63,154,153,106,66,108,226,122,148,63,
154,153,106,66,98,226,122,148,63,93,143,108,66,1,0,160,63,154,153,110,66,103,102,166,63,103,102,112,66,98,205,204,172,63,52,51,114,66,62,10,183,63,1,0,117,66,72,225,186,63,236,81,119,66,108,72,225,186,63,236,81,119,66,108,92,185,189,63,144,183,120,66,
108,136,84,190,63,228,29,122,66,108,108,178,188,63,4,132,123,66,108,20,212,184,63,10,233,124,66,108,248,187,178,63,18,76,126,66,108,0,110,170,63,56,172,127,66,108,124,239,159,63,78,132,128,66,108,36,71,147,63,47,48,129,66,108,196,245,136,63,246,168,129,
66,108,195,245,136,63,246,168,129,66,98,144,194,117,63,51,51,130,66,226,122,84,63,82,184,130,66,52,51,51,63,113,61,131,66,108,48,51,51,63,113,61,131,66,108,192,247,250,62,153,19,132,66,108,128,95,154,62,218,238,132,66,108,128,194,117,62,113,61,133,66,
108,146,194,117,62,113,61,133,66,108,144,194,117,62,113,61,133,66,108,0,106,59,62,41,137,133,66,108,176,181,8,62,62,214,133,66,108,0,140,187,61,126,36,134,66,108,0,218,106,61,185,115,134,66,108,0,236,252,60,186,195,134,66,108,0,200,72,60,78,20,135,66,
108,0,208,199,58,68,101,135,66,108,0,0,0,0,225,122,135,66,108,0,0,0,0,225,122,135,66,108,0,0,128,52,225,122,135,66,108,0,232,222,186,244,179,135,66,108,0,92,14,59,0,237,135,66,108,0,51,62,60,225,37,136,66,108,0,203,217,60,114,94,136,66,108,64,200,64,
61,142,150,136,66,108,192,127,149,61,18,206,136,66,108,160,163,213,61,219,4,137,66,108,96,83,16,62,197,58,137,66,108,144,44,59,62,173,111,137,66,108,240,65,107,62,115,163,137,66,108,92,58,144,62,244,213,137,66,108,160,153,153,62,102,230,137,66,108,154,
153,153,62,102,230,137,66,108,152,153,153,62,102,230,137,66,108,128,201,188,62,40,28,138,66,108,244,157,226,62,22,80,138,66,108,96,127,5,63,16,130,138,66,108,2,233,26,63,245,177,138,66,108,50,126,49,63,167,223,138,66,108,122,48,73,63,9,11,139,66,108,
180,240,97,63,254,51,139,66,108,6,175,123,63,109,90,139,66,108,127,45,139,63,60,126,139,66,108,193,241,152,63,86,159,139,66,108,124,27,167,63,165,189,139,66,108,160,161,181,63,21,217,139,66,108,166,112,189,63,102,230,139,66,108,164,112,189,63,102,230,
139,66,108,160,112,189,63,102,230,139,66,108,93,221,217,63,63,24,140,66,108,118,224,246,63,90,68,140,66,108,173,51,10,64,154,106,140,66,108,146,47,25,64,230,138,140,66,108,30,133,27,64,92,143,140,66,108,31,133,27,64,92,143,140,66,108,52,51,51,64,143,
194,140,66,98,185,30,85,64,61,10,141,66,62,10,119,64,102,102,141,66,226,122,140,64,112,189,141,66,108,195,245,176,64,194,117,142,66,98,0,0,216,64,51,51,143,66,246,40,0,65,143,194,143,66,21,174,19,65,235,81,144,66,108,21,174,19,65,234,81,144,66,108,82,
132,47,65,96,26,145,66,108,129,1,75,65,27,15,146,66,108,12,20,102,65,126,47,147,66,108,246,40,104,65,174,71,147,66,108,246,40,104,65,174,71,147,66,108,246,40,120,65,123,20,148,66,108,246,40,120,65,123,20,148,66,108,56,114,127,65,31,126,148,66,108,178,
113,131,65,250,219,148,66,108,218,59,135,65,208,45,149,66,108,39,21,139,65,109,115,149,66,108,36,251,142,65,163,172,149,66,108,82,235,146,65,79,217,149,66,108,44,227,150,65,84,249,149,66,108,255,255,151,65,0,0,150,66,108,0,0,152,65,0,0,150,66,108,61,
10,153,65,0,0,150,66,108,61,10,153,65,0,0,150,66,108,250,95,155,65,252,251,149,66,108,42,180,157,65,130,240,149,66,108,80,5,160,65,152,221,149,66,108,240,81,162,65,75,195,149,66,108,146,152,164,65,172,161,149,66,108,192,215,166,65,208,120,149,66,108,
12,14,169,65,209,72,149,66,108,10,58,171,65,206,17,149,66,108,86,90,173,65,234,211,148,66,108,150,109,175,65,77,143,148,66,108,0,0,176,65,225,122,148,66,108,0,0,176,65,225,122,148,66,108,255,255,175,65,225,122,148,66,108,111,241,177,65,153,45,148,66,
108,204,210,179,65,50,218,147,66,108,226,162,181,65,226,128,147,66,108,138,96,183,65,226,33,147,66,108,164,10,185,65,111,189,146,66,108,34,160,186,65,201,83,146,66,108,255,31,188,65,52,229,145,66,108,70,137,189,65,247,113,145,66,108,15,219,190,65,91,
250,144,66,108,130,20,192,65,172,126,144,66,108,50,51,193,65,0,0,144,66,108,51,51,193,65,0,0,144,66,108,51,51,193,65,0,0,144,66,108,251,51,194,65,179,122,143,66,108,204,25,195,65,92,242,142,66,108,16,228,195,65,81,103,142,66,108,102,102,196,65,0,0,142,
66,108,102,102,196,65,0,0,142,66,108,101,102,196,65,0,0,142,66,108,43,217,202,65,102,147,142,66,108,88,103,209,65,253,17,143,66,108,187,12,216,65,115,123,143,66,108,19,197,222,65,133,207,143,66,108,20,140,229,65,254,13,144,66,108,102,93,236,65,181,54,
144,66,108,174,52,243,65,144,73,144,66,108,163,112,249,65,174,71,144,66,108,164,112,249,65,174,71,144,66,108,163,112,249,65,174,71,144,66,108,49,249,255,65,182,40,144,66,108,187,60,3,66,225,244,143,66,108,166,118,6,66,82,172,143,66,108,71,168,9,66,54,
79,143,66,108,148,207,12,66,201,221,142,66,108,137,234,15,66,84,88,142,66,108,40,247,18,66,44,191,141,66,108,174,71,19,66,20,174,141,66,108,174,71,19,66,20,174,141,66,98,174,71,23,66,225,250,141,66,174,71,27,66,102,102,142,66,174,71,31,66,10,215,142,
66,98,123,20,31,66,71,225,143,66,133,235,30,66,164,240,144,66,133,235,30,66,30,5,146,66,108,133,235,30,66,30,5,146,66,108,117,229,30,66,57,150,146,66,108,232,237,30,66,76,39,147,66,108,218,4,31,66,251,183,147,66,108,58,42,31,66,232,71,148,66,108,241,
93,31,66,185,214,148,66,108,222,159,31,66,17,100,149,66,108,215,239,31,66,150,239,149,66,108,169,77,32,66,239,120,150,66,108,23,185,32,66,196,255,150,66,108,221,49,33,66,190,131,151,66,108,174,183,33,66,137,4,152,66,108,82,184,33,66,30,5,152,66,108,82,
184,33,66,30,5,152,66,108,82,184,33,66,30,5,152,66,108,228,84,34,66,184,113,152,66,108,30,252,34,66,69,218,152,66,108,151,173,35,66,131,62,153,66,108,220,104,36,66,49,158,153,66,108,117,45,37,66,19,249,153,66,108,229,250,37,66,238,78,154,66,108,168,208,
38,66,139,159,154,66,108,54,174,39,66,183,234,154,66,108,0,147,40,66,65,48,155,66,108,117,126,41,66,254,111,155,66,108,253,111,42,66,196,169,155,66,108,254,102,43,66,110,221,155,66,108,225,122,43,66,71,225,155,66,108,225,122,43,66,71,225,155,66,108,225,
122,43,66,71,225,155,66,108,65,231,44,66,120,46,156,66,108,228,90,46,66,118,114,156,66,108,221,212,47,66,21,173,156,66,108,56,84,49,66,46,222,156,66,108,1,216,50,66,164,5,157,66,108,64,95,52,66,92,35,157,66,108,250,232,53,66,68,55,157,66,108,51,116,55,
66,78,65,157,66,108,123,20,56,66,143,66,157,66,108,123,20,56,66,143,66,157,66,108,123,20,56,66,143,66,157,66,108,191,99,57,66,126,63,157,66,108,74,178,58,66,14,52,157,66,108,70,255,59,66,68,32,157,66,108,123,20,60,66,184,30,157,66,108,123,20,60,66,184,
30,157,66,108,123,20,60,66,184,30,157,66,108,84,127,61,66,218,252,156,66,108,86,230,62,66,246,209,156,66,108,155,72,64,66,39,158,156,66,108,66,165,65,66,142,97,156,66,108,106,251,66,66,83,28,156,66,108,57,74,68,66,160,206,155,66,108,217,144,69,66,169,
120,155,66,108,120,206,70,66,163,26,155,66,108,76,2,72,66,204,180,154,66,108,205,204,72,66,133,107,154,66,108,205,204,72,66,133,107,154,66,108,204,204,72,66,133,107,154,66,108,101,58,75,66,36,101,153,66,108,253,140,77,66,142,79,152,66,108,24,195,79,66,
118,43,151,66,108,0,0,80,66,60,10,151,66,108,0,0,80,66,61,10,151,66,108,205,204,81,66,245,40,150,66,108,206,204,81,66,245,40,150,66,108,148,110,84,66,162,238,148,66,108,237,46,87,66,138,197,147,66,108,23,12,90,66,106,174,146,66,108,1,0,92,66,0,0,146,
66,108,0,0,92,66,0,0,146,66,108,0,0,92,66,0,0,146,66,108,198,218,96,66,44,146,144,66,108,145,216,101,66,220,67,143,66,108,92,143,104,66,184,158,142,66,108,92,143,104,66,184,158,142,66,108,194,245,109,66,174,71,141,66,108,194,245,109,66,174,71,141,66,
108,98,121,111,66,194,235,140,66,108,86,243,112,66,68,134,140,66,108,171,98,114,66,117,23,140,66,108,120,198,115,66,155,159,139,66,108,216,29,117,66,3,31,139,66,108,239,103,118,66,0,150,138,66,108,234,163,119,66,233,4,138,66,108,0,209,120,66,26,108,137,
66,108,122,20,121,66,174,71,137,66,108,122,20,121,66,174,71,137,66,108,122,20,121,66,174,71,137,66,108,43,188,121,66,81,223,136,66,108,55,89,122,66,228,114,136,66,108,59,235,122,66,173,2,136,66,108,217,113,123,66,244,142,135,66,108,186,236,123,66,3,24,
135,66,108,145,91,124,66,37,158,134,66,108,153,153,124,66,235,81,134,66,108,153,153,124,66,235,81,134,66,108,153,153,124,66,184,30,134,66,108,153,153,124,66,184,30,134,66,108,20,189,124,66,153,218,133,66,108,181,217,124,66,173,149,133,66,108,104,239,
124,66,32,80,133,66,108,34,254,124,66,31,10,133,66,108,215,5,125,66,213,195,132,66,108,130,6,125,66,113,125,132,66,108,37,0,125,66,31,55,132,66,108,194,242,124,66,12,241,131,66,108,98,222,124,66,101,171,131,66,108,18,195,124,66,87,102,131,66,108,228,
160,124,66,14,34,131,66,108,238,119,124,66,181,222,130,66,108,73,72,124,66,119,156,130,66,108,21,18,124,66,128,91,130,66,108,0,0,124,66,174,71,130,66,108,0,0,124,66,174,71,130,66,99,109,123,20,252,65,174,71,77,65,108,122,20,252,65,174,71,77,65,108,97,
172,252,65,253,78,74,65,108,25,87,253,65,111,102,71,65,108,54,20,254,65,223,143,68,65,108,63,227,254,65,31,205,65,65,108,175,195,255,65,242,31,63,65,108,123,90,0,66,17,138,60,65,108,61,219,0,66,33,13,58,65,108,204,99,1,66,186,170,55,65,108,207,243,1,
66,100,100,53,65,108,234,138,2,66,146,59,51,65,108,190,40,3,66,166,49,49,65,108,229,204,3,66,240,71,47,65,108,113,61,4,66,123,20,46,65,108,113,61,4,66,123,20,46,65,108,113,61,4,66,123,20,46,65,108,140,172,4,66,19,221,44,65,108,103,31,5,66,69,188,43,65,
108,186,149,5,66,202,178,42,65,108,56,15,6,66,75,193,41,65,108,147,139,6,66,100,232,40,65,108,62,10,7,66,246,40,40,65,108,62,10,7,66,246,40,40,65,108,62,10,7,66,246,40,40,65,108,118,129,7,66,108,116,39,65,108,201,250,7,66,243,215,38,65,108,233,117,8,
66,236,83,38,65,108,137,242,8,66,173,232,37,65,108,88,112,9,66,123,150,37,65,108,5,239,9,66,137,93,37,65,108,64,110,10,66,253,61,37,65,108,183,237,10,66,234,55,37,65,108,25,109,11,66,85,75,37,65,108,20,236,11,66,49,120,37,65,108,87,106,12,66,98,190,37,
65,108,164,112,12,66,144,194,37,65,108,164,112,12,66,144,194,37,65,108,164,112,12,66,144,194,37,65,108,141,4,13,66,57,25,38,65,108,49,151,13,66,88,141,38,65,108,51,40,14,66,163,30,39,65,108,54,183,14,66,189,204,39,65,108,223,67,15,66,54,151,40,65,108,
211,205,15,66,141,125,41,65,108,185,84,16,66,46,127,42,65,108,61,216,16,66,118,155,43,65,108,9,88,17,66,172,209,44,65,108,31,133,17,66,175,71,45,65,108,31,133,17,66,175,71,45,65,108,30,133,17,66,175,71,45,65,108,101,50,18,66,126,58,47,65,108,56,217,18,
66,82,79,49,65,108,45,121,19,66,213,132,51,65,108,222,17,20,66,158,217,53,65,108,234,162,20,66,46,76,56,65,108,243,43,21,66,245,218,58,65,108,162,172,21,66,80,132,61,65,108,164,36,22,66,139,70,64,65,108,173,147,22,66,225,31,67,65,108,117,249,22,66,129,
14,70,65,108,188,85,23,66,137,16,73,65,108,70,168,23,66,14,36,76,65,108,222,240,23,66,23,71,79,65,108,0,0,24,66,0,0,80,65,108,0,0,24,66,0,0,80,65,108,0,0,24,66,255,255,79,65,108,218,94,24,66,146,247,84,65,108,177,173,24,66,131,0,90,65,108,84,236,24,66,
156,23,95,65,108,156,26,25,66,153,57,100,65,108,105,56,25,66,50,99,105,65,108,170,69,25,66,26,145,110,65,108,85,66,25,66,0,192,115,65,108,51,51,25,66,255,255,119,65,108,51,51,25,66,0,0,120,65,108,51,51,25,66,0,0,120,65,108,99,20,25,66,24,81,124,65,108,
206,231,24,66,83,77,128,65,108,144,173,24,66,246,108,130,65,108,208,101,24,66,24,134,132,65,108,185,16,24,66,98,151,134,65,108,0,0,24,66,195,245,134,65,108,0,0,24,66,195,245,134,65,108,205,204,22,66,21,174,133,65,108,205,204,22,66,21,174,133,65,108,150,
213,21,66,205,229,132,65,108,174,217,20,66,124,54,132,65,108,181,217,19,66,144,160,131,65,108,236,81,19,66,41,92,131,65,108,236,81,19,66,41,92,131,65,108,235,81,19,66,41,92,131,65,108,78,142,19,66,151,207,130,65,108,25,199,19,66,40,61,130,65,108,42,252,
19,66,59,165,129,65,108,255,255,19,66,154,153,129,65,108,0,0,20,66,154,153,129,65,108,0,0,20,66,154,153,129,65,108,234,53,20,66,165,195,128,65,108,105,102,20,66,33,209,127,65,108,95,145,20,66,210,17,126,65,108,177,182,20,66,124,74,124,65,108,70,214,20,
66,65,124,122,65,108,11,240,20,66,74,168,120,65,108,238,3,21,66,194,207,118,65,108,228,17,21,66,216,243,116,65,108,123,20,21,66,226,122,116,65,108,123,20,21,66,226,122,116,65,108,123,20,21,66,226,122,116,65,108,18,38,21,66,122,86,114,65,108,201,48,21,
66,61,47,112,65,108,153,52,21,66,140,6,110,65,108,129,49,21,66,201,221,107,65,108,129,39,21,66,85,182,105,65,108,160,22,21,66,145,145,103,65,108,234,254,20,66,220,112,101,65,108,108,224,20,66,148,85,99,65,108,60,187,20,66,16,65,97,65,108,112,143,20,66,
166,52,95,65,108,37,93,20,66,165,49,93,65,108,122,36,20,66,87,57,91,65,108,0,0,20,66,123,20,90,65,108,0,0,20,66,123,20,90,65,108,0,0,20,66,123,20,90,65,108,160,200,19,66,144,107,88,65,108,3,140,19,66,63,206,86,65,108,80,74,19,66,144,61,85,65,108,175,
3,19,66,131,186,83,65,108,80,184,18,66,17,70,82,65,108,97,104,18,66,40,225,80,65,108,22,20,18,66,172,140,79,65,108,164,187,17,66,119,73,78,65,108,70,95,17,66,87,24,77,65,108,53,255,16,66,17,250,75,65,108,174,155,16,66,90,239,74,65,108,243,52,16,66,223,
248,73,65,108,68,203,15,66,60,23,73,65,108,229,94,15,66,2,75,72,65,108,51,51,15,66,0,0,72,65,108,51,51,15,66,0,0,72,65,108,51,51,15,66,0,0,72,65,108,163,196,14,66,176,150,71,65,108,230,84,14,66,155,67,71,65,108,67,228,13,66,248,6,71,65,108,3,115,13,66,
237,224,70,65,108,108,1,13,66,146,209,70,65,108,201,143,12,66,241,216,70,65,108,102,102,12,66,72,225,70,65,108,102,102,12,66,72,225,70,65,108,102,102,12,66,72,225,70,65,108,102,17,12,66,18,6,71,65,108,247,188,11,66,207,59,71,65,108,79,105,11,66,91,130,
71,65,108,164,22,11,66,138,217,71,65,108,41,197,10,66,36,65,72,65,108,21,117,10,66,232,184,72,65,108,152,38,10,66,135,64,73,65,108,231,217,9,66,171,215,73,65,108,50,143,9,66,244,125,74,65,108,102,102,9,66,72,225,74,65,108,102,102,9,66,72,225,74,65,108,
102,102,9,66,72,225,74,65,108,162,21,9,66,94,193,75,65,108,196,199,8,66,82,177,76,65,108,255,124,8,66,138,176,77,65,108,130,53,8,66,99,190,78,65,108,123,241,7,66,48,218,79,65,108,22,177,7,66,60,3,81,65,108,123,116,7,66,201,56,82,65,108,210,59,7,66,17,
122,83,65,108,51,51,7,66,21,174,83,65,108,51,51,7,66,21,174,83,65,108,51,51,7,66,22,174,83,65,108,212,232,6,66,166,142,85,65,108,142,164,6,66,122,125,87,65,108,140,102,6,66,86,121,89,65,108,247,46,6,66,246,128,91,65,108,242,253,5,66,11,147,93,65,108,
156,211,5,66,68,174,95,65,108,16,176,5,66,71,209,97,65,108,101,147,5,66,182,250,99,65,108,174,125,5,66,48,41,102,65,108,248,110,5,66,78,91,104,65,108,77,103,5,66,169,143,106,65,108,102,102,5,66,52,51,107,65,108,102,102,5,66,52,51,107,65,108,102,102,5,
66,52,51,107,65,108,201,97,5,66,79,71,109,65,108,212,99,5,66,172,91,111,65,108,102,102,5,66,247,40,112,65,108,102,102,5,66,247,40,112,65,108,0,0,4,66,205,204,108,65,108,0,0,4,66,205,204,108,65,108,187,82,2,66,125,71,105,65,108,189,154,0,66,31,25,102,
65,108,60,178,253,65,188,67,99,65,108,184,30,251,65,164,112,97,65,108,184,30,251,65,164,112,97,65,108,184,30,251,65,164,112,97,65,108,183,30,251,65,164,112,97,65,108,172,11,251,65,169,113,94,65,108,209,11,251,65,189,113,91,65,108,39,31,251,65,202,114,
88,65,108,162,69,251,65,188,118,85,65,108,40,127,251,65,122,127,82,65,108,148,203,251,65,235,142,79,65,108,122,20,252,65,174,71,77,65,108,123,20,252,65,174,71,77,65,99,109,225,122,25,66,51,51,169,65,98,225,122,25,66,123,20,170,65,112,61,25,66,61,10,171,
65,245,40,25,66,133,235,171,65,108,245,40,25,66,184,30,173,65,108,246,40,25,66,184,30,173,65,108,47,38,25,66,221,211,173,65,108,226,30,25,66,129,136,174,65,108,20,19,25,66,48,60,175,65,108,204,2,25,66,119,238,175,65,108,21,238,24,66,229,158,176,65,108,
252,212,24,66,9,77,177,65,108,145,183,24,66,115,248,177,65,108,153,153,24,66,92,143,178,65,108,153,153,24,66,92,143,178,65,108,153,153,24,66,92,143,178,65,108,153,117,24,66,90,5,179,65,108,178,78,24,66,154,119,179,65,108,253,36,24,66,210,229,179,65,108,
148,248,23,66,187,79,180,65,108,147,201,23,66,18,181,180,65,108,25,152,23,66,149,21,181,65,108,70,100,23,66,8,113,181,65,108,58,46,23,66,47,199,181,65,108,25,246,22,66,212,23,182,65,108,5,188,22,66,195,98,182,65,108,37,128,22,66,203,167,182,65,108,158,
66,22,66,193,230,182,65,108,152,3,22,66,125,31,183,65,108,133,235,21,66,51,51,183,65,108,133,235,21,66,51,51,183,65,108,133,235,21,66,51,51,183,65,108,114,47,21,66,55,213,183,65,108,143,111,20,66,59,100,184,65,108,205,204,19,66,205,204,184,65,108,205,
204,19,66,205,204,184,65,108,21,174,18,66,31,133,185,65,108,21,174,18,66,32,133,185,65,108,161,49,17,66,173,224,186,65,108,86,190,15,66,210,97,188,65,108,34,85,14,66,154,7,190,65,108,236,246,12,66,246,208,191,65,108,148,164,11,66,192,188,193,65,108,242,
94,10,66,192,201,195,65,108,52,51,10,66,124,20,196,65,108,52,51,10,66,123,20,196,65,108,52,51,10,66,122,20,196,65,108,234,10,8,66,16,102,199,65,108,21,206,5,66,96,127,202,65,108,52,51,5,66,174,71,203,65,108,52,51,5,66,174,71,203,65,108,52,51,5,66,174,
71,203,65,108,48,213,3,66,229,218,204,65,108,136,109,2,66,158,74,206,65,108,36,253,0,66,238,149,207,65,108,218,9,255,65,0,188,208,65,108,172,11,252,65,26,188,209,65,108,73,225,250,65,123,20,210,65,108,73,225,250,65,123,20,210,65,108,72,225,250,65,123,
20,210,65,108,49,184,248,65,11,190,210,65,108,81,135,246,65,192,75,211,65,108,16,80,244,65,64,189,211,65,108,216,19,242,65,66,18,212,65,108,23,212,239,65,142,74,212,65,108,62,146,237,65,3,102,212,65,108,191,79,235,65,141,100,212,65,108,11,14,233,65,46,
70,212,65,108,215,163,232,65,112,61,212,65,108,216,163,232,65,113,61,212,65,108,216,163,232,65,113,61,212,65,108,25,49,231,65,85,23,212,65,108,185,192,229,65,190,222,211,65,108,163,83,228,65,208,147,211,65,108,192,234,226,65,187,54,211,65,108,248,134,
225,65,186,199,210,65,108,46,41,224,65,21,71,210,65,108,65,210,222,65,29,181,209,65,108,14,131,221,65,48,18,209,65,108,107,60,220,65,183,94,208,65,108,41,255,218,65,36,155,207,65,108,247,40,218,65,62,10,207,65,108,247,40,218,65,62,10,207,65,108,247,40,
218,65,62,10,207,65,108,196,164,216,65,45,219,205,65,108,50,48,215,65,22,153,204,65,108,48,204,213,65,200,68,203,65,108,163,121,212,65,27,223,201,65,108,98,57,211,65,245,104,200,65,108,247,40,210,65,62,10,199,65,108,247,40,210,65,62,10,199,65,108,247,
40,210,65,62,10,199,65,108,75,195,212,65,247,139,199,65,108,71,99,215,65,57,236,199,65,108,59,7,218,65,198,42,200,65,108,42,92,219,65,113,61,200,65,108,42,92,219,65,113,61,200,65,108,175,71,221,65,113,61,200,65,108,175,71,221,65,113,61,200,65,108,238,
138,226,65,26,4,200,65,108,161,201,231,65,129,135,199,65,108,107,0,237,65,244,199,198,65,108,185,30,241,65,0,0,198,65,108,185,30,241,65,0,0,198,65,108,185,30,241,65,0,0,198,65,108,16,91,246,65,184,223,196,65,108,83,135,251,65,208,124,195,65,108,24,80,
0,66,42,216,193,65,108,72,225,0,66,164,112,193,65,108,72,225,0,66,164,112,193,65,108,72,225,0,66,164,112,193,65,108,53,27,3,66,175,118,191,65,108,199,71,5,66,100,68,189,65,108,154,101,7,66,42,219,186,65,108,84,115,9,66,142,60,184,65,108,162,111,11,66,
58,106,181,65,108,92,143,12,66,21,174,179,65,108,92,143,12,66,21,174,179,65,98,10,215,13,66,21,174,177,65,61,10,15,66,21,174,175,65,92,143,16,66,175,71,173,65,108,215,163,17,66,42,92,171,65,108,215,163,17,66,42,92,171,65,108,184,30,18,66,42,92,171,65,
108,184,30,18,66,42,92,171,65,108,111,144,18,66,208,121,171,65,108,191,2,19,66,15,140,171,65,108,95,117,19,66,218,146,171,65,108,6,232,19,66,47,142,171,65,108,107,90,20,66,15,126,171,65,108,67,204,20,66,132,98,171,65,108,71,225,20,66,42,92,171,65,108,
71,225,20,66,42,92,171,65,108,71,225,20,66,42,92,171,65,108,226,88,21,66,177,78,171,65,108,1,208,21,66,71,53,171,65,108,87,70,22,66,253,15,171,65,108,152,187,22,66,235,222,170,65,108,122,47,23,66,48,162,170,65,108,91,143,23,66,103,102,170,65,108,91,143,
23,66,103,102,170,65,108,91,143,23,66,103,102,170,65,108,188,240,23,66,89,63,170,65,108,4,81,24,66,155,14,170,65,108,246,175,24,66,78,212,169,65,108,84,13,25,66,149,144,169,65,108,227,104,25,66,157,67,169,65,108,225,122,25,66,51,51,169,65,108,225,122,
25,66,51,51,169,65,99,109,122,20,188,65,102,102,74,65,108,122,20,188,65,102,102,74,65,108,63,115,188,65,241,81,72,65,108,52,223,188,65,159,71,70,65,108,21,88,189,65,191,72,68,65,108,146,221,189,65,151,86,66,65,108,88,111,190,65,103,114,64,65,108,10,13,
191,65,100,157,62,65,108,64,182,191,65,186,216,60,65,108,145,106,192,65,139,37,59,65,108,136,41,193,65,237,132,57,65,108,20,174,193,65,225,122,56,65,108,20,174,193,65,225,122,56,65,108,20,174,193,65,225,122,56,65,108,112,72,194,65,192,109,55,65,108,85,
233,194,65,100,112,54,65,108,90,144,195,65,110,131,53,65,108,23,61,196,65,117,167,52,65,108,27,239,196,65,7,221,51,65,108,245,165,197,65,166,36,51,65,108,49,97,198,65,198,126,50,65,108,85,32,199,65,210,235,49,65,108,233,226,199,65,41,108,49,65,108,111,
168,200,65,28,0,49,65,108,105,112,201,65,239,167,48,65,108,87,58,202,65,220,99,48,65,108,184,5,203,65,14,52,48,65,108,174,71,203,65,246,40,48,65,108,174,71,203,65,246,40,48,65,108,174,71,203,65,246,40,48,65,108,163,71,204,65,98,35,48,65,108,106,71,205,
65,101,55,48,65,108,96,70,206,65,244,100,48,65,108,224,67,207,65,239,171,48,65,108,73,63,208,65,43,12,49,65,108,250,55,209,65,106,133,49,65,108,83,45,210,65,94,23,50,65,108,185,30,211,65,169,193,50,65,108,174,71,211,65,72,225,50,65,108,174,71,211,65,
72,225,50,65,108,174,71,211,65,72,225,50,65,108,201,59,212,65,104,224,51,65,108,54,41,213,65,157,247,52,65,108,93,15,214,65,52,38,54,65,108,170,237,214,65,108,107,55,65,108,144,195,215,65,117,198,56,65,108,133,144,216,65,112,54,58,65,108,7,84,217,65,
114,186,59,65,108,20,174,217,65,226,122,60,65,108,20,174,217,65,226,122,60,65,108,20,174,217,65,226,122,60,65,108,215,224,218,65,68,64,63,65,108,126,1,220,65,107,35,66,65,108,80,15,221,65,129,34,69,65,108,160,9,222,65,154,59,72,65,108,207,239,222,65,
186,108,75,65,108,72,193,223,65,215,179,78,65,108,134,125,224,65,216,14,82,65,108,17,36,225,65,151,123,85,65,108,20,174,225,65,206,204,88,65,108,20,174,225,65,206,204,88,65,108,20,174,225,65,206,204,88,65,108,158,80,226,65,50,35,93,65,108,53,215,226,
65,114,136,97,65,108,131,65,227,65,190,249,101,65,108,30,133,227,65,144,194,105,65,108,30,133,227,65,144,194,105,65,108,30,133,227,65,143,194,105,65,108,236,159,224,65,220,221,106,65,108,188,194,221,65,228,66,108,65,108,98,239,218,65,196,240,109,65,108,
225,122,218,65,112,61,110,65,108,225,122,218,65,113,61,110,65,108,225,122,218,65,114,61,110,65,108,76,52,218,65,105,98,108,65,108,239,225,217,65,7,143,106,65,108,254,131,217,65,118,196,104,65,108,181,26,217,65,219,3,103,65,108,88,166,216,65,87,78,101,
65,108,50,39,216,65,255,164,99,65,108,146,157,215,65,230,8,98,65,108,211,9,215,65,18,123,96,65,108,82,108,214,65,130,252,94,65,108,116,197,213,65,43,142,93,65,108,164,21,213,65,247,48,92,65,108,82,184,212,65,32,133,91,65,108,82,184,212,65,31,133,91,65,
108,82,184,212,65,31,133,91,65,108,193,79,212,65,53,205,90,65,108,184,226,211,65,251,31,90,65,108,126,113,211,65,222,125,89,65,108,91,252,210,65,70,231,88,65,108,154,131,210,65,147,92,88,65,108,137,7,210,65,31,222,87,65,108,118,136,209,65,59,108,87,65,
108,180,6,209,65,46,7,87,65,108,148,130,208,65,59,175,86,65,108,0,0,208,65,102,102,86,65,108,0,0,208,65,102,102,86,65,108,0,0,208,65,102,102,86,65,108,182,156,207,65,101,52,86,65,108,76,56,207,65,98,12,86,65,108,2,211,206,65,116,238,85,65,108,24,109,
206,65,177,218,85,65,108,209,6,206,65,35,209,85,65,108,110,160,205,65,210,209,85,65,108,47,58,205,65,188,220,85,65,108,87,212,204,65,220,241,85,65,108,39,111,204,65,34,17,86,65,108,223,10,204,65,125,58,86,65,108,192,167,203,65,208,109,86,65,108,9,70,
203,65,250,170,86,65,108,249,229,202,65,214,241,86,65,108,205,135,202,65,54,66,87,65,108,192,43,202,65,229,155,87,65,108,16,210,201,65,172,254,87,65,108,243,122,201,65,73,106,88,65,108,163,38,201,65,122,222,88,65,108,86,213,200,65,243,90,89,65,108,62,
135,200,65,100,223,89,65,108,143,60,200,65,122,107,90,65,108,120,245,199,65,217,254,90,65,108,38,178,199,65,37,153,91,65,108,197,114,199,65,250,57,92,65,108,126,55,199,65,241,224,92,65,108,117,0,199,65,160,141,93,65,108,207,205,198,65,152,63,94,65,108,
171,159,198,65,103,246,94,65,108,40,118,198,65,152,177,95,65,108,102,102,198,65,0,0,96,65,108,102,102,198,65,0,0,96,65,108,102,102,198,65,0,0,96,65,108,144,244,197,65,64,200,97,65,108,70,142,197,65,78,155,99,65,108,200,51,197,65,1,120,101,65,108,81,229,
196,65,39,93,103,65,108,19,163,196,65,138,73,105,65,108,55,109,196,65,238,59,107,65,108,102,102,196,65,31,133,107,65,108,102,102,196,65,31,133,107,65,108,102,102,196,65,31,133,107,65,108,134,60,196,65,250,111,110,65,108,94,37,196,65,22,94,113,65,108,
252,32,196,65,146,77,116,65,108,99,47,196,65,142,60,119,65,108,137,80,196,65,42,41,122,65,108,102,102,196,65,31,133,123,65,108,102,102,196,65,31,133,123,65,108,102,102,196,65,31,133,123,65,108,118,131,196,65,16,140,125,65,108,117,173,196,65,116,143,127,
65,108,71,228,196,65,0,199,128,65,108,202,39,197,65,55,195,129,65,108,211,119,197,65,189,187,130,65,108,30,133,197,65,72,225,130,65,108,30,133,197,65,72,225,130,65,108,225,122,196,65,21,174,131,65,108,225,122,196,65,21,174,131,65,108,186,232,193,65,154,
248,133,65,108,182,116,191,65,73,99,136,65,108,112,61,190,65,21,174,137,65,108,112,61,190,65,21,174,137,65,108,143,194,189,65,21,174,137,65,108,144,194,189,65,22,174,137,65,108,18,236,188,65,121,57,134,65,108,14,66,188,65,63,187,130,65,108,242,196,187,
65,72,107,126,65,108,15,117,187,65,209,85,119,65,108,42,92,187,65,45,92,115,65,108,41,92,187,65,42,92,115,65,108,41,92,187,65,43,92,115,65,108,11,2,187,65,181,1,110,65,108,74,202,186,65,244,159,104,65,108,8,181,186,65,88,58,99,65,108,83,194,186,65,87,
212,93,65,108,36,242,186,65,100,113,88,65,108,90,68,187,65,241,20,83,65,108,195,184,187,65,110,194,77,65,108,123,20,188,65,102,102,74,65,108,123,20,188,65,102,102,74,65,99,109,236,81,178,65,0,0,168,65,98,236,81,178,65,195,245,166,65,205,204,178,65,123,
20,166,65,195,245,178,65,174,71,165,65,98,185,30,179,65,225,122,164,65,164,112,179,65,205,204,162,65,144,194,179,65,20,174,161,65,108,144,194,179,65,20,174,161,65,108,171,68,180,65,100,109,160,65,108,164,214,180,65,156,51,159,65,108,29,120,181,65,131,
1,158,65,108,174,40,182,65,222,215,156,65,108,232,231,182,65,108,183,155,65,108,79,181,183,65,228,160,154,65,108,226,122,184,65,20,174,153,65,108,226,122,184,65,20,174,153,65,108,226,122,184,65,20,174,153,65,108,2,3,186,65,42,213,151,65,108,71,162,187,
65,112,16,150,65,108,168,87,189,65,9,97,148,65,108,12,34,191,65,8,200,146,65,108,226,122,192,65,20,174,145,65,108,226,122,192,65,20,174,145,65,108,93,143,194,65,0,0,144,65,108,52,51,195,65,164,112,143,65,98,113,61,196,65,113,61,142,65,165,112,197,65,
51,51,141,65,93,143,198,65,123,20,140,65,98,21,174,199,65,195,245,138,65,247,40,200,65,225,122,138,65,195,245,200,65,143,194,137,65,108,195,245,200,65,144,194,137,65,108,106,57,203,65,14,233,135,65,108,2,148,205,65,30,45,134,65,108,8,4,208,65,217,143,
132,65,108,240,135,210,65,72,18,131,65,108,26,30,213,65,96,181,129,65,108,226,196,215,65,0,122,128,65,108,147,122,218,65,228,193,126,65,108,195,245,218,65,102,102,126,65,108,195,245,218,65,102,102,126,65,108,144,194,219,65,102,102,126,65,108,144,194,
219,65,102,102,126,65,108,144,194,219,65,102,102,126,65,108,153,61,222,65,27,183,124,65,108,158,194,224,65,212,71,123,65,108,2,80,227,65,125,25,122,65,108,144,194,227,65,133,235,121,65,108,144,194,227,65,133,235,121,65,108,144,194,227,65,134,235,121,
65,108,114,6,230,65,76,57,121,65,108,15,78,232,65,64,193,120,65,108,241,151,234,65,178,131,120,65,108,144,194,235,65,226,122,120,65,108,144,194,235,65,225,122,120,65,108,144,194,235,65,226,122,120,65,108,103,194,237,65,196,143,120,65,108,21,193,239,65,
202,215,120,65,108,82,189,241,65,198,82,121,65,108,218,181,243,65,103,0,122,65,108,106,169,245,65,63,224,122,65,108,195,150,247,65,192,241,123,65,108,21,174,247,65,0,0,124,65,108,21,174,247,65,0,0,124,65,98,82,184,248,65,0,0,124,65,21,174,249,65,154,
153,125,65,82,184,250,65,102,102,126,65,108,82,184,250,65,102,102,126,65,108,17,155,254,65,236,218,128,65,108,178,51,1,66,214,179,130,65,108,154,153,1,66,184,30,131,65,108,154,153,1,66,184,30,131,65,108,154,153,6,66,102,102,136,65,108,154,153,6,66,102,
102,136,65,108,154,153,6,66,102,102,136,65,108,99,145,8,66,186,72,138,65,108,153,148,10,66,25,248,139,65,108,241,161,12,66,109,115,141,65,108,28,184,14,66,198,185,142,65,108,1,0,15,66,71,225,142,65,108,0,0,15,66,71,225,142,65,98,20,174,15,66,71,225,142,
65,174,71,16,66,143,194,143,65,195,245,16,66,122,20,144,65,98,113,61,18,66,122,20,144,65,72,225,18,66,122,20,152,65,41,92,20,66,122,20,152,65,108,41,92,20,66,122,20,152,65,108,92,165,20,66,190,22,152,65,108,105,238,20,66,82,32,152,65,108,34,55,21,66,
48,49,152,65,108,87,127,21,66,78,73,152,65,108,219,198,21,66,156,104,152,65,108,128,13,22,66,5,143,152,65,108,25,83,22,66,115,188,152,65,108,120,151,22,66,198,240,152,65,108,115,218,22,66,223,43,153,65,108,223,27,23,66,150,109,153,65,108,184,30,23,66,
163,112,153,65,108,184,30,23,66,163,112,153,65,108,184,30,23,66,163,112,153,65,108,99,92,23,66,166,183,153,65,108,53,152,23,66,188,4,154,65,108,6,210,23,66,181,87,154,65,108,178,9,24,66,90,176,154,65,108,21,63,24,66,116,14,155,65,108,13,114,24,66,198,
113,155,65,108,30,133,24,66,153,153,155,65,108,30,133,24,66,153,153,155,65,98,132,235,25,66,143,194,157,65,30,133,24,66,153,153,155,65,30,133,24,66,153,153,155,65,108,30,133,24,66,153,153,155,65,108,49,133,24,66,253,255,155,65,108,181,130,24,66,65,102,
156,65,108,172,125,24,66,38,204,156,65,108,24,118,24,66,105,49,157,65,108,255,107,24,66,201,149,157,65,108,103,95,24,66,8,249,157,65,108,88,80,24,66,228,90,158,65,108,220,62,24,66,31,187,158,65,108,253,42,24,66,124,25,159,65,108,202,20,24,66,191,117,
159,65,108,79,252,23,66,172,207,159,65,108,157,225,23,66,10,39,160,65,108,197,196,23,66,161,123,160,65,108,20,174,23,66,81,184,160,65,108,20,174,23,66,81,184,160,65,108,20,174,23,66,81,184,160,65,108,15,146,23,66,224,254,160,65,108,80,116,23,66,138,66,
161,65,108,233,84,23,66,38,131,161,65,108,239,51,23,66,137,192,161,65,108,118,17,23,66,141,250,161,65,108,150,237,22,66,13,49,162,65,108,101,200,22,66,229,99,162,65,108,250,161,22,66,245,146,162,65,108,110,122,22,66,30,190,162,65,108,219,81,22,66,70,
229,162,65,108,90,40,22,66,84,8,163,65,108,7,254,21,66,48,39,163,65,108,133,235,21,66,50,51,163,65,108,133,235,21,66,50,51,163,65,108,133,235,21,66,50,51,163,65,108,253,169,21,66,202,91,163,65,108,135,103,21,66,199,125,163,65,108,76,36,21,66,21,153,163,
65,108,121,224,20,66,162,173,163,65,108,55,156,20,66,97,187,163,65,108,180,87,20,66,73,194,163,65,108,235,81,20,66,142,194,163,65,108,235,81,20,66,142,194,163,65,108,133,235,19,66,142,194,163,65,108,132,235,19,66,142,194,163,65,108,71,111,19,66,74,207,
163,65,108,224,242,18,66,151,207,163,65,108,159,118,18,66,116,195,163,65,108,164,112,18,66,142,194,163,65,108,164,112,18,66,142,194,163,65,108,62,10,18,66,142,194,163,65,108,62,10,18,66,142,194,163,65,108,23,216,17,66,5,174,163,65,108,124,165,17,66,134,
158,163,65,108,142,114,17,66,26,148,163,65,108,110,63,17,66,201,142,163,65,108,60,12,17,66,150,142,163,65,108,26,217,16,66,130,147,163,65,108,39,166,16,66,136,157,163,65,108,132,115,16,66,162,172,163,65,108,83,65,16,66,200,192,163,65,108,114,61,16,66,
142,194,163,65,108,113,61,16,66,142,194,163,65,108,52,51,15,66,193,245,164,65,108,52,51,15,66,193,245,164,65,108,203,224,14,66,61,126,165,65,108,230,145,14,66,201,14,166,65,108,236,81,14,66,91,143,166,65,108,236,81,14,66,91,143,166,65,98,226,122,13,66,
245,40,168,65,21,174,12,66,30,133,169,65,134,235,11,66,204,204,170,65,108,11,215,9,66,122,20,174,65,108,174,71,255,65,102,102,186,65,108,174,71,255,65,102,102,186,65,108,111,139,250,65,57,247,187,65,108,171,188,245,65,246,74,189,65,108,119,222,240,65,
196,96,190,65,108,133,235,239,65,92,143,190,65,108,133,235,239,65,92,143,190,65,108,134,235,239,65,92,143,190,65,108,12,26,235,65,206,114,191,65,108,192,62,230,65,82,24,192,65,108,187,92,225,65,124,127,192,65,108,21,174,221,65,214,163,192,65,108,20,174,
221,65,215,163,192,65,108,10,215,219,65,215,163,192,65,108,10,215,219,65,215,163,192,65,108,64,188,217,65,112,134,192,65,108,155,163,215,65,38,78,192,65,108,113,142,213,65,28,251,191,65,108,24,126,211,65,134,141,191,65,108,227,115,209,65,172,5,191,65,
108,30,113,207,65,227,99,190,65,108,21,119,205,65,148,168,189,65,108,10,135,203,65,54,212,188,65,108,58,162,201,65,82,231,187,65,108,41,92,201,65,143,194,187,65,108,41,92,201,65,143,194,187,65,108,41,92,201,65,143,194,187,65,108,244,223,199,65,0,20,186,
65,108,178,78,198,65,252,120,184,65,108,103,169,196,65,137,242,182,65,108,30,241,194,65,161,129,181,65,108,243,38,193,65,49,39,180,65,108,9,76,191,65,21,228,178,65,108,174,71,191,65,71,225,178,65,108,174,71,191,65,71,225,178,65,108,174,71,191,65,71,225,
178,65,108,248,166,190,65,16,135,178,65,108,248,10,190,65,237,36,178,65,108,17,116,189,65,30,187,177,65,108,165,226,188,65,230,73,177,65,108,15,87,188,65,142,209,176,65,108,170,209,187,65,98,82,176,65,108,41,92,187,65,10,215,175,65,108,41,92,187,65,10,
215,175,65,98,72,225,186,65,194,245,174,65,236,81,178,65,123,20,174,65,246,40,178,65,164,112,173,65,108,246,40,178,65,164,112,173,65,108,62,32,178,65,159,10,173,65,108,163,28,178,65,75,164,172,65,108,39,30,178,65,234,61,172,65,108,199,36,178,65,190,215,
171,65,108,246,40,178,65,20,174,171,65,108,246,40,178,65,21,174,171,65,108,246,40,178,65,21,174,171,65,108,190,28,178,65,162,7,171,65,108,221,24,178,65,201,96,170,65,108,83,29,178,65,243,185,169,65,108,31,42,178,65,139,19,169,65,108,55,63,178,65,253,
109,168,65,108,236,81,178,65,0,0,168,65,108,236,81,178,65,0,0,168,65,99,109,72,225,188,65,62,10,141,66,108,72,225,188,65,62,10,141,66,108,164,89,188,65,206,127,141,66,108,172,186,187,65,135,243,141,66,108,195,4,187,65,30,101,142,66,108,95,56,186,65,75,
212,142,66,108,123,20,186,65,103,230,142,66,108,123,20,186,65,103,230,142,66,108,123,20,186,65,103,230,142,66,108,246,45,185,65,183,79,143,66,108,173,50,184,65,5,182,143,66,108,64,35,183,65,14,25,144,66,108,94,0,182,65,147,120,144,66,108,192,202,180,
65,87,212,144,66,108,45,131,179,65,31,44,145,66,108,118,42,178,65,179,127,145,66,108,120,193,176,65,222,206,145,66,108,26,73,175,65,109,25,146,66,108,76,194,173,65,49,95,146,66,108,9,46,172,65,252,159,146,66,108,123,20,172,65,216,163,146,66,108,123,20,
172,65,216,163,146,66,108,123,20,172,65,216,163,146,66,108,116,103,170,65,77,224,146,66,108,225,174,168,65,83,23,147,66,108,218,235,166,65,198,72,147,66,108,128,31,165,65,135,116,147,66,108,251,74,163,65,121,154,147,66,108,118,111,161,65,132,186,147,
66,108,33,142,159,65,148,212,147,66,108,48,168,157,65,152,232,147,66,108,218,190,155,65,131,246,147,66,108,89,211,153,65,76,254,147,66,108,0,0,152,65,0,0,148,66,108,0,0,152,65,0,0,148,66,108,0,0,152,65,0,0,148,66,108,134,101,148,65,24,227,147,66,108,
250,209,144,65,179,186,147,66,108,166,71,141,65,235,134,147,66,108,207,200,137,65,224,71,147,66,108,176,87,134,65,187,253,146,66,108,126,246,130,65,171,168,146,66,108,196,78,127,65,231,72,146,66,108,174,71,125,65,246,40,146,66,108,174,71,125,65,246,40,
146,66,108,174,71,109,65,10,87,145,66,108,173,71,109,65,10,87,145,66,108,223,181,81,65,238,44,144,66,108,178,181,53,65,72,47,143,66,108,16,89,25,65,189,94,142,66,108,92,143,22,65,205,76,142,66,108,92,143,22,65,205,76,142,66,98,41,92,3,65,144,194,141,
66,61,10,223,64,51,51,141,66,194,245,184,64,225,122,140,66,108,123,20,150,64,205,204,139,66,98,205,204,132,64,164,112,139,66,62,10,103,64,154,25,139,66,226,122,68,64,236,209,138,66,108,32,133,43,64,154,153,138,66,108,33,133,43,64,154,153,138,66,108,20,
243,30,64,149,123,138,66,108,14,149,18,64,147,88,138,66,108,250,114,6,64,171,48,138,66,108,57,41,245,63,245,3,138,66,108,51,51,243,63,0,0,138,66,108,51,51,243,63,0,0,138,66,108,51,51,243,63,0,0,138,66,108,70,7,234,63,228,240,137,66,108,156,14,225,63,
248,223,137,66,108,244,78,216,63,69,205,137,66,108,228,205,207,63,218,184,137,66,108,225,144,199,63,193,162,137,66,108,46,157,191,63,10,139,137,66,108,226,247,183,63,195,113,137,66,108,225,165,176,63,253,86,137,66,108,219,171,169,63,201,58,137,66,108,
68,14,163,63,57,29,137,66,108,91,209,156,63,96,254,136,66,108,29,249,150,63,82,222,136,66,108,51,51,147,63,174,199,136,66,108,51,51,147,63,174,199,136,66,108,51,51,147,63,174,199,136,66,108,24,134,143,63,103,170,136,66,108,210,55,140,63,108,140,136,66,
108,127,74,137,63,210,109,136,66,108,253,191,134,63,172,78,136,66,108,238,153,132,63,14,47,136,66,108,177,217,130,63,12,15,136,66,108,101,128,129,63,187,238,135,66,108,231,142,128,63,47,206,135,66,108,210,5,128,63,125,173,135,66,108,250,202,127,63,187,
140,135,66,108,254,255,127,63,225,122,135,66,108,0,0,128,63,225,122,135,66,108,0,0,128,63,225,122,135,66,108,148,178,128,63,31,66,135,66,108,124,26,130,63,147,9,135,66,108,208,54,132,63,97,209,134,66,108,56,6,135,63,173,153,134,66,108,230,134,138,63,
154,98,134,66,108,158,182,142,63,77,44,134,66,108,178,146,147,63,231,246,133,66,108,144,194,149,63,70,225,133,66,108,143,194,149,63,71,225,133,66,108,144,194,149,63,71,225,133,66,108,132,92,170,63,249,21,133,66,108,40,122,193,63,11,79,132,66,108,36,133,
203,63,0,0,132,66,108,31,133,203,63,0,0,132,66,98,164,112,221,63,164,112,131,66,41,92,239,63,72,225,130,66,82,184,254,63,174,71,130,66,108,84,184,254,63,174,71,130,66,108,24,127,7,64,127,136,129,66,108,170,109,14,64,75,198,128,66,108,106,35,20,64,145,
1,128,66,108,180,156,24,64,153,117,126,66,108,172,214,27,64,252,228,124,66,108,64,207,29,64,75,82,123,66,108,46,133,30,64,135,190,121,66,108,0,248,29,64,179,42,120,66,108,206,204,28,64,61,10,119,66,108,205,204,28,64,61,10,119,66,98,205,204,28,64,215,
163,116,66,62,10,23,64,112,61,114,66,92,143,18,64,10,215,111,66,98,122,20,14,64,164,112,109,66,31,133,11,64,184,30,108,66,153,153,9,64,112,61,106,66,108,154,153,9,64,112,61,106,66,108,244,238,7,64,219,62,105,66,108,110,16,7,64,67,63,104,66,108,146,254,
6,64,74,63,103,66,108,110,185,7,64,149,63,102,66,108,136,64,9,64,199,64,101,66,108,154,153,9,64,122,20,101,66,108,153,153,9,64,122,20,101,66,108,153,153,9,64,122,20,101,66,108,161,19,11,64,18,171,100,66,108,122,225,12,64,251,66,100,66,108,252,1,15,64,
118,220,99,66,108,204,115,17,64,197,119,99,66,108,88,53,20,64,41,21,99,66,108,221,68,23,64,224,180,98,66,108,102,160,26,64,41,87,98,66,108,206,69,30,64,63,252,97,66,108,190,50,34,64,93,164,97,66,108,180,100,38,64,186,79,97,66,108,153,153,41,64,122,20,
97,66,108,153,153,41,64,122,20,97,66,108,152,153,41,64,122,20,97,66,108,71,66,46,64,253,213,96,66,108,112,27,51,64,78,155,96,66,108,250,33,56,64,146,100,96,66,108,173,82,61,64,236,49,96,66,108,56,170,66,64,125,3,96,66,108,46,37,72,64,98,217,95,66,108,
15,192,77,64,183,179,95,66,108,68,119,83,64,147,146,95,66,108,38,71,89,64,12,118,95,66,108,251,43,95,64,52,94,95,66,108,254,33,101,64,26,75,95,66,108,102,102,102,64,173,71,95,66,108,102,102,102,64,173,71,95,66,108,102,102,102,64,173,71,95,66,108,107,
218,112,64,170,38,95,66,108,126,101,123,64,13,14,95,66,108,112,0,131,64,231,253,94,66,108,228,82,136,64,65,246,94,66,108,30,133,139,64,193,245,94,66,108,30,133,139,64,193,245,94,66,108,20,174,167,64,193,245,94,66,98,174,71,177,64,193,245,94,66,71,225,
186,64,193,245,94,66,204,204,196,64,193,245,94,66,108,204,204,196,64,193,245,94,66,108,2,38,202,64,202,234,94,66,108,31,121,207,64,73,215,94,66,108,187,194,212,64,74,187,94,66,108,117,255,217,64,223,150,94,66,108,242,43,223,64,31,106,94,66,108,227,68,
228,64,39,53,94,66,108,5,71,233,64,26,248,93,66,108,35,47,238,64,29,179,93,66,108,26,250,242,64,93,102,93,66,108,245,40,244,64,234,81,93,66,108,245,40,244,64,234,81,93,66,108,244,40,244,64,234,81,93,66,108,41,113,248,64,214,255,92,66,108,45,151,252,64,
4,167,92,66,108,45,76,0,65,171,71,92,66,108,16,57,2,65,9,226,91,66,108,4,17,4,65,94,118,91,66,108,218,210,5,65,241,4,91,66,108,115,125,7,65,9,142,90,66,108,191,15,9,65,243,17,90,66,108,187,136,10,65,254,144,89,66,108,51,51,11,65,234,81,89,66,108,51,51,
11,65,234,81,89,66,108,51,51,11,65,234,81,89,66,108,72,97,16,65,234,104,87,66,108,244,43,21,65,245,111,85,66,108,164,112,21,65,234,81,85,66,108,164,112,21,65,234,81,85,66,108,164,112,21,65,254,255,84,66,108,164,112,21,65,254,255,84,66,108,218,56,24,65,
213,189,83,66,108,149,64,27,65,249,132,82,66,108,227,133,30,65,51,86,81,66,108,31,133,31,65,254,255,80,66,108,31,133,31,65,254,255,80,66,108,31,133,31,65,254,255,80,66,108,219,137,32,65,8,177,80,66,108,12,158,33,65,110,101,80,66,108,2,193,34,65,95,29,
80,66,108,2,242,35,65,9,217,79,66,108,74,48,37,65,153,152,79,66,108,15,123,38,65,56,92,79,66,108,123,209,39,65,13,36,79,66,108,181,50,41,65,58,240,78,66,108,218,157,42,65,226,192,78,66,108,2,18,44,65,35,150,78,66,108,236,81,44,65,90,143,78,66,108,236,
81,44,65,90,143,78,66,108,236,81,44,65,90,143,78,66,108,236,81,44,65,90,143,78,66,108,183,159,45,65,48,112,78,66,108,83,243,46,65,59,85,78,66,108,229,75,48,65,141,62,78,66,108,146,168,49,65,52,44,78,66,108,123,8,51,65,61,30,78,66,108,190,106,52,65,175,
20,78,66,108,120,206,53,65,146,15,78,66,108,198,50,55,65,233,14,78,66,108,196,150,56,65,179,18,78,66,108,142,249,57,65,239,26,78,66,108,65,90,59,65,151,39,78,66,108,236,81,60,65,49,51,78,66,108,236,81,60,65,49,51,78,66,108,236,81,60,65,49,51,78,66,108,
197,59,62,65,211,75,78,66,108,21,32,64,65,140,106,78,66,108,166,253,65,65,72,143,78,66,108,70,211,67,65,241,185,78,66,108,200,159,69,65,105,234,78,66,108,6,98,71,65,147,32,79,66,108,224,24,73,65,76,92,79,66,108,62,195,74,65,110,157,79,66,108,236,81,76,
65,69,225,79,66,108,236,81,76,65,69,225,79,66,108,236,81,76,65,69,225,79,66,108,202,130,80,65,229,183,80,66,108,104,135,84,65,168,155,81,66,108,54,93,88,65,252,139,82,66,108,188,1,92,65,71,136,83,66,108,169,114,95,65,233,143,84,66,108,200,173,98,65,56,
162,85,66,108,6,177,101,65,133,190,86,66,108,113,61,102,65,192,245,86,66,108,113,61,102,65,192,245,86,66,98,82,184,110,65,8,215,89,66,113,61,118,65,151,153,92,66,144,194,125,65,172,71,95,66,98,246,40,132,65,172,71,99,66,62,10,137,65,131,235,102,66,174,
71,141,65,90,143,106,66,108,92,143,146,65,182,30,111,66,108,92,143,146,65,181,30,111,66,108,145,138,152,65,132,52,116,66,108,253,5,159,65,110,34,121,66,108,11,215,161,65,182,30,123,66,108,10,215,161,65,182,30,123,66,98,102,102,164,65,8,215,124,66,184,
30,167,65,28,133,126,66,10,215,169,65,122,20,128,66,98,92,143,172,65,102,230,128,66,20,174,173,65,204,76,129,66,153,153,175,65,102,230,129,66,108,163,112,177,65,0,128,130,66,108,163,112,177,65,0,128,130,66,108,225,92,179,65,173,35,131,66,108,201,39,181,
65,77,205,131,66,108,52,208,182,65,114,124,132,66,108,20,85,184,65,173,48,133,66,108,112,181,185,65,138,233,133,66,108,102,240,186,65,147,166,134,66,108,45,5,188,65,79,103,135,66,108,102,102,188,65,51,179,135,66,108,102,102,188,65,51,179,135,66,108,102,
102,188,65,51,179,135,66,108,37,240,188,65,228,53,136,66,108,151,95,189,65,36,186,136,66,108,116,180,189,65,159,63,137,66,108,136,238,189,65,254,197,137,66,108,172,13,190,65,236,76,138,66,108,204,17,190,65,18,212,138,66,108,231,250,189,65,26,91,139,66,
108,10,201,189,65,174,225,139,66,108,85,124,189,65,120,103,140,66,108,250,20,189,65,33,236,140,66,108,72,225,188,65,215,35,141,66,108,72,225,188,65,215,35,141,66,99,109,195,245,16,66,62,10,132,66,108,195,245,16,66,62,10,132,66,108,62,132,14,66,180,163,
132,66,108,43,4,12,66,87,45,133,66,108,34,119,9,66,208,166,133,66,108,199,222,6,66,208,15,134,66,108,192,60,4,66,20,104,134,66,108,191,146,1,66,100,175,134,66,108,238,196,253,65,146,229,134,66,108,66,91,248,65,123,10,135,66,108,239,235,242,65,9,30,135,
66,108,114,122,237,65,46,32,135,66,108,68,10,232,65,232,16,135,66,108,225,158,226,65,67,240,134,66,108,193,59,221,65,82,190,134,66,108,86,228,215,65,54,123,134,66,108,11,156,210,65,26,39,134,66,108,66,102,205,65,51,194,133,66,108,79,70,200,65,194,76,
133,66,108,122,63,195,65,18,199,132,66,108,0,0,192,65,102,102,132,66,108,0,0,192,65,102,102,132,66,108,0,0,192,65,102,102,132,66,108,204,169,189,65,46,102,131,66,108,30,33,187,65,193,109,130,66,108,148,103,184,65,190,125,129,66,108,0,0,184,65,41,92,129,
66,108,0,0,184,65,41,92,129,66,98,164,112,181,65,0,128,128,66,205,204,178,65,41,92,127,66,0,0,176,65,82,184,125,66,98,51,51,173,65,123,20,124,66,205,204,170,65,31,133,122,66,0,0,168,65,10,215,120,66,108,255,255,167,65,10,215,120,66,108,246,128,161,65,
229,15,116,66,108,69,126,155,65,185,32,111,66,108,176,71,153,65,248,40,109,66,108,174,71,153,65,246,40,109,66,98,31,133,151,65,154,153,107,66,143,194,149,65,123,20,106,66,133,235,147,65,92,143,104,66,98,194,245,140,65,20,174,98,66,205,204,132,65,92,143,
92,66,133,235,117,65,143,194,85,66,108,134,235,117,65,142,194,85,66,108,12,45,116,65,236,136,81,66,108,94,71,115,65,15,75,77,66,108,16,59,115,65,175,11,73,66,108,40,8,116,65,132,205,68,66,108,206,204,116,65,91,143,66,66,108,205,204,116,65,92,143,66,66,
108,206,204,116,65,92,143,66,66,108,162,131,119,65,28,117,61,66,108,188,62,123,65,44,101,56,66,108,184,251,127,65,202,98,51,66,108,199,219,130,65,43,113,46,66,108,75,55,134,65,119,147,41,66,108,63,14,138,65,204,204,36,66,108,42,92,139,65,235,81,35,66,
108,41,92,139,65,235,81,35,66,108,43,92,139,65,235,81,35,66,108,19,98,144,65,251,247,29,66,108,79,239,149,65,228,191,24,66,108,83,0,156,65,252,172,19,66,108,124,20,160,65,92,143,16,66,108,123,20,160,65,92,143,16,66,108,123,20,160,65,91,143,16,66,108,
38,214,159,65,90,42,15,66,108,148,187,159,65,60,196,13,66,108,216,196,159,65,230,93,12,66,108,234,241,159,65,63,248,10,66,108,173,66,160,65,42,148,9,66,108,239,182,160,65,139,50,8,66,108,100,78,161,65,70,212,6,66,108,172,8,162,65,58,122,5,66,108,123,
20,162,65,101,102,5,66,108,123,20,162,65,102,102,5,66,108,124,20,162,65,102,102,5,66,108,4,65,164,65,238,173,2,66,108,120,178,166,65,61,4,0,66,108,72,103,169,65,14,214,250,65,108,184,93,172,65,236,199,245,65,108,229,147,175,65,80,225,240,65,108,190,7,
179,65,93,37,236,65,108,124,20,180,65,204,204,234,65,108,123,20,180,65,204,204,234,65,108,123,20,180,65,204,204,234,65,108,4,222,181,65,38,136,232,65,108,245,137,183,65,92,45,230,65,108,61,23,185,65,239,189,227,65,108,221,132,186,65,111,59,225,65,108,
236,209,187,65,118,167,222,65,108,148,253,188,65,170,3,220,65,108,22,7,190,65,190,81,217,65,108,225,122,190,65,0,0,216,65,108,225,122,190,65,255,255,215,65,108,225,122,190,65,255,255,215,65,108,158,52,191,65,193,238,211,65,108,21,186,191,65,135,213,207,
65,108,241,10,192,65,241,182,203,65,108,254,38,192,65,162,149,199,65,108,123,20,192,65,255,255,195,65,108,123,20,192,65,255,255,195,65,98,123,20,192,65,204,204,194,65,123,20,192,65,19,174,193,65,123,20,192,65,224,122,192,65,108,246,40,194,65,255,255,
193,65,108,62,10,195,65,224,122,194,65,108,113,61,196,65,132,235,195,65,108,41,92,199,65,255,255,199,65,108,40,92,199,65,254,255,199,65,108,15,13,201,65,84,102,202,65,108,32,220,202,65,67,182,204,65,108,49,200,204,65,80,238,206,65,108,9,208,206,65,14,
13,209,65,108,91,242,208,65,36,17,211,65,108,201,45,211,65,70,249,212,65,108,225,122,212,65,0,0,214,65,108,225,122,212,65,255,255,213,65,108,225,122,212,65,255,255,213,65,108,48,6,214,65,131,7,215,65,108,43,158,215,65,240,250,215,65,108,207,65,217,65,
172,217,216,65,108,14,240,218,65,40,163,217,65,108,213,167,220,65,226,86,218,65,108,11,104,222,65,103,244,218,65,108,145,47,224,65,84,123,219,65,108,68,253,225,65,81,235,219,65,108,252,207,227,65,23,68,220,65,108,142,166,229,65,110,133,220,65,108,72,
225,230,65,214,163,220,65,108,71,225,230,65,214,163,220,65,108,40,92,235,65,214,163,220,65,108,39,92,235,65,214,163,220,65,108,228,65,238,65,94,134,220,65,108,58,37,241,65,220,67,220,65,108,81,4,244,65,125,220,219,65,108,82,221,246,65,130,80,219,65,108,
107,174,249,65,68,160,218,65,108,122,20,252,65,132,235,217,65,108,122,20,252,65,132,235,217,65,108,122,20,252,65,132,235,217,65,108,220,112,255,65,50,207,216,65,108,251,94,1,66,60,136,215,65,108,213,252,2,66,114,23,214,65,108,243,144,4,66,191,125,212,
65,108,83,26,6,66,42,188,210,65,108,143,194,6,66,132,235,209,65,108,143,194,6,66,132,235,209,65,108,143,194,6,66,132,235,209,65,108,32,42,9,66,202,144,206,65,108,118,123,11,66,156,249,202,65,108,184,30,12,66,132,235,201,65,108,184,30,12,66,132,235,201,
65,108,184,30,12,66,132,235,201,65,108,146,80,13,66,58,39,200,65,108,88,141,14,66,19,130,198,65,108,62,212,15,66,30,253,196,65,108,117,36,17,66,82,153,195,65,108,35,125,18,66,147,87,194,65,108,110,221,19,66,175,56,193,65,108,0,0,20,66,184,30,193,65,108,
0,0,20,66,184,30,193,65,108,61,10,21,66,102,102,192,65,108,61,10,21,66,102,102,192,65,108,70,248,21,66,20,200,191,65,108,14,226,22,66,42,18,191,65,108,215,163,23,66,102,102,190,65,108,215,163,23,66,102,102,190,65,108,123,20,24,66,133,235,189,65,98,123,
20,25,66,123,20,194,65,10,215,25,66,102,102,198,65,143,194,26,66,92,143,202,65,98,194,245,28,66,194,245,212,65,10,215,31,66,82,184,222,65,112,61,34,66,184,30,233,65,108,112,61,34,66,184,30,233,65,108,176,214,35,66,208,115,240,65,108,132,64,37,66,121,
239,247,65,108,6,122,38,66,231,140,255,65,108,108,130,39,66,158,163,3,66,108,14,89,40,66,195,140,7,66,108,132,235,40,66,0,0,11,66,108,132,235,40,66,0,0,11,66,108,132,235,40,66,0,0,11,66,108,198,219,42,66,186,22,13,66,108,176,176,44,66,150,69,15,66,108,
21,105,46,66,48,139,17,66,108,220,3,48,66,17,230,19,66,108,254,127,49,66,186,84,22,66,108,136,220,50,66,155,213,24,66,108,224,122,51,66,123,20,26,66,108,224,122,51,66,123,20,26,66,98,173,71,59,66,123,20,42,66,244,40,59,66,0,0,61,66,122,20,57,66,144,194,
78,66,108,122,20,57,66,144,194,78,66,108,50,75,56,66,209,154,84,66,108,99,55,55,66,35,103,90,66,108,50,51,55,66,226,122,90,66,108,50,51,55,66,226,122,90,66,108,224,122,52,66,124,20,90,66,108,214,163,50,66,206,204,89,66,108,214,163,50,66,206,204,89,66,
108,233,168,49,66,57,154,89,66,108,197,171,48,66,62,116,89,66,108,12,173,47,66,246,90,89,66,108,97,173,46,66,114,78,89,66,108,104,173,45,66,185,78,89,66,108,234,81,45,66,237,81,89,66,108,234,81,45,66,237,81,89,66,108,234,81,45,66,237,81,89,66,108,30,
199,44,66,42,93,89,66,108,15,61,44,66,83,111,89,66,108,20,180,43,66,92,136,89,66,108,133,44,43,66,55,168,89,66,108,185,166,42,66,205,206,89,66,108,6,35,42,66,7,252,89,66,108,192,161,41,66,200,47,90,66,108,57,35,41,66,238,105,90,66,108,194,167,40,66,84,
170,90,66,108,171,47,40,66,210,240,90,66,108,65,187,39,66,57,61,91,66,108,205,74,39,66,90,143,91,66,108,60,10,39,66,145,194,91,66,108,60,10,39,66,145,194,91,66,108,60,10,39,66,145,194,91,66,108,5,169,38,66,167,34,92,66,108,186,76,38,66,123,135,92,66,
108,150,245,37,66,203,240,92,66,108,210,163,37,66,85,94,93,66,108,162,87,37,66,210,207,93,66,108,54,17,37,66,249,68,94,66,108,187,208,36,66,127,189,94,66,108,91,150,36,66,25,57,95,66,108,59,98,36,66,117,183,95,66,108,125,52,36,66,68,56,96,66,108,61,13,
36,66,51,187,96,66,108,150,236,35,66,238,63,97,66,108,154,210,35,66,33,198,97,66,108,142,194,35,66,53,51,98,66,108,142,194,35,66,53,51,98,66,108,142,194,35,66,53,51,98,66,108,92,168,35,66,74,140,99,66,108,114,159,35,66,64,230,100,66,108,213,167,35,66,
57,64,102,66,108,128,193,35,66,89,153,103,66,108,142,194,35,66,217,163,103,66,108,142,194,35,66,217,163,103,66,108,143,194,35,66,217,163,103,66,108,6,30,36,66,46,83,111,66,108,12,23,36,66,160,4,119,66,108,1,0,36,66,226,122,121,66,108,0,0,36,66,225,122,
121,66,108,0,0,36,66,226,122,121,66,108,227,173,32,66,7,174,124,66,108,229,51,29,66,169,181,127,66,108,64,148,25,66,236,71,129,66,108,70,209,21,66,97,157,130,66,108,94,237,17,66,88,218,131,66,108,196,245,16,66,215,35,132,66,108,195,245,16,66,215,35,132,
66,99,109,195,245,120,66,123,148,133,66,108,195,245,120,66,123,148,133,66,108,52,162,120,66,24,248,133,66,108,202,68,120,66,127,89,134,66,108,194,221,119,66,112,184,134,66,108,93,109,119,66,177,20,135,66,108,228,243,118,66,5,110,135,66,108,163,113,118,
66,51,196,135,66,108,246,40,118,66,164,240,135,66,108,246,40,118,66,164,240,135,66,108,246,40,118,66,164,240,135,66,108,172,26,117,66,19,122,136,66,108,252,254,115,66,148,252,136,66,108,155,214,114,66,213,119,137,66,108,70,162,113,66,135,235,137,66,108,
196,98,112,66,95,87,138,66,108,225,24,111,66,24,187,138,66,108,111,197,109,66,116,22,139,66,108,72,105,108,66,54,105,139,66,108,174,71,108,66,164,112,139,66,108,174,71,108,66,164,112,139,66,108,82,184,102,66,236,209,140,66,108,82,184,102,66,236,209,140,
66,108,243,156,97,66,85,18,142,66,108,61,163,92,66,3,115,143,66,108,195,245,89,66,144,66,144,66,108,195,245,89,66,144,66,144,66,108,194,245,89,66,144,66,144,66,108,178,214,86,66,228,87,145,66,108,92,212,83,66,215,128,146,66,108,169,240,80,66,172,188,
147,66,108,61,10,79,66,185,158,148,66,108,62,10,79,66,185,158,148,66,108,246,40,77,66,62,138,149,66,108,246,40,77,66,62,138,149,66,108,102,6,75,66,243,151,150,66,108,142,201,72,66,169,151,151,66,108,222,115,70,66,188,136,152,66,108,174,71,70,66,154,153,
152,66,108,174,71,70,66,154,153,152,66,108,174,71,70,66,154,153,152,66,108,26,68,69,66,68,246,152,66,108,150,55,68,66,83,76,153,66,108,207,34,67,66,144,155,153,66,108,115,6,66,66,202,227,153,66,108,59,227,64,66,210,36,154,66,108,224,185,63,66,125,94,
154,66,108,32,139,62,66,168,144,154,66,108,189,87,61,66,50,187,154,66,108,124,32,60,66,0,222,154,66,108,235,81,59,66,164,240,154,66,108,235,81,59,66,164,240,154,66,108,235,81,59,66,164,240,154,66,108,56,48,58,66,38,2,155,66,108,33,13,57,66,101,12,155,
66,108,133,235,55,66,92,15,155,66,108,133,235,55,66,92,15,155,66,108,41,92,55,66,92,15,155,66,108,41,92,55,66,92,15,155,66,108,33,33,54,66,44,8,155,66,108,54,231,52,66,31,249,154,66,108,102,102,52,66,164,240,154,66,108,102,102,52,66,164,240,154,66,108,
61,10,52,66,164,240,154,66,108,61,10,52,66,164,240,154,66,108,160,162,50,66,224,210,154,66,108,112,62,49,66,41,172,154,66,108,145,222,47,66,152,124,154,66,108,227,131,46,66,76,68,154,66,108,69,47,45,66,103,3,154,66,108,184,30,45,66,0,0,154,66,108,184,
30,45,66,0,0,154,66,108,184,30,45,66,0,0,154,66,108,43,83,44,66,196,214,153,66,108,254,139,43,66,127,168,153,66,108,176,201,42,66,78,117,153,66,108,191,12,42,66,82,61,153,66,108,163,85,41,66,176,0,153,66,108,209,164,40,66,142,191,152,66,108,186,250,39,
66,21,122,152,66,108,204,87,39,66,115,48,152,66,108,110,188,38,66,213,226,151,66,108,3,41,38,66,111,145,151,66,108,235,157,37,66,116,60,151,66,108,184,30,37,66,103,230,150,66,108,184,30,37,66,102,230,150,66,108,184,30,37,66,102,230,150,66,108,10,178,
36,66,161,121,150,66,108,94,80,36,66,72,10,150,66,108,243,249,35,66,161,152,149,66,108,255,174,35,66,246,36,149,66,108,180,111,35,66,144,175,148,66,108,56,60,35,66,187,56,148,66,108,174,20,35,66,195,192,147,66,108,47,249,34,66,244,71,147,66,108,204,233,
34,66,156,206,146,66,108,143,230,34,66,8,85,146,66,108,133,235,34,66,0,0,146,66,108,133,235,34,66,0,0,146,66,98,133,235,34,66,154,25,145,66,133,235,34,66,51,51,144,66,51,51,35,66,205,76,143,66,98,153,153,35,66,21,46,141,66,41,92,36,66,92,15,139,66,184,
30,37,66,225,250,136,66,98,184,30,38,66,51,51,134,66,71,225,38,66,112,189,131,66,164,112,39,66,225,122,129,66,98,1,0,40,66,164,112,126,66,246,40,40,66,174,71,122,66,51,51,40,66,20,174,117,66,98,112,61,40,66,122,20,113,66,51,51,40,66,40,92,108,66,82,184,
39,66,30,133,103,66,108,82,184,39,66,30,133,103,66,108,137,162,39,66,184,82,102,66,108,24,156,39,66,158,31,101,66,108,1,165,39,66,148,236,99,66,108,82,184,39,66,132,235,98,66,108,82,184,39,66,132,235,98,66,108,82,184,39,66,132,235,98,66,108,63,195,39,
66,193,151,98,66,108,88,210,39,66,165,68,98,66,108,148,229,39,66,100,242,97,66,108,230,252,39,66,52,161,97,66,108,64,24,40,66,72,81,97,66,108,143,55,40,66,212,2,97,66,108,192,90,40,66,10,182,96,66,108,188,129,40,66,26,107,96,66,108,107,172,40,66,53,34,
96,66,108,176,218,40,66,137,219,95,66,108,111,12,41,66,68,151,95,66,108,136,65,41,66,146,85,95,66,108,216,121,41,66,155,22,95,66,108,215,163,41,66,132,235,94,66,108,215,163,41,66,132,235,94,66,108,215,163,41,66,132,235,94,66,108,54,233,41,66,246,182,
94,66,108,30,49,42,66,240,133,94,66,108,100,123,42,66,145,88,94,66,108,214,199,42,66,248,46,94,66,108,67,22,43,66,62,9,94,66,108,123,102,43,66,123,231,93,66,108,72,184,43,66,197,201,93,66,108,120,11,44,66,48,176,93,66,108,212,95,44,66,203,154,93,66,108,
39,181,44,66,164,137,93,66,108,58,11,45,66,199,124,93,66,108,214,97,45,66,59,116,93,66,108,215,163,45,66,163,112,93,66,108,215,163,45,66,163,112,93,66,108,41,92,46,66,163,112,93,66,108,41,92,46,66,162,112,93,66,108,174,58,47,66,124,121,93,66,108,123,
24,48,66,113,141,93,66,108,2,245,48,66,118,172,93,66,108,181,207,49,66,118,214,93,66,108,0,0,50,66,70,225,93,66,108,0,0,50,66,71,225,93,66,108,184,30,52,66,51,51,94,66,108,235,81,54,66,31,133,94,66,98,245,40,56,66,205,204,94,66,255,255,57,66,185,30,95,
66,204,204,59,66,92,143,95,66,98,81,184,60,66,205,204,95,66,214,163,61,66,123,20,96,66,204,204,62,66,164,112,96,66,98,194,245,63,66,205,204,96,66,9,215,64,66,123,20,97,66,9,215,65,66,236,81,97,66,108,234,81,66,66,236,81,97,66,108,234,81,66,66,236,81,
97,66,108,117,158,66,66,220,198,97,66,108,191,240,66,66,212,55,98,66,108,149,72,67,66,138,164,98,66,108,189,165,67,66,186,12,99,66,108,253,7,68,66,32,112,99,66,108,21,111,68,66,126,206,99,66,108,195,218,68,66,150,39,100,66,108,195,74,69,66,49,123,100,
66,108,205,190,69,66,23,201,100,66,108,150,54,70,66,24,17,101,66,108,211,177,70,66,5,83,101,66,108,51,48,71,66,180,142,101,66,108,102,177,71,66,0,196,101,66,108,26,53,72,66,197,242,101,66,108,214,163,72,66,123,20,102,66,108,214,163,72,66,123,20,102,66,
108,214,163,72,66,123,20,102,66,108,164,86,73,66,57,67,102,66,108,143,11,74,66,247,104,102,66,108,35,194,74,66,159,133,102,66,108,235,121,75,66,30,153,102,66,108,114,50,76,66,102,163,102,66,108,65,235,76,66,115,164,102,66,108,226,163,77,66,67,156,102,
66,108,224,91,78,66,219,138,102,66,108,196,18,79,66,71,112,102,66,108,26,200,79,66,151,76,102,66,108,109,123,80,66,226,31,102,66,108,214,163,80,66,123,20,102,66,108,214,163,80,66,123,20,102,66,108,214,163,80,66,123,20,102,66,108,81,160,81,66,45,204,101,
66,108,222,152,82,66,87,119,101,66,108,221,140,83,66,48,22,101,66,108,180,123,84,66,247,168,100,66,108,200,100,85,66,240,47,100,66,108,134,71,86,66,106,171,99,66,108,91,35,87,66,186,27,99,66,108,188,247,87,66,58,129,98,66,108,0,0,88,66,225,122,98,66,
108,0,0,88,66,225,122,98,66,108,0,0,88,66,225,122,98,66,108,82,219,88,66,241,171,97,66,108,7,172,89,66,78,210,96,66,108,205,204,89,66,20,174,96,66,108,205,204,89,66,20,174,96,66,108,195,245,90,66,133,235,96,66,108,185,30,92,66,113,61,97,66,108,185,30,
92,66,113,61,97,66,108,184,156,92,66,21,101,97,66,108,146,24,93,66,248,146,97,66,108,250,145,93,66,254,198,97,66,108,162,8,94,66,4,1,98,66,108,61,124,94,66,230,64,98,66,108,130,236,94,66,122,134,98,66,108,41,89,95,66,149,209,98,66,108,236,193,95,66,5,
34,99,66,108,185,30,96,66,164,112,99,66,108,185,30,96,66,164,112,99,66,108,185,30,96,66,164,112,99,66,108,95,120,96,66,134,218,99,66,108,157,204,96,66,194,72,100,66,108,62,27,97,66,16,187,100,66,108,15,100,97,66,39,49,101,66,108,226,166,97,66,188,170,
101,66,108,140,227,97,66,130,39,102,66,108,124,20,98,66,154,153,102,66,108,124,20,98,66,154,153,102,66,108,124,20,98,66,154,153,102,66,108,122,104,98,66,16,135,103,66,108,126,176,98,66,109,120,104,66,108,92,236,98,66,22,109,105,66,108,236,27,99,66,110,
100,106,66,108,17,63,99,66,216,93,107,66,108,174,71,99,66,21,174,107,66,108,175,71,99,66,21,174,107,66,108,175,71,99,66,185,30,109,66,108,174,71,99,66,185,30,109,66,108,178,86,99,66,218,94,110,66,108,176,117,99,66,212,157,111,66,108,155,153,99,66,155,
153,112,66,108,155,153,99,66,154,153,112,66,108,155,153,99,66,154,153,112,66,108,129,198,99,66,80,85,113,66,108,187,252,99,66,139,14,114,66,108,37,60,100,66,213,196,114,66,108,151,132,100,66,185,119,115,66,108,226,213,100,66,198,38,116,66,108,212,47,
101,66,138,209,116,66,108,49,146,101,66,152,119,117,66,108,188,252,101,66,136,24,118,66,108,48,111,102,66,240,179,118,66,108,67,233,102,66,110,73,119,66,108,124,20,103,66,226,122,119,66,108,124,20,103,66,226,122,119,66,108,125,20,103,66,226,122,119,66,
108,158,190,104,66,123,60,121,66,108,176,126,106,66,56,232,122,66,108,147,83,108,66,7,125,124,66,108,145,194,108,66,11,215,124,66,108,144,194,108,66,11,215,124,66,108,145,194,108,66,11,215,124,66,108,157,241,110,66,234,174,126,66,108,140,55,113,66,33,
53,128,66,108,135,235,114,66,205,204,128,66,108,134,235,114,66,205,204,128,66,108,1,0,116,66,246,40,129,66,108,1,0,116,66,246,40,129,66,108,64,175,116,66,201,97,129,66,108,153,88,117,66,236,158,129,66,108,159,251,117,66,54,224,129,66,108,62,10,118,66,
103,230,129,66,108,62,10,118,66,103,230,129,66,108,62,10,118,66,103,230,129,66,108,72,95,118,66,74,7,130,66,108,238,176,118,66,66,42,130,66,108,252,254,118,66,58,79,130,66,108,62,73,119,66,25,118,130,66,108,133,143,119,66,198,158,130,66,108,166,209,119,
66,40,201,130,66,108,116,15,120,66,36,245,130,66,108,202,72,120,66,157,34,131,66,108,42,92,120,66,52,51,131,66,108,42,92,120,66,52,51,131,66,108,42,92,120,66,52,51,131,66,108,44,133,120,66,116,90,131,66,108,52,170,120,66,174,130,131,66,108,42,203,120,
66,201,171,131,66,108,251,231,120,66,168,213,131,66,108,146,0,121,66,51,0,132,66,108,225,20,121,66,78,43,132,66,108,219,36,121,66,220,86,132,66,108,117,48,121,66,195,130,132,66,108,168,55,121,66,230,174,132,66,108,111,58,121,66,41,219,132,66,108,201,
56,121,66,112,7,133,66,108,182,50,121,66,157,51,133,66,108,58,40,121,66,150,95,133,66,108,93,25,121,66,62,139,133,66,108,61,10,121,66,20,174,133,66,108,61,10,121,66,20,174,133,66,99,101,0,0 };
const uint8 xcode[] = { 110,109,72,225,2,66,41,92,31,64,108,72,225,2,66,40,92,31,64,108,137,147,2,66,16,119,29,64,108,95,68,2,66,188,208,27,64,108,253,243,1,66,63,106,26,64,108,150,162,1,66,123,68,25,64,108,94,80,1,66,46,96,24,64,108,138,253,0,66,233,189,23,64,108,79,170,0,
66,20,94,23,64,108,225,86,0,66,236,64,23,64,108,119,3,0,66,134,102,23,64,108,140,96,255,65,198,206,23,64,108,6,187,254,65,108,121,24,64,108,197,22,254,65,11,102,25,64,108,51,116,253,65,10,148,26,64,108,185,211,252,65,170,2,28,64,108,187,53,252,65,253,
176,29,64,108,20,174,251,65,40,92,31,64,108,21,174,251,65,41,92,31,64,108,21,174,251,65,41,92,31,64,108,73,51,251,65,222,11,33,64,108,242,181,250,65,240,137,34,64,108,96,54,250,65,106,213,35,64,108,229,180,249,65,120,237,36,64,108,212,49,249,65,104,209,
37,64,108,127,173,248,65,166,128,38,64,108,61,40,248,65,196,250,38,64,108,98,162,247,65,115,63,39,64,108,69,28,247,65,134,78,39,64,108,57,150,246,65,246,39,39,64,108,151,16,246,65,217,203,38,64,108,179,139,245,65,107,58,38,64,108,225,7,245,65,10,116,
37,64,108,119,133,244,65,50,121,36,64,108,200,4,244,65,136,74,35,64,108,39,134,243,65,201,232,33,64,108,227,9,243,65,218,84,32,64,108,77,144,242,65,190,143,30,64,108,179,25,242,65,149,154,28,64,108,97,166,241,65,160,118,26,64,108,159,54,241,65,64,37,
24,64,108,183,202,240,65,237,167,21,64,108,236,98,240,65,66,0,19,64,108,129,255,239,65,240,47,16,64,108,182,160,239,65,196,56,13,64,108,42,92,239,65,72,225,10,64,108,42,92,239,65,72,225,10,64,108,42,92,239,65,73,225,10,64,108,94,226,237,65,2,150,254,
63,108,129,86,236,65,252,158,232,63,108,147,185,234,65,140,235,211,63,108,156,12,233,65,236,136,192,63,108,173,80,231,65,140,131,174,63,108,227,134,229,65,236,230,157,63,108,98,176,227,65,180,189,142,63,108,89,206,225,65,148,17,129,63,108,251,225,223,
65,144,214,105,63,108,42,92,223,65,8,215,99,63,108,42,92,223,65,12,215,99,63,108,42,92,223,65,16,215,99,63,108,107,36,218,65,176,63,42,63,108,80,215,212,65,0,38,242,62,108,62,120,207,65,32,225,160,62,108,165,10,202,65,64,201,65,62,108,254,145,196,65,
128,101,201,61,108,201,17,191,65,0,234,42,61,108,138,141,185,65,0,46,160,60,108,203,8,180,65,0,139,2,61,108,18,135,174,65,128,19,161,61,108,154,153,169,65,128,153,25,62,108,154,153,169,65,154,153,25,62,108,154,153,169,65,160,153,25,62,108,162,198,166,
65,224,114,72,62,108,65,249,163,65,16,167,132,62,108,66,51,161,65,0,1,174,62,108,105,118,158,65,192,44,224,62,108,120,196,155,65,32,133,13,63,108,41,31,153,65,224,57,47,63,108,44,136,150,65,24,31,85,63,108,43,1,148,65,136,28,127,63,108,195,139,145,65,
168,139,150,63,108,0,0,144,65,104,102,166,63,108,0,0,144,65,102,102,166,63,108,0,0,144,65,102,102,166,63,108,45,87,143,65,231,184,174,63,108,56,181,142,65,191,143,183,63,108,135,26,142,65,72,229,192,63,108,123,20,142,65,174,71,193,63,108,123,20,142,65,
174,71,193,63,108,62,10,141,65,215,163,208,63,108,52,51,137,65,133,235,1,64,108,225,122,142,65,0,0,0,64,108,224,122,142,65,0,0,0,64,108,24,10,149,65,192,9,247,63,108,97,158,155,65,32,85,243,63,108,134,51,162,65,144,228,244,63,108,80,197,168,65,16,183,
251,63,108,164,112,171,65,0,0,0,64,108,164,112,171,65,0,0,0,64,108,164,112,171,65,0,0,0,64,108,134,137,172,65,121,157,0,64,108,18,161,173,65,13,171,1,64,108,150,182,174,65,17,40,3,64,108,95,201,175,65,144,19,5,64,108,190,216,176,65,81,108,7,64,108,6,
228,177,65,211,48,10,64,108,139,234,178,65,79,95,13,64,108,165,235,179,65,191,245,16,64,108,177,230,180,65,212,241,20,64,108,12,219,181,65,4,81,25,64,108,28,200,182,65,129,16,30,64,108,71,173,183,65,66,45,35,64,108,252,137,184,65,2,164,40,64,108,174,
93,185,65,65,113,46,64,108,212,39,186,65,73,145,52,64,108,238,231,186,65,48,0,59,64,108,164,112,187,65,0,0,64,64,108,164,112,187,65,0,0,64,64,98,31,133,191,65,154,153,105,64,154,153,189,65,0,0,144,64,123,20,190,65,194,245,168,64,108,0,0,0,0,61,10,15,
65,108,61,10,71,64,92,143,252,65,108,72,225,128,65,92,143,236,65,108,72,225,128,65,92,143,236,65,108,67,216,128,65,164,79,237,65,108,222,216,128,65,33,16,238,65,108,72,225,128,65,82,184,238,65,108,72,225,128,65,82,184,238,65,108,72,225,128,65,81,184,
238,65,108,41,216,128,65,131,158,239,65,108,142,218,128,65,224,132,240,65,108,118,232,128,65,213,106,241,65,108,216,1,129,65,206,79,242,65,108,163,38,129,65,57,51,243,65,108,192,86,129,65,133,20,244,65,108,17,146,129,65,33,243,244,65,108,111,216,129,
65,127,206,245,65,108,172,41,130,65,18,166,246,65,108,151,133,130,65,81,121,247,65,108,242,235,130,65,180,71,248,65,108,126,92,131,65,184,16,249,65,108,241,214,131,65,219,211,249,65,108,254,90,132,65,162,144,250,65,108,80,232,132,65,146,70,251,65,108,
140,126,133,65,56,245,251,65,108,20,174,133,65,245,40,252,65,108,21,174,133,65,246,40,252,65,108,21,174,133,65,246,40,252,65,108,192,107,134,65,228,215,252,65,108,237,49,135,65,31,125,253,65,108,28,0,136,65,62,24,254,65,108,202,213,136,65,222,168,254,
65,108,110,178,137,65,161,46,255,65,108,123,149,138,65,50,169,255,65,108,96,126,139,65,33,12,0,66,108,135,108,140,65,198,61,0,66,108,88,95,141,65,104,105,0,66,108,56,86,142,65,234,142,0,66,108,137,80,143,65,52,174,0,66,108,171,77,144,65,52,199,0,66,108,
251,76,145,65,216,217,0,66,108,214,77,146,65,20,230,0,66,108,153,79,147,65,226,235,0,66,108,113,61,148,65,133,235,0,66,108,113,61,148,65,133,235,0,66,108,41,92,149,65,133,235,0,66,108,41,92,149,65,133,235,0,66,108,248,181,150,65,185,228,0,66,108,171,
14,152,65,75,213,0,66,108,100,101,153,65,69,189,0,66,108,73,185,154,65,181,156,0,66,108,128,9,156,65,178,115,0,66,108,50,85,157,65,86,66,0,66,108,138,155,158,65,190,8,0,66,108,185,219,159,65,36,142,255,65,108,240,20,161,65,245,250,254,65,108,105,70,162,
65,77,88,254,65,108,94,111,163,65,150,166,253,65,108,19,143,164,65,63,230,252,65,108,206,164,165,65,197,23,252,65,108,223,175,166,65,171,59,251,65,108,31,133,167,65,225,122,250,65,108,31,133,167,65,225,122,250,65,108,31,133,167,65,225,122,250,65,108,
198,77,168,65,122,12,249,65,108,222,3,169,65,129,148,247,65,108,240,166,169,65,230,19,246,65,108,150,54,170,65,160,139,244,65,108,114,178,170,65,169,252,242,65,108,195,245,170,65,0,0,242,65,108,195,245,170,65,0,0,242,65,108,0,0,174,65,154,153,229,65,
108,0,0,174,65,154,153,229,65,108,174,71,247,65,236,81,218,65,108,0,0,224,65,215,163,200,64,98,133,235,225,65,246,40,196,64,20,174,227,65,31,133,179,64,113,61,230,65,92,143,178,64,98,41,92,235,65,235,81,176,64,31,133,239,65,0,0,176,64,113,61,242,65,82,
184,190,64,108,113,61,242,65,81,184,190,64,108,167,157,242,65,199,232,192,64,108,191,4,243,65,77,5,195,64,108,119,114,243,65,138,12,197,64,108,136,230,243,65,49,253,198,64,108,170,96,244,65,5,214,200,64,108,140,224,244,65,216,149,202,64,108,222,101,245,
65,138,59,204,64,108,74,240,245,65,14,198,205,64,108,120,127,246,65,104,52,207,64,108,12,19,247,65,172,133,208,64,108,167,170,247,65,4,185,209,64,108,233,69,248,65,171,205,210,64,108,111,228,248,65,239,194,211,64,108,210,133,249,65,52,152,212,64,108,
171,41,250,65,241,76,213,64,108,146,207,250,65,179,224,213,64,108,29,119,251,65,26,83,214,64,108,154,153,251,65,102,102,214,64,108,154,153,251,65,102,102,214,64,108,154,153,251,65,101,102,214,64,108,75,161,252,65,236,19,215,64,108,125,166,253,65,242,
245,215,64,108,136,168,254,65,231,11,217,64,108,199,166,255,65,26,85,218,64,108,185,30,0,66,50,51,219,64,108,185,30,0,66,51,51,219,64,108,184,30,0,66,51,51,219,64,108,205,56,0,66,29,136,219,64,108,97,83,0,66,126,210,219,64,108,99,110,0,66,39,18,220,64,
108,195,137,0,66,239,70,220,64,108,110,165,0,66,180,112,220,64,108,83,193,0,66,92,143,220,64,108,96,221,0,66,211,162,220,64,108,132,249,0,66,12,171,220,64,108,171,21,1,66,3,168,220,64,108,197,49,1,66,184,153,220,64,108,191,77,1,66,54,128,220,64,108,135,
105,1,66,141,91,220,64,108,11,133,1,66,211,43,220,64,108,59,160,1,66,40,241,219,64,108,4,187,1,66,178,171,219,64,108,85,213,1,66,156,91,219,64,108,71,225,1,66,51,51,219,64,108,72,225,1,66,51,51,219,64,108,72,225,1,66,51,51,219,64,108,35,251,1,66,24,167,
218,64,108,22,20,2,66,211,16,218,64,108,17,44,2,66,197,112,217,64,108,3,67,2,66,84,199,216,64,108,224,88,2,66,236,20,216,64,108,152,109,2,66,255,89,215,64,108,30,129,2,66,5,151,214,64,108,103,147,2,66,124,204,213,64,108,101,164,2,66,227,250,212,64,108,
16,180,2,66,194,34,212,64,108,91,194,2,66,163,68,211,64,108,62,207,2,66,20,97,210,64,108,178,218,2,66,166,120,209,64,108,174,228,2,66,239,139,208,64,108,44,237,2,66,134,155,207,64,108,39,244,2,66,4,168,206,64,108,195,245,2,66,102,102,206,64,108,195,245,
2,66,102,102,206,64,98,134,235,3,66,10,215,179,64,72,225,4,66,153,153,153,64,72,225,5,66,122,20,126,64,98,184,30,7,66,0,0,64,64,133,235,6,66,143,194,53,64,72,225,2,66,41,92,31,64,99,109,0,0,64,65,133,235,157,65,108,215,163,60,65,133,235,157,65,108,72,
225,38,65,31,133,185,65,108,72,225,38,65,31,133,185,65,108,1,178,38,65,28,205,185,65,108,150,123,38,65,211,19,186,65,108,44,62,38,65,23,89,186,65,108,232,249,37,65,188,156,186,65,108,248,174,37,65,151,222,186,65,108,138,93,37,65,125,30,187,65,108,211,
5,37,65,70,92,187,65,108,11,168,36,65,202,151,187,65,108,110,68,36,65,227,208,187,65,108,60,219,35,65,108,7,188,65,108,184,108,35,65,67,59,188,65,108,41,249,34,65,71,108,188,65,108,217,128,34,65,87,154,188,65,108,103,102,34,65,216,163,188,65,108,103,
102,34,65,215,163,188,65,108,1,0,36,65,184,30,189,65,108,155,153,33,65,215,163,190,65,108,247,40,8,65,215,163,206,65,108,82,184,230,64,0,0,220,65,108,72,225,226,64,0,0,220,65,108,72,225,226,64,0,0,220,65,108,85,204,225,64,122,237,219,65,108,110,187,224,
64,132,215,219,65,108,67,175,223,64,44,190,219,65,108,126,168,222,64,131,161,219,65,108,144,194,221,64,31,133,219,65,108,144,194,221,64,31,133,219,65,108,134,235,217,64,62,10,219,65,108,134,235,217,64,52,51,217,65,98,32,133,219,64,206,204,212,65,165,
112,221,64,103,102,208,65,42,92,223,64,1,0,204,65,108,93,143,226,64,196,245,196,65,98,226,122,228,64,196,245,192,65,124,20,230,64,196,245,188,65,21,174,231,64,196,245,184,65,108,21,174,231,64,196,245,184,65,108,88,169,231,64,131,191,184,65,108,117,175,
231,64,68,137,184,65,108,105,192,231,64,42,83,184,65,108,40,220,231,64,88,29,184,65,108,160,2,232,64,240,231,183,65,108,186,51,232,64,19,179,183,65,108,85,111,232,64,229,126,183,65,108,76,181,232,64,134,75,183,65,108,113,5,233,64,24,25,183,65,108,146,
95,233,64,186,231,182,65,108,116,195,233,64,140,183,182,65,108,217,48,234,64,172,136,182,65,108,121,167,234,64,58,91,182,65,108,9,39,235,64,82,47,182,65,108,55,175,235,64,16,5,182,65,108,173,63,236,64,143,220,181,65,108,13,216,236,64,233,181,181,65,108,
247,119,237,64,55,145,181,65,108,123,20,238,64,165,112,181,65,108,123,20,238,64,165,112,181,65,108,123,20,238,64,165,112,181,65,108,123,20,238,64,165,112,181,65,108,123,20,238,64,165,112,181,65,108,45,199,237,64,89,66,181,65,108,57,131,237,64,36,19,181,
65,108,202,72,237,64,37,227,180,65,108,7,24,237,64,122,178,180,65,108,14,241,236,64,66,129,180,65,108,248,211,236,64,158,79,180,65,108,217,192,236,64,173,29,180,65,108,187,183,236,64,142,235,179,65,108,165,184,236,64,99,185,179,65,108,151,195,236,64,
74,135,179,65,108,137,216,236,64,101,85,179,65,108,110,247,236,64,210,35,179,65,108,50,32,237,64,178,242,178,65,108,188,82,237,64,36,194,178,65,108,234,142,237,64,71,146,178,65,108,150,212,237,64,59,99,178,65,108,123,20,238,64,115,61,178,65,108,123,20,
238,64,114,61,178,65,108,154,153,5,65,134,235,159,65,108,154,153,5,65,134,235,159,65,108,17,95,5,65,76,48,160,65,108,186,29,5,65,134,115,160,65,108,192,213,4,65,9,181,160,65,108,80,135,4,65,170,244,160,65,108,158,50,4,65,65,50,161,65,108,222,215,3,65,
166,109,161,65,108,76,119,3,65,180,166,161,65,108,36,17,3,65,69,221,161,65,108,169,165,2,65,56,17,162,65,108,31,53,2,65,107,66,162,65,108,206,191,1,65,190,112,162,65,108,1,70,1,65,19,156,162,65,108,6,200,0,65,80,196,162,65,108,46,70,0,65,89,233,162,65,
108,151,129,255,64,25,11,163,65,108,104,112,254,64,120,41,163,65,108,127,89,253,64,99,68,163,65,108,141,61,252,64,202,91,163,65,108,72,29,251,64,157,111,163,65,108,105,249,249,64,208,127,163,65,108,170,210,248,64,88,140,163,65,108,200,169,247,64,45,149,
163,65,108,84,184,246,64,154,153,163,65,108,83,184,246,64,154,153,163,65,98,73,225,218,64,103,102,164,65,93,143,194,64,174,71,165,65,32,133,171,64,246,40,166,65,108,20,174,167,64,246,40,166,65,108,20,174,167,64,246,40,166,65,108,175,237,166,64,123,42,
166,65,108,57,45,166,64,152,41,166,65,108,47,109,165,64,78,38,166,65,108,10,174,164,64,159,32,166,65,108,69,240,163,64,142,24,166,65,108,90,52,163,64,33,14,166,65,108,192,122,162,64,94,1,166,65,108,239,195,161,64,77,242,165,65,108,91,16,161,64,249,224,
165,65,108,120,96,160,64,107,205,165,65,108,182,180,159,64,178,183,165,65,108,131,13,159,64,217,159,165,65,108,73,107,158,64,242,133,165,65,108,102,102,158,64,31,133,165,65,108,102,102,158,64,31,133,165,65,108,102,102,158,64,31,133,165,65,108,235,187,
157,64,65,93,165,65,108,159,25,157,64,77,51,165,65,108,234,127,156,64,96,7,165,65,108,46,239,155,64,150,217,164,65,108,200,103,155,64,11,170,164,65,108,14,234,154,64,222,120,164,65,108,82,118,154,64,46,70,164,65,108,220,12,154,64,29,18,164,65,108,241,
173,153,64,203,220,163,65,108,205,89,153,64,91,166,163,65,108,166,16,153,64,238,110,163,65,108,171,210,152,64,170,54,163,65,108,3,160,152,64,177,253,162,65,108,208,120,152,64,41,196,162,65,108,42,93,152,64,53,138,162,65,108,236,81,152,64,103,102,162,
65,108,235,81,152,64,103,102,162,65,98,81,184,150,64,226,122,158,65,245,40,148,64,103,102,154,65,153,153,145,64,93,143,150,65,108,123,20,142,64,0,0,144,65,108,113,61,170,64,72,225,142,65,108,52,51,19,65,11,215,137,65,108,236,81,24,65,165,112,137,65,108,
123,20,22,65,196,245,140,65,108,174,71,49,65,44,92,87,65,108,174,71,49,65,44,92,87,65,108,71,107,49,65,253,249,86,65,108,189,147,49,65,182,153,86,65,108,246,192,49,65,146,59,86,65,108,214,242,49,65,208,223,85,65,108,59,41,50,65,168,134,85,65,108,3,100,
50,65,86,48,85,65,108,10,163,50,65,15,221,84,65,108,37,230,50,65,9,141,84,65,108,43,45,51,65,119,64,84,65,108,238,119,51,65,139,247,83,65,108,62,198,51,65,114,178,83,65,108,233,23,52,65,90,113,83,65,108,187,108,52,65,107,52,83,65,108,125,196,52,65,205,
251,82,65,108,248,30,53,65,164,199,82,65,108,240,123,53,65,17,152,82,65,108,44,219,53,65,51,109,82,65,108,133,235,53,65,105,102,82,65,108,133,235,53,65,105,102,82,65,108,133,235,53,65,105,102,82,65,108,133,235,53,65,105,102,82,65,108,247,194,53,65,243,
3,82,65,108,97,159,53,65,150,159,81,65,108,220,128,53,65,146,57,81,65,108,121,103,53,65,39,210,80,65,108,73,83,53,65,153,105,80,65,108,90,68,53,65,43,0,80,65,108,180,58,53,65,30,150,79,65,108,95,54,53,65,185,43,79,65,108,92,55,53,65,62,193,78,65,108,
171,61,53,65,241,86,78,65,108,72,73,53,65,24,237,77,65,108,44,90,53,65,245,131,77,65,108,76,112,53,65,203,27,77,65,108,153,139,53,65,222,180,76,65,108,2,172,53,65,111,79,76,65,108,115,209,53,65,192,235,75,65,108,133,235,53,65,23,174,75,65,108,133,235,
53,65,23,174,75,65,98,10,215,55,65,33,133,71,65,153,153,57,65,54,51,67,65,41,92,59,65,64,10,63,65,108,195,245,60,65,54,51,59,65,108,195,245,60,65,54,51,59,65,108,231,104,61,65,49,40,58,65,108,63,233,61,65,67,35,57,65,108,120,118,62,65,19,37,56,65,108,
57,16,63,65,66,46,55,65,108,30,182,63,65,112,63,54,65,108,189,103,64,65,53,89,53,65,108,166,36,65,65,36,124,52,65,108,94,236,65,65,203,168,51,65,108,103,190,66,65,177,223,50,65,108,58,154,67,65,87,33,50,65,108,73,127,68,65,54,110,49,65,108,4,109,69,65,
193,198,48,65,108,209,98,70,65,99,43,48,65,108,19,96,71,65,128,156,47,65,108,40,100,72,65,115,26,47,65,108,106,110,73,65,144,165,46,65,108,46,126,74,65,32,62,46,65,108,199,146,75,65,102,228,45,65,108,131,171,76,65,157,152,45,65,108,176,199,77,65,243,
90,45,65,108,150,230,78,65,146,43,45,65,108,127,7,80,65,150,10,45,65,108,177,41,81,65,21,248,44,65,108,164,112,81,65,197,245,44,65,108,164,112,81,65,197,245,44,65,108,113,61,82,65,197,245,44,65,108,113,61,82,65,197,245,44,65,108,41,92,87,65,64,10,47,
65,108,41,92,87,65,64,10,47,65,108,39,152,90,65,130,71,48,65,108,65,195,93,65,192,173,49,65,108,111,219,96,65,22,60,51,65,108,41,92,99,65,218,163,52,65,108,41,92,99,65,218,163,52,65,108,41,92,99,65,218,163,52,65,108,9,21,100,65,154,21,53,65,108,254,199,
100,65,115,144,53,65,108,150,116,101,65,22,20,54,65,108,99,26,102,65,48,160,54,65,108,250,184,102,65,102,52,55,65,108,247,79,103,65,89,208,55,65,108,247,222,103,65,167,115,56,65,108,160,101,104,65,230,29,57,65,108,156,227,104,65,169,206,57,65,108,154,
88,105,65,128,133,58,65,108,80,196,105,65,245,65,59,65,108,119,38,106,65,144,3,60,65,108,210,126,106,65,213,201,60,65,108,40,205,106,65,69,148,61,65,108,71,17,107,65,94,98,62,65,108,3,75,107,65,157,51,63,65,108,55,122,107,65,124,7,64,65,108,198,158,107,
65,115,221,64,65,108,151,184,107,65,249,180,65,65,108,154,199,107,65,133,141,66,65,108,198,203,107,65,140,102,67,65,108,24,197,107,65,130,63,68,65,108,148,179,107,65,221,23,69,65,108,69,151,107,65,20,239,69,65,108,62,112,107,65,155,196,70,65,108,151,
62,107,65,234,151,71,65,108,113,2,107,65,123,104,72,65,108,241,187,106,65,199,53,73,65,108,69,107,106,65,75,255,73,65,108,160,16,106,65,135,196,74,65,108,143,194,105,65,44,92,75,65,108,143,194,105,65,44,92,75,65,108,51,51,103,65,167,112,81,65,98,153,
153,101,65,187,30,85,65,0,0,100,65,208,204,88,65,92,143,98,65,218,163,92,65,108,92,143,98,65,218,163,92,65,108,194,90,98,65,159,16,93,65,108,202,32,98,65,160,122,93,65,108,152,225,97,65,153,225,93,65,108,84,157,97,65,73,69,94,65,108,43,84,97,65,111,165,
94,65,108,75,6,97,65,207,1,95,65,108,230,179,96,65,44,90,95,65,108,49,93,96,65,80,174,95,65,108,99,2,96,65,2,254,95,65,108,0,0,96,65,0,0,96,65,108,0,0,96,65,0,0,96,65,108,164,112,97,65,195,245,96,65,108,225,122,96,65,41,92,99,65,108,41,92,95,65,113,61,
102,65,108,41,92,95,65,246,40,104,65,108,143,194,81,65,184,30,133,65,108,215,163,84,65,184,30,133,65,108,41,92,137,65,0,0,128,65,108,41,92,137,65,0,0,128,65,108,223,193,137,65,204,11,128,65,108,10,40,138,65,126,18,128,65,108,107,142,138,65,20,20,128,
65,108,191,244,138,65,139,16,128,65,108,197,90,139,65,229,7,128,65,108,155,153,139,65,0,0,128,65,108,154,153,139,65,0,0,128,65,108,154,153,139,65,0,0,128,65,108,0,5,140,65,146,154,127,65,108,205,114,140,65,1,64,127,65,108,186,226,140,65,134,240,126,65,
108,128,84,141,65,86,172,126,65,108,213,199,141,65,154,115,126,65,108,113,60,142,65,120,70,126,65,108,8,178,142,65,12,37,126,65,108,79,40,143,65,107,15,126,65,108,251,158,143,65,165,5,126,65,108,192,21,144,65,190,7,126,65,108,81,140,144,65,182,21,126,
65,108,98,2,145,65,131,47,126,65,108,169,119,145,65,22,85,126,65,108,218,235,145,65,85,134,126,65,108,171,94,146,65,34,195,126,65,108,210,207,146,65,85,11,127,65,108,6,63,147,65,193,94,127,65,108,2,172,147,65,48,189,127,65,108,127,22,148,65,51,19,128,
65,108,56,126,148,65,15,77,128,65,108,236,226,148,65,8,140,128,65,108,90,68,149,65,245,207,128,65,108,68,162,149,65,171,24,129,65,108,110,252,149,65,252,101,129,65,108,157,82,150,65,181,183,129,65,108,155,164,150,65,163,13,130,65,108,52,242,150,65,143,
103,130,65,108,53,59,151,65,62,197,130,65,108,112,127,151,65,118,38,131,65,108,186,190,151,65,247,138,131,65,108,233,248,151,65,130,242,131,65,108,0,0,152,65,0,0,132,65,108,0,0,152,65,0,0,132,65,98,133,235,153,65,205,204,134,65,113,61,156,65,154,153,
137,65,215,163,158,65,92,143,140,65,108,123,20,162,65,205,204,144,65,108,143,194,163,65,195,245,146,65,108,61,10,161,65,164,112,147,65,99,109,174,71,209,65,246,40,186,65,108,174,71,209,65,246,40,186,65,108,217,203,204,65,48,238,183,65,108,249,109,200,
65,196,122,181,65,108,220,48,196,65,64,208,178,65,108,53,23,192,65,92,240,175,65,108,247,40,188,65,72,225,172,65,108,246,40,188,65,72,225,172,65,98,51,51,185,65,82,184,168,65,164,112,189,65,103,102,156,65,10,215,189,65,195,245,158,65,108,10,215,189,65,
195,245,158,65,108,170,153,190,65,102,134,158,65,108,122,86,191,65,114,13,158,65,108,2,13,192,65,53,139,157,65,108,206,188,192,65,2,0,157,65,108,71,225,192,65,72,225,156,65,108,71,225,192,65,72,225,156,65,98,204,204,194,65,195,245,154,65,225,122,196,
65,41,92,155,65,214,163,198,65,72,225,156,65,108,214,163,198,65,72,225,156,65,108,92,203,199,65,106,214,157,65,108,68,230,200,65,3,218,158,65,108,215,243,201,65,109,235,159,65,108,105,243,202,65,249,9,161,65,108,88,228,203,65,238,52,162,65,108,8,198,
204,65,143,107,163,65,108,234,151,205,65,20,173,164,65,108,119,89,206,65,175,248,165,65,108,51,10,207,65,141,77,167,65,108,174,169,207,65,211,170,168,65,108,128,55,208,65,162,15,170,65,108,80,179,208,65,21,123,171,65,108,206,28,209,65,68,236,172,65,108,
183,115,209,65,66,98,174,65,108,211,183,209,65,33,220,175,65,108,246,232,209,65,238,88,177,65,108,2,7,210,65,183,215,178,65,108,226,17,210,65,133,87,180,65,108,144,9,210,65,100,215,181,65,108,18,238,209,65,93,86,183,65,108,120,191,209,65,124,211,184,
65,108,31,133,209,65,246,40,186,65,108,31,133,209,65,246,40,186,65,99,109,102,102,4,66,61,10,119,64,98,102,102,3,66,143,194,149,64,163,112,2,66,0,0,176,64,225,122,1,66,92,143,202,64,98,225,122,1,66,61,10,207,64,51,51,1,66,41,92,207,64,51,51,1,66,41,92,
207,64,98,51,51,1,66,41,92,207,64,51,51,1,66,41,92,207,64,82,184,0,66,41,92,207,64,108,82,184,0,66,42,92,207,64,108,148,39,0,66,86,193,205,64,108,229,40,255,65,230,96,204,64,108,153,254,253,65,186,59,203,64,108,3,209,252,65,142,82,202,64,108,246,40,252,
65,134,235,201,64,108,246,40,252,65,133,235,201,64,108,246,40,252,65,133,235,201,64,108,163,168,251,65,118,151,201,64,108,134,41,251,65,218,41,201,64,108,240,171,250,65,248,162,200,64,108,49,48,250,65,38,3,200,64,108,154,182,249,65,202,74,199,64,108,
119,63,249,65,89,122,198,64,108,20,203,248,65,90,146,197,64,108,190,89,248,65,98,147,196,64,108,187,235,247,65,18,126,195,64,108,82,129,247,65,28,83,194,64,108,200,26,247,65,65,19,193,64,108,93,184,246,65,75,191,191,64,108,81,90,246,65,22,88,190,64,108,
225,0,246,65,135,222,188,64,108,69,172,245,65,142,83,187,64,108,179,92,245,65,42,184,185,64,108,94,18,245,65,97,13,184,64,108,195,245,244,65,42,92,183,64,108,195,245,244,65,41,92,183,64,108,195,245,244,65,41,92,183,64,108,43,115,244,65,87,55,181,64,108,
225,233,243,65,80,45,179,64,108,62,90,243,65,99,63,177,64,108,156,196,242,65,203,110,175,64,108,92,41,242,65,177,188,173,64,108,225,136,241,65,44,42,172,64,108,146,227,240,65,60,184,170,64,108,217,57,240,65,208,103,169,64,108,34,140,239,65,189,57,168,
64,108,220,218,238,65,197,46,167,64,108,121,38,238,65,148,71,166,64,108,108,111,237,65,188,132,165,64,108,43,182,236,65,187,230,164,64,108,43,251,235,65,245,109,164,64,108,229,62,235,65,185,26,164,64,108,209,129,234,65,58,237,163,64,108,104,196,233,65,
152,229,163,64,108,35,7,233,65,213,3,164,64,108,123,74,232,65,223,71,164,64,108,234,142,231,65,139,177,164,64,108,230,212,230,65,148,64,165,64,108,231,28,230,65,160,244,165,64,108,0,0,230,65,123,20,166,64,108,0,0,230,65,123,20,166,64,98,164,112,227,65,
123,20,166,64,123,20,226,65,123,20,182,64,123,20,224,65,113,61,186,64,108,21,174,223,65,113,61,186,64,108,21,174,223,65,113,61,186,64,108,191,249,222,65,78,25,188,64,108,148,75,222,65,159,24,190,64,108,5,164,221,65,30,58,192,64,108,125,3,221,65,111,124,
194,64,108,97,106,220,65,30,222,196,64,108,21,217,219,65,166,93,199,64,108,245,79,219,65,110,249,201,64,108,89,207,218,65,202,175,204,64,108,147,87,218,65,254,126,207,64,108,240,232,217,65,61,101,210,64,108,182,131,217,65,173,96,213,64,108,39,40,217,
65,102,111,216,64,108,125,214,216,65,113,143,219,64,108,216,163,216,65,144,194,221,64,108,216,163,216,65,144,194,221,64,108,216,163,216,65,140,194,221,64,108,162,174,208,65,46,8,28,65,108,210,220,201,65,72,236,73,65,108,50,51,201,65,76,225,78,65,108,
52,51,201,65,72,225,78,65,98,83,184,200,65,144,194,81,65,113,61,200,65,226,122,84,65,144,194,199,65,11,215,87,65,108,164,112,197,65,134,235,105,65,108,92,143,196,65,1,0,112,65,98,10,215,197,65,124,20,106,65,61,10,217,65,62,10,99,65,92,143,220,65,1,0,
100,65,98,102,102,222,65,1,0,100,65,205,204,222,65,83,184,102,65,72,225,222,65,11,215,103,65,98,31,133,223,65,93,143,114,65,52,51,225,65,134,235,131,65,52,51,225,65,236,81,132,65,108,52,51,225,65,144,194,133,65,108,144,194,223,65,144,194,133,65,98,246,
40,206,65,246,40,138,65,226,122,198,65,124,20,140,65,62,10,195,65,216,163,140,65,108,102,102,194,65,216,163,140,65,108,102,102,194,65,216,163,140,65,98,92,143,192,65,216,163,140,65,225,122,192,65,216,163,140,65,235,81,192,65,11,215,139,65,108,235,81,
192,65,175,71,139,65,108,40,92,189,65,144,194,151,65,108,40,92,187,65,144,194,159,65,113,40,92,179,65,236,81,194,65,81,184,170,65,72,225,228,65,108,0,0,168,65,174,71,241,65,108,0,0,168,65,174,71,241,65,108,154,165,167,65,119,181,242,65,108,8,57,167,65,
71,30,244,65,108,145,186,166,65,55,129,245,65,108,133,42,166,65,98,221,246,65,108,64,137,165,65,236,49,248,65,108,195,245,164,65,174,71,249,65,108,195,245,164,65,174,71,249,65,108,195,245,164,65,174,71,249,65,108,195,13,164,65,225,5,250,65,108,140,28,
163,65,63,184,250,65,108,183,34,162,65,86,94,251,65,108,229,32,161,65,186,247,251,65,108,188,23,160,65,11,132,252,65,108,227,7,159,65,239,2,253,65,108,11,242,157,65,20,116,253,65,108,227,214,156,65,49,215,253,65,108,34,183,155,65,8,44,254,65,108,128,
147,154,65,98,114,254,65,108,182,108,153,65,19,170,254,65,108,131,67,152,65,246,210,254,65,108,163,24,151,65,241,236,254,65,108,215,236,149,65,244,247,254,65,108,195,245,148,65,194,245,254,65,108,195,245,148,65,194,245,254,65,108,195,245,148,65,194,245,
254,65,108,194,245,148,65,194,245,254,65,108,226,31,148,65,208,252,254,65,108,235,73,147,65,43,249,254,65,108,104,116,146,65,214,234,254,65,108,225,159,145,65,217,209,254,65,108,221,204,144,65,70,174,254,65,108,227,251,143,65,49,128,254,65,108,123,45,
143,65,186,71,254,65,108,38,98,142,65,4,5,254,65,108,105,154,141,65,57,184,253,65,108,193,214,140,65,140,97,253,65,108,174,23,140,65,51,1,253,65,108,168,93,139,65,108,151,252,65,108,39,169,138,65,123,36,252,65,108,158,250,137,65,169,168,251,65,108,126,
82,137,65,70,36,251,65,108,49,177,136,65,166,151,250,65,108,31,23,136,65,35,3,250,65,108,0,0,136,65,133,235,249,65,108,0,0,136,65,133,235,249,65,108,0,0,136,65,133,235,249,65,108,62,130,135,65,129,92,249,65,108,201,11,135,65,97,199,248,65,108,238,156,
134,65,134,44,248,65,108,245,53,134,65,82,140,247,65,108,30,215,133,65,43,231,246,65,108,166,128,133,65,124,61,246,65,108,197,50,133,65,177,143,245,65,108,172,237,132,65,57,222,244,65,108,137,177,132,65,134,41,244,65,108,128,126,132,65,11,114,243,65,
108,180,84,132,65,62,184,242,65,108,62,52,132,65,149,252,241,65,108,52,29,132,65,137,63,241,65,108,164,15,132,65,147,129,240,65,108,150,11,132,65,45,195,239,65,108,14,17,132,65,207,4,239,65,108,123,20,132,65,205,204,238,65,108,123,20,132,65,205,204,238,
65,108,123,20,132,65,205,204,238,65,108,249,34,132,65,110,34,238,65,108,247,57,132,65,254,120,237,65,108,101,89,132,65,234,208,236,65,108,47,129,132,65,158,42,236,65,108,60,177,132,65,133,134,235,65,108,82,184,132,65,164,112,235,65,108,82,184,132,65,
164,112,235,65,108,82,184,132,65,164,112,235,65,98,82,184,132,65,215,163,234,65,184,30,133,65,10,215,233,65,31,133,133,65,195,245,232,65,113,62,10,149,65,195,245,188,65,215,163,164,65,195,245,144,65,98,113,61,162,65,246,40,142,65,133,235,159,65,164,112,
139,65,154,153,157,65,195,245,136,65,108,215,163,88,65,41,92,27,65,108,215,163,88,65,41,92,27,65,108,18,241,87,65,185,170,26,65,108,101,71,87,65,146,240,25,65,108,59,167,86,65,44,46,25,65,108,252,16,86,65,3,100,24,65,108,8,133,85,65,152,146,23,65,108,
183,3,85,65,114,186,22,65,108,94,141,84,65,26,220,21,65,108,72,34,84,65,31,248,20,65,108,184,194,83,65,19,15,20,65,108,237,110,83,65,139,33,19,65,108,28,39,83,65,30,48,18,65,108,115,235,82,65,104,59,17,65,108,24,188,82,65,5,68,16,65,108,41,153,82,65,
147,74,15,65,108,189,130,82,65,178,79,14,65,108,226,120,82,65,3,84,13,65,108,159,123,82,65,38,88,12,65,108,241,138,82,65,188,92,11,65,108,207,166,82,65,103,98,10,65,108,39,207,82,65,199,105,9,65,108,224,3,83,65,122,115,8,65,108,214,68,83,65,31,128,7,
65,108,226,145,83,65,80,144,6,65,108,209,234,83,65,168,164,5,65,108,107,79,84,65,190,189,4,65,108,112,191,84,65,36,220,3,65,108,150,58,85,65,108,0,3,65,108,145,192,85,65,34,43,2,65,108,10,81,86,65,207,92,1,65,108,165,235,86,65,245,149,0,65,108,254,143,
87,65,44,174,255,64,108,173,61,88,65,85,65,254,64,108,66,244,88,65,79,230,252,64,108,73,179,89,65,248,157,251,64,108,143,194,89,65,30,133,251,64,108,143,194,89,65,31,133,251,64,108,143,194,89,65,31,133,251,64,108,228,141,90,65,231,32,250,64,108,222,97,
91,65,116,209,248,64,108,247,61,92,65,158,151,247,64,108,161,33,93,65,44,116,246,64,108,75,12,94,65,216,103,245,64,108,94,253,94,65,80,115,244,64,108,65,244,95,65,46,151,243,64,108,84,240,96,65,1,212,242,64,108,248,240,97,65,68,42,242,64,108,136,245,
98,65,102,154,241,64,108,92,253,99,65,192,36,241,64,108,205,7,101,65,160,201,240,64,108,47,20,102,65,62,137,240,64,108,215,33,103,65,198,99,240,64,108,25,48,104,65,77,89,240,64,108,72,62,105,65,220,105,240,64,108,182,75,106,65,102,149,240,64,108,183,
87,107,65,210,219,240,64,108,160,97,108,65,241,60,241,64,108,198,104,109,65,134,184,241,64,108,130,108,110,65,65,78,242,64,108,45,108,111,65,194,253,242,64,108,35,103,112,65,154,198,243,64,108,197,92,113,65,71,168,244,64,108,115,76,114,65,57,162,245,
64,108,151,53,115,65,209,179,246,64,108,153,23,116,65,96,220,247,64,108,234,241,116,65,38,27,249,64,108,253,195,117,65,90,111,250,64,108,78,141,118,65,32,216,251,64,108,89,77,119,65,146,84,253,64,108,166,3,120,65,189,227,254,64,108,225,122,120,65,0,0,
0,65,108,225,122,120,65,0,0,0,65,98,72,225,134,65,205,204,24,65,41,92,145,65,143,194,49,65,112,61,156,65,72,225,74,65,108,50,51,173,65,41,92,115,65,108,19,174,173,65,225,122,116,65,98,244,40,174,65,153,153,117,65,70,225,174,65,92,143,106,65,193,245,176,
65,123,20,94,65,108,193,245,176,65,195,245,92,65,108,0,0,184,65,184,30,53,65,98,10,215,185,65,10,215,39,65,143,194,187,65,92,143,26,65,20,174,189,65,164,112,13,65,108,20,174,189,65,164,112,13,65,108,54,195,190,65,198,99,6,65,108,228,170,191,65,233,122,
254,64,108,140,100,192,65,138,4,240,64,108,182,239,192,65,174,109,225,64,108,8,76,193,65,170,191,210,64,108,73,121,193,65,228,3,196,64,108,90,119,193,65,200,67,181,64,108,40,92,193,65,31,133,171,64,108,40,92,193,65,31,133,171,64,108,40,92,193,65,41,92,
167,64,108,40,92,193,65,41,92,167,64,98,71,225,192,65,164,112,141,64,214,163,194,65,41,92,95,64,122,20,190,65,215,163,48,64,108,122,20,190,65,215,163,48,64,108,65,68,189,65,169,17,41,64,108,48,104,188,65,39,213,33,64,108,210,128,187,65,244,242,26,64,
108,188,142,186,65,119,111,20,64,108,137,146,185,65,218,78,14,64,108,217,140,184,65,10,149,8,64,108,85,126,183,65,175,69,3,64,108,170,103,182,65,100,200,252,63,108,137,73,181,65,94,231,243,63,108,170,36,180,65,2,238,235,63,108,200,249,178,65,98,225,228,
63,108,163,201,177,65,8,198,222,63,108,253,148,176,65,216,159,217,63,108,156,92,175,65,30,114,213,63,108,71,33,174,65,136,63,210,63,108,201,227,172,65,32,10,208,63,108,235,81,172,65,42,92,207,63,108,235,81,172,65,41,92,207,63,108,235,81,172,65,40,92,
207,63,108,222,165,166,65,8,207,197,63,108,254,243,160,65,32,206,192,63,108,51,51,157,65,8,0,192,63,108,51,51,157,65,0,0,192,63,98,246,40,154,65,0,0,192,63,61,10,151,65,0,0,192,63,20,174,147,65,0,0,192,63,108,20,174,147,65,0,0,192,63,108,171,15,150,65,
240,141,169,63,108,113,130,152,65,136,10,149,63,108,215,4,155,65,232,130,130,63,108,64,149,157,65,208,5,100,63,108,9,50,160,65,48,42,71,63,108,134,217,162,65,104,133,46,63,108,3,138,165,65,64,39,26,63,108,202,65,168,65,192,28,10,63,108,92,143,170,65,
0,0,0,63,108,92,143,170,65,0,0,0,63,108,92,143,170,65,0,0,0,63,108,108,226,175,65,64,224,216,62,108,154,59,181,65,0,213,194,62,108,122,151,186,65,64,236,189,62,108,159,242,191,65,96,41,202,62,108,155,73,197,65,96,132,231,62,108,3,153,202,65,64,245,10,
63,108,113,221,207,65,16,159,42,63,108,135,19,213,65,64,171,82,63,108,239,55,218,65,48,128,129,63,108,205,204,222,65,72,225,154,63,108,205,204,222,65,72,225,154,63,108,205,204,222,65,72,225,154,63,108,20,150,224,65,88,200,165,63,108,17,86,226,65,152,
25,178,63,108,165,11,228,65,40,205,191,63,108,185,181,229,65,60,218,206,63,108,58,83,231,65,54,55,223,63,108,34,227,232,65,162,217,240,63,108,112,100,234,65,25,219,1,64,108,45,214,235,65,108,224,11,64,108,109,55,237,65,95,118,22,64,108,154,153,237,65,
155,153,25,64,108,154,153,237,65,154,153,25,64,108,154,153,237,65,153,153,25,64,108,160,15,238,65,234,141,29,64,108,212,139,238,65,196,81,33,64,108,230,13,239,65,195,226,36,64,108,130,149,239,65,155,62,40,64,108,82,34,240,65,40,99,43,64,108,251,179,240,
65,102,78,46,64,108,33,74,241,65,120,254,48,64,108,100,228,241,65,164,113,51,64,108,96,130,242,65,92,166,53,64,108,177,35,243,65,50,155,55,64,108,239,199,243,65,233,78,57,64,108,177,110,244,65,105,192,58,64,108,141,23,245,65,198,238,59,64,108,23,194,
245,65,62,217,60,64,108,225,109,246,65,59,127,61,64,108,126,26,247,65,84,224,61,64,108,126,199,247,65,72,252,61,64,108,116,116,248,65,8,211,61,64,108,241,32,249,65,174,100,61,64,108,134,204,249,65,127,177,60,64,108,198,118,250,65,240,185,59,64,108,67,
31,251,65,156,126,58,64,108,146,197,251,65,80,0,57,64,108,72,105,252,65,0,64,55,64,108,253,9,253,65,202,62,53,64,108,154,153,253,65,52,51,51,64,108,154,153,253,65,52,51,51,64,108,154,153,253,65,52,51,51,64,108,37,16,254,65,60,177,49,64,108,244,136,254,
65,36,95,48,64,108,185,3,255,65,198,61,47,64,108,38,128,255,65,220,77,46,64,108,234,253,255,65,254,143,45,64,108,91,62,0,66,166,4,45,64,108,28,126,0,66,44,172,44,64,108,15,190,0,66,203,134,44,64,108,12,254,0,66,153,148,44,64,108,233,61,1,66,142,213,44,
64,108,126,125,1,66,128,73,45,64,108,162,188,1,66,37,240,45,64,108,45,251,1,66,18,201,46,64,108,245,56,2,66,189,211,47,64,108,213,117,2,66,123,15,49,64,108,165,177,2,66,130,123,50,64,108,205,204,2,66,52,51,51,64,108,205,204,2,66,52,51,51,64,98,174,71,
5,66,20,174,71,64,174,71,5,66,20,174,71,64,102,102,4,66,61,10,119,64,99,101,0,0 };
const uint8 visualStudio[] = { 110,109,0,0,112,65,0,0,0,0,108,0,0,227,64,0,0,253,64,108,0,0,0,64,0,0,128,64,108,0,0,0,0,0,0,160,64,108,0,0,0,0,0,0,112,65,108,0,0,0,64,0,0,128,65,108,0,0,224,64,0,0,64,65,108,0,0,112,65,0,0,160,65,108,0,0,160,65,0,0,144,65,108,0,0,160,65,0,0,0,64,108,
0,0,112,65,0,0,0,0,99,109,0,0,112,65,0,0,192,64,108,0,0,112,65,0,0,96,65,108,0,176,26,65,0,0,32,65,108,0,0,112,65,0,0,192,64,99,109,0,0,0,64,0,0,224,64,108,0,0,162,64,0,0,31,65,108,0,0,0,64,0,0,80,65,108,0,0,0,64,0,0,224,64,99,101,0,0 };
}
Icons::Icons()
{
#define JUCE_LOAD_PATH_DATA(name) \
name.loadPathFromData (IconPathData::name, sizeof (IconPathData::name));
/* Some of the icon images used here are based on icons from this project:
http://raphaeljs.com/icons
They're MIT licensed - the licensing info is on the linked page.
*/
JUCE_LOAD_PATH_DATA (imageDoc)
JUCE_LOAD_PATH_DATA (config)
JUCE_LOAD_PATH_DATA (graph)
JUCE_LOAD_PATH_DATA (info)
JUCE_LOAD_PATH_DATA (warning)
JUCE_LOAD_PATH_DATA (user)
JUCE_LOAD_PATH_DATA (closedFolder)
JUCE_LOAD_PATH_DATA (exporter)
JUCE_LOAD_PATH_DATA (fileExplorer)
JUCE_LOAD_PATH_DATA (file)
JUCE_LOAD_PATH_DATA (modules)
JUCE_LOAD_PATH_DATA (openFolder)
JUCE_LOAD_PATH_DATA (settings)
JUCE_LOAD_PATH_DATA (singleModule)
JUCE_LOAD_PATH_DATA (plus);
JUCE_LOAD_PATH_DATA (android);
JUCE_LOAD_PATH_DATA (codeBlocks);
JUCE_LOAD_PATH_DATA (linux);
JUCE_LOAD_PATH_DATA (xcode);
JUCE_LOAD_PATH_DATA (visualStudio);
}
@@ -0,0 +1,86 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
struct Icon
{
Icon() = default;
Icon (const Path& pathToUse, Colour pathColour)
: path (pathToUse),
colour (pathColour)
{
}
void draw (Graphics& g, const juce::Rectangle<float>& area, bool isCrossedOut) const
{
if (! path.isEmpty())
{
g.setColour (colour);
const RectanglePlacement placement (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize);
g.fillPath (path, placement.getTransformToFit (path.getBounds(), area));
if (isCrossedOut)
{
g.setColour (Colours::red.withAlpha (0.8f));
g.drawLine ((float) area.getX(), area.getY() + area.getHeight() * 0.2f,
(float) area.getRight(), area.getY() + area.getHeight() * 0.8f, 3.0f);
}
}
}
Icon withContrastingColourTo (Colour background) const
{
return Icon (path, background.contrasting (colour, 0.6f));
}
Icon withColour (Colour newColour)
{
return Icon (path, newColour);
}
Path path;
Colour colour;
};
//==============================================================================
class Icons
{
public:
Icons();
Path imageDoc, config, graph, info, warning, user, closedFolder, exporter, fileExplorer, file,
modules, openFolder, settings, singleModule, plus, android, codeBlocks,
linux, xcode, visualStudio;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Icons)
};
const Icons& getIcons();
@@ -0,0 +1,251 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "jucer_JucerTreeViewBase.h"
#include "../../Project/UI/jucer_ProjectContentComponent.h"
//==============================================================================
void TreePanelBase::setRoot (std::unique_ptr<JucerTreeViewBase> root)
{
rootItem = std::move (root);
tree.setRootItem (rootItem.get());
tree.getRootItem()->setOpen (true);
if (project != nullptr)
{
if (auto treeOpenness = project->getStoredProperties().getXmlValue (opennessStateKey))
{
tree.restoreOpennessState (*treeOpenness, true);
for (int i = tree.getNumSelectedItems(); --i >= 0;)
if (auto item = dynamic_cast<JucerTreeViewBase*> (tree.getSelectedItem (i)))
item->cancelDelayedSelectionTimer();
}
}
}
void TreePanelBase::saveOpenness()
{
if (project != nullptr)
{
std::unique_ptr<XmlElement> opennessState (tree.getOpennessState (true));
if (opennessState != nullptr)
project->getStoredProperties().setValue (opennessStateKey, opennessState.get());
else
project->getStoredProperties().removeValue (opennessStateKey);
}
}
//==============================================================================
JucerTreeViewBase::JucerTreeViewBase()
{
setLinesDrawnForSubItems (false);
setDrawsInLeftMargin (true);
}
void JucerTreeViewBase::refreshSubItems()
{
WholeTreeOpennessRestorer wtor (*this);
clearSubItems();
addSubItems();
}
Font JucerTreeViewBase::getFont() const
{
return Font ((float) getItemHeight() * 0.6f);
}
void JucerTreeViewBase::paintOpenCloseButton (Graphics& g, const Rectangle<float>& area, Colour /*backgroundColour*/, bool isMouseOver)
{
g.setColour (getOwnerView()->findColour (isSelected() ? defaultHighlightedTextColourId : treeIconColourId));
TreeViewItem::paintOpenCloseButton (g, area, getOwnerView()->findColour (defaultIconColourId), isMouseOver);
}
void JucerTreeViewBase::paintIcon (Graphics& g, Rectangle<float> area)
{
g.setColour (getContentColour (true));
getIcon().draw (g, area, isIconCrossedOut());
textX = roundToInt (area.getRight()) + 7;
}
void JucerTreeViewBase::paintItem (Graphics& g, int width, int height)
{
ignoreUnused (width, height);
auto bounds = g.getClipBounds().withY (0).withHeight (height).toFloat();
g.setColour (getOwnerView()->findColour (treeIconColourId).withMultipliedAlpha (0.4f));
g.fillRect (bounds.removeFromBottom (0.5f).reduced (5, 0));
}
Colour JucerTreeViewBase::getContentColour (bool isIcon) const
{
if (isMissing()) return Colours::red;
if (isSelected()) return getOwnerView()->findColour (defaultHighlightedTextColourId);
if (hasWarnings()) return getOwnerView()->findColour (defaultHighlightColourId);
return getOwnerView()->findColour (isIcon ? treeIconColourId : defaultTextColourId);
}
void JucerTreeViewBase::paintContent (Graphics& g, Rectangle<int> area)
{
g.setFont (getFont());
g.setColour (getContentColour (false));
g.drawFittedText (getDisplayName(), area, Justification::centredLeft, 1, 1.0f);
}
std::unique_ptr<Component> JucerTreeViewBase::createItemComponent()
{
return std::make_unique<TreeItemComponent> (*this);
}
//==============================================================================
class RenameTreeItemCallback final : public ModalComponentManager::Callback
{
public:
RenameTreeItemCallback (JucerTreeViewBase& ti, Component& parent, const Rectangle<int>& bounds)
: item (ti)
{
ed.setMultiLine (false, false);
ed.setPopupMenuEnabled (false);
ed.setSelectAllWhenFocused (true);
ed.setFont (item.getFont());
ed.onReturnKey = [this] { ed.exitModalState (1); };
ed.onEscapeKey = [this] { ed.exitModalState (0); };
ed.onFocusLost = [this] { ed.exitModalState (0); };
ed.setText (item.getRenamingName());
ed.setBounds (bounds);
parent.addAndMakeVisible (ed);
ed.enterModalState (true, this);
}
void modalStateFinished (int resultCode) override
{
if (resultCode != 0)
item.setName (ed.getText());
}
private:
struct RenameEditor final : public TextEditor
{
void inputAttemptWhenModal() override { exitModalState (0); }
};
RenameEditor ed;
JucerTreeViewBase& item;
JUCE_DECLARE_NON_COPYABLE (RenameTreeItemCallback)
};
void JucerTreeViewBase::showRenameBox()
{
Rectangle<int> r (getItemPosition (true));
r.setLeft (r.getX() + textX);
r.setHeight (getItemHeight());
new RenameTreeItemCallback (*this, *getOwnerView(), r);
}
void JucerTreeViewBase::itemClicked (const MouseEvent& e)
{
if (e.mods.isPopupMenu())
{
if (getOwnerView()->getNumSelectedItems() > 1)
showMultiSelectionPopupMenu (e.getMouseDownScreenPosition());
else
showPopupMenu (e.getMouseDownScreenPosition());
}
else if (isSelected())
{
itemSelectionChanged (true);
}
}
static void treeViewMenuItemChosen (int resultCode, WeakReference<JucerTreeViewBase> item)
{
if (item != nullptr)
item->handlePopupMenuResult (resultCode);
}
void JucerTreeViewBase::launchPopupMenu (PopupMenu& m, Point<int> p)
{
m.showMenuAsync (PopupMenu::Options().withTargetScreenArea ({ p.x, p.y, 1, 1 }),
ModalCallbackFunction::create (treeViewMenuItemChosen, WeakReference<JucerTreeViewBase> (this)));
}
ProjectContentComponent* JucerTreeViewBase::getProjectContentComponent() const
{
for (Component* c = getOwnerView(); c != nullptr; c = c->getParentComponent())
if (ProjectContentComponent* pcc = dynamic_cast<ProjectContentComponent*> (c))
return pcc;
return nullptr;
}
//==============================================================================
class JucerTreeViewBase::ItemSelectionTimer final : public Timer
{
public:
explicit ItemSelectionTimer (JucerTreeViewBase& tvb) : owner (tvb) {}
void timerCallback() override { owner.invokeShowDocument(); }
private:
JucerTreeViewBase& owner;
JUCE_DECLARE_NON_COPYABLE (ItemSelectionTimer)
};
void JucerTreeViewBase::itemSelectionChanged (bool isNowSelected)
{
if (isNowSelected)
{
delayedSelectionTimer.reset (new ItemSelectionTimer (*this));
delayedSelectionTimer->startTimer (getMillisecsAllowedForDragGesture());
}
else
{
cancelDelayedSelectionTimer();
}
}
void JucerTreeViewBase::invokeShowDocument()
{
cancelDelayedSelectionTimer();
showDocument();
}
void JucerTreeViewBase::itemDoubleClicked (const MouseEvent&)
{
invokeShowDocument();
}
void JucerTreeViewBase::cancelDelayedSelectionTimer()
{
delayedSelectionTimer.reset();
}
@@ -0,0 +1,248 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
class ProjectContentComponent;
class Project;
//==============================================================================
class JucerTreeViewBase : public TreeViewItem,
public TooltipClient
{
public:
JucerTreeViewBase();
~JucerTreeViewBase() override = default;
int getItemWidth() const override { return -1; }
int getItemHeight() const override { return 25; }
void paintOpenCloseButton (Graphics&, const Rectangle<float>& area, Colour backgroundColour, bool isMouseOver) override;
void paintItem (Graphics& g, int width, int height) override;
void itemClicked (const MouseEvent& e) override;
void itemSelectionChanged (bool isNowSelected) override;
void itemDoubleClicked (const MouseEvent&) override;
std::unique_ptr<Component> createItemComponent() override;
String getTooltip() override { return {}; }
String getAccessibilityName() override { return getDisplayName(); }
void cancelDelayedSelectionTimer();
//==============================================================================
virtual bool isRoot() const { return false; }
virtual Font getFont() const;
virtual String getRenamingName() const = 0;
virtual String getDisplayName() const = 0;
virtual void setName (const String& newName) = 0;
virtual bool isMissing() const = 0;
virtual bool hasWarnings() const { return false; }
virtual Icon getIcon() const = 0;
virtual bool isIconCrossedOut() const { return false; }
virtual void paintIcon (Graphics& g, Rectangle<float> area);
virtual void paintContent (Graphics& g, Rectangle<int> area);
virtual int getRightHandButtonSpace() { return 0; }
virtual Colour getContentColour (bool isIcon) const;
virtual int getMillisecsAllowedForDragGesture() { return 120; }
virtual File getDraggableFile() const { return {}; }
void refreshSubItems();
void showRenameBox();
virtual void deleteItem() {}
virtual void deleteAllSelectedItems() {}
virtual void showDocument() {}
virtual void showMultiSelectionPopupMenu (Point<int>) {}
virtual void showPopupMenu (Point<int>) {}
virtual void showAddMenu (Point<int>) {}
virtual void handlePopupMenuResult (int) {}
virtual void setSearchFilter (const String&) {}
void launchPopupMenu (PopupMenu&, Point<int>); // runs asynchronously, and produces a callback to handlePopupMenuResult().
//==============================================================================
// To handle situations where an item gets deleted before openness is
// restored for it, this OpennessRestorer keeps only a pointer to the
// topmost tree item.
struct WholeTreeOpennessRestorer final : public OpennessRestorer
{
WholeTreeOpennessRestorer (TreeViewItem& item) : OpennessRestorer (getTopLevelItem (item))
{}
private:
static TreeViewItem& getTopLevelItem (TreeViewItem& item)
{
if (TreeViewItem* const p = item.getParentItem())
return getTopLevelItem (*p);
return item;
}
};
int textX = 0;
protected:
ProjectContentComponent* getProjectContentComponent() const;
virtual void addSubItems() {}
private:
class ItemSelectionTimer;
std::unique_ptr<Timer> delayedSelectionTimer;
void invokeShowDocument();
JUCE_DECLARE_WEAK_REFERENCEABLE (JucerTreeViewBase)
};
//==============================================================================
class TreePanelBase : public Component
{
public:
TreePanelBase (const Project* p, const String& treeviewID)
: project (p), opennessStateKey (treeviewID)
{
addAndMakeVisible (tree);
tree.setRootItemVisible (true);
tree.setDefaultOpenness (true);
tree.setColour (TreeView::backgroundColourId, Colours::transparentBlack);
tree.setIndentSize (14);
tree.getViewport()->setScrollBarThickness (6);
tree.addMouseListener (this, true);
}
~TreePanelBase() override
{
tree.setRootItem (nullptr);
}
void setRoot (std::unique_ptr<JucerTreeViewBase>);
void saveOpenness();
virtual void deleteSelectedItems()
{
if (rootItem != nullptr)
rootItem->deleteAllSelectedItems();
}
void setEmptyTreeMessage (const String& newMessage)
{
if (emptyTreeMessage != newMessage)
{
emptyTreeMessage = newMessage;
repaint();
}
}
static void drawEmptyPanelMessage (Component& comp, Graphics& g, const String& message)
{
const int fontHeight = 13;
const Rectangle<int> area (comp.getLocalBounds());
g.setColour (comp.findColour (defaultTextColourId));
g.setFont ((float) fontHeight);
g.drawFittedText (message, area.reduced (4, 2), Justification::centred, area.getHeight() / fontHeight);
}
void paint (Graphics& g) override
{
if (emptyTreeMessage.isNotEmpty() && (rootItem == nullptr || rootItem->getNumSubItems() == 0))
drawEmptyPanelMessage (*this, g, emptyTreeMessage);
}
void resized() override
{
tree.setBounds (getAvailableBounds());
}
Rectangle<int> getAvailableBounds() const
{
return Rectangle<int> (0, 2, getWidth() - 2, getHeight() - 2);
}
void mouseDown (const MouseEvent& e) override
{
if (e.eventComponent == &tree)
{
tree.clearSelectedItems();
if (e.mods.isRightButtonDown())
rootItem->showPopupMenu (e.getMouseDownScreenPosition());
}
}
const Project* project;
TreeView tree;
std::unique_ptr<JucerTreeViewBase> rootItem;
private:
String opennessStateKey, emptyTreeMessage;
};
//==============================================================================
class TreeItemComponent final : public Component
{
public:
TreeItemComponent (JucerTreeViewBase& i) : item (&i)
{
setAccessible (false);
setInterceptsMouseClicks (false, true);
item->textX = iconWidth;
}
void paint (Graphics& g) override
{
if (item == nullptr)
return;
auto bounds = getLocalBounds().toFloat();
auto iconBounds = bounds.removeFromLeft ((float) iconWidth).reduced (7, 5);
bounds.removeFromRight ((float) buttons.size() * bounds.getHeight());
item->paintIcon (g, iconBounds);
item->paintContent (g, bounds.toNearestInt());
}
void resized() override
{
auto r = getLocalBounds();
for (int i = buttons.size(); --i >= 0;)
buttons.getUnchecked (i)->setBounds (r.removeFromRight (r.getHeight()));
}
void addRightHandButton (Component* button)
{
buttons.add (button);
addAndMakeVisible (button);
}
WeakReference<JucerTreeViewBase> item;
OwnedArray<Component> buttons;
const int iconWidth = 25;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeItemComponent)
};
@@ -0,0 +1,526 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "jucer_ProjucerLookAndFeel.h"
#include "../../Project/UI/jucer_ProjectContentComponent.h"
//==============================================================================
ProjucerLookAndFeel::ProjucerLookAndFeel()
{
setupColours();
}
ProjucerLookAndFeel::~ProjucerLookAndFeel() {}
void ProjucerLookAndFeel::drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
{
const auto area = button.getActiveArea();
auto backgroundColour = findColour (button.isFrontTab() ? secondaryBackgroundColourId
: inactiveTabBackgroundColourId);
g.setColour (backgroundColour);
g.fillRect (area);
const auto alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f;
auto textColour = findColour (defaultTextColourId).withMultipliedAlpha (alpha);
auto iconColour = findColour (button.isFrontTab() ? activeTabIconColourId
: inactiveTabIconColourId);
auto isProjectTab = button.getName() == ProjectContentComponent::getProjectTabName();
if (isProjectTab)
{
auto icon = Icon (getIcons().closedFolder,
iconColour.withMultipliedAlpha (alpha));
auto isSingleTab = (button.getTabbedButtonBar().getNumTabs() == 1);
if (isSingleTab)
{
auto activeArea = button.getActiveArea().reduced (5);
activeArea.removeFromLeft (15);
icon.draw (g, activeArea.removeFromLeft (activeArea.getHeight()).toFloat(), false);
activeArea.removeFromLeft (10);
g.setColour (textColour);
g.drawFittedText (ProjectContentComponent::getProjectTabName(),
activeArea, Justification::centredLeft, 1);
}
else
{
icon.draw (g, button.getTextArea().reduced (8, 8).toFloat(), false);
}
}
else
{
TextLayout textLayout;
LookAndFeel_V3::createTabTextLayout (button, (float) area.getWidth(), (float) area.getHeight(), textColour, textLayout);
textLayout.draw (g, button.getTextArea().toFloat());
}
}
int ProjucerLookAndFeel::getTabButtonBestWidth (TabBarButton& button, int)
{
if (TabbedButtonBar* bar = button.findParentComponentOfClass<TabbedButtonBar>())
return bar->getWidth() / bar->getNumTabs();
return 120;
}
void ProjucerLookAndFeel::drawPropertyComponentLabel (Graphics& g, int, int height, PropertyComponent& component)
{
g.setColour (component.findColour (defaultTextColourId)
.withMultipliedAlpha (component.isEnabled() ? 1.0f : 0.6f));
auto textWidth = getTextWidthForPropertyComponent (component);
g.setFont (getPropertyComponentFont());
g.drawFittedText (component.getName(), 0, 0, textWidth, height, Justification::centredLeft, 5, 1.0f);
}
Rectangle<int> ProjucerLookAndFeel::getPropertyComponentContentPosition (PropertyComponent& component)
{
const auto paddedTextW = getTextWidthForPropertyComponent (component) + 5;
return { paddedTextW , 0, component.getWidth() - paddedTextW, component.getHeight() - 1 };
}
void ProjucerLookAndFeel::drawButtonBackground (Graphics& g,
Button& button,
const Colour& backgroundColour,
bool isMouseOverButton,
bool isButtonDown)
{
const auto cornerSize = button.findParentComponentOfClass<PropertyComponent>() != nullptr ? 0.0f : 3.0f;
const auto bounds = button.getLocalBounds().toFloat();
auto baseColour = backgroundColour.withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f);
if (isButtonDown || isMouseOverButton)
baseColour = baseColour.contrasting (isButtonDown ? 0.2f : 0.05f);
g.setColour (baseColour);
if (button.isConnectedOnLeft() || button.isConnectedOnRight())
{
Path path;
path.addRoundedRectangle (bounds.getX(), bounds.getY(),
bounds.getWidth(), bounds.getHeight(),
cornerSize, cornerSize,
! button.isConnectedOnLeft(),
! button.isConnectedOnRight(),
! button.isConnectedOnLeft(),
! button.isConnectedOnRight());
g.fillPath (path);
}
else
{
g.fillRoundedRectangle (bounds, cornerSize);
}
}
void ProjucerLookAndFeel::drawButtonText (Graphics& g, TextButton& button, bool isMouseOverButton, bool isButtonDown)
{
ignoreUnused (isMouseOverButton, isButtonDown);
g.setFont (getTextButtonFont (button, button.getHeight()));
g.setColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId
: TextButton::textColourOffId)
.withMultipliedAlpha (button.isEnabled() ? 1.0f
: 0.5f));
auto xIndent = jmin (8, button.getWidth() / 10);
auto yIndent = jmin (3, button.getHeight() / 6);
auto textBounds = button.getLocalBounds().reduced (xIndent, yIndent);
g.drawFittedText (button.getButtonText(), textBounds, Justification::centred, 3, 1.0f);
}
void ProjucerLookAndFeel::drawToggleButton (Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown)
{
ignoreUnused (isMouseOverButton, isButtonDown);
if (! button.isEnabled())
g.setOpacity (0.5f);
bool isTextEmpty = button.getButtonText().isEmpty();
bool isPropertyComponentChild = (dynamic_cast<BooleanPropertyComponent*> (button.getParentComponent()) != nullptr
|| dynamic_cast<MultiChoicePropertyComponent*> (button.getParentComponent()) != nullptr);
auto bounds = button.getLocalBounds();
auto sideLength = isPropertyComponentChild ? 25 : bounds.getHeight();
auto rectBounds = isTextEmpty ? bounds
: bounds.removeFromLeft (jmin (sideLength, bounds.getWidth() / 3));
rectBounds = rectBounds.withSizeKeepingCentre (sideLength, sideLength).reduced (4);
g.setColour (button.findColour (ToggleButton::tickDisabledColourId));
g.drawRoundedRectangle (rectBounds.toFloat(), 2.0f, 1.0f);
if (button.getToggleState())
{
g.setColour (button.findColour (ToggleButton::tickColourId));
const auto tick = getTickShape (0.75f);
g.fillPath (tick, tick.getTransformToScaleToFit (rectBounds.reduced (2).toFloat(), false));
}
if (! isTextEmpty)
{
bounds.removeFromLeft (5);
const auto fontSize = jmin (15.0f, (float) button.getHeight() * 0.75f);
g.setFont (fontSize);
g.setColour (isPropertyComponentChild ? findColour (widgetTextColourId)
: button.findColour (ToggleButton::textColourId));
g.drawFittedText (button.getButtonText(), bounds, Justification::centredLeft, 2);
}
}
void ProjucerLookAndFeel::fillTextEditorBackground (Graphics& g, int width, int height, TextEditor& textEditor)
{
g.setColour (textEditor.findColour (TextEditor::backgroundColourId));
g.fillRect (0, 0, width, height);
g.setColour (textEditor.findColour (TextEditor::outlineColourId));
g.drawHorizontalLine (height - 1, 0.0f, static_cast<float> (width));
}
void ProjucerLookAndFeel::layoutFileBrowserComponent (FileBrowserComponent& browserComp,
DirectoryContentsDisplayComponent* fileListComponent,
FilePreviewComponent* previewComp,
ComboBox* currentPathBox,
TextEditor* filenameBox,
Button* goUpButton)
{
const auto sectionHeight = 22;
const auto buttonWidth = 50;
auto b = browserComp.getLocalBounds().reduced (20, 5);
auto topSlice = b.removeFromTop (sectionHeight);
auto bottomSlice = b.removeFromBottom (sectionHeight);
currentPathBox->setBounds (topSlice.removeFromLeft (topSlice.getWidth() - buttonWidth));
currentPathBox->setColour (ComboBox::backgroundColourId, findColour (backgroundColourId));
currentPathBox->setColour (ComboBox::textColourId, findColour (defaultTextColourId));
currentPathBox->setColour (ComboBox::arrowColourId, findColour (defaultTextColourId));
topSlice.removeFromLeft (6);
goUpButton->setBounds (topSlice);
bottomSlice.removeFromLeft (50);
filenameBox->setBounds (bottomSlice);
filenameBox->setColour (TextEditor::backgroundColourId, findColour (backgroundColourId));
filenameBox->setColour (TextEditor::textColourId, findColour (defaultTextColourId));
filenameBox->setColour (TextEditor::outlineColourId, findColour (defaultTextColourId));
filenameBox->applyFontToAllText (filenameBox->getFont());
if (previewComp != nullptr)
previewComp->setBounds (b.removeFromRight (b.getWidth() / 3));
if (auto listAsComp = dynamic_cast<Component*> (fileListComponent))
listAsComp->setBounds (b.reduced (0, 10));
}
void ProjucerLookAndFeel::drawFileBrowserRow (Graphics& g, int width, int height,
const File& file, const String& filename, Image* icon,
const String& fileSizeDescription,
const String& fileTimeDescription,
bool isDirectory, bool isItemSelected,
int itemIndex, DirectoryContentsDisplayComponent& dcc)
{
if (auto fileListComp = dynamic_cast<Component*> (&dcc))
{
fileListComp->setColour (DirectoryContentsDisplayComponent::textColourId,
findColour (isItemSelected ? defaultHighlightedTextColourId : defaultTextColourId));
fileListComp->setColour (DirectoryContentsDisplayComponent::highlightColourId,
findColour (defaultHighlightColourId).withAlpha (0.75f));
}
LookAndFeel_V2::drawFileBrowserRow (g, width, height, file, filename, icon,
fileSizeDescription, fileTimeDescription,
isDirectory, isItemSelected, itemIndex, dcc);
}
void ProjucerLookAndFeel::drawCallOutBoxBackground (CallOutBox&, Graphics& g, const Path& path, Image&)
{
g.setColour (findColour (secondaryBackgroundColourId));
g.fillPath (path);
g.setColour (findColour (userButtonBackgroundColourId));
g.strokePath (path, PathStrokeType (2.0f));
}
void ProjucerLookAndFeel::drawMenuBarBackground (Graphics& g, int width, int height,
bool, MenuBarComponent& menuBar)
{
const auto colour = menuBar.findColour (backgroundColourId).withAlpha (0.75f);
Rectangle<int> r (width, height);
g.setColour (colour.contrasting (0.15f));
g.fillRect (r.removeFromTop (1));
g.fillRect (r.removeFromBottom (1));
g.setGradientFill (ColourGradient (colour, 0, 0, colour.darker (0.2f), 0, (float)height, false));
g.fillRect (r);
}
void ProjucerLookAndFeel::drawMenuBarItem (Graphics& g, int width, int height,
int itemIndex, const String& itemText,
bool isMouseOverItem, bool isMenuOpen,
bool /*isMouseOverBar*/, MenuBarComponent& menuBar)
{
if (! menuBar.isEnabled())
{
g.setColour (menuBar.findColour (defaultTextColourId)
.withMultipliedAlpha (0.5f));
}
else if (isMenuOpen || isMouseOverItem)
{
g.fillAll (menuBar.findColour (defaultHighlightColourId).withAlpha (0.75f));
g.setColour (menuBar.findColour (defaultHighlightedTextColourId));
}
else
{
g.setColour (menuBar.findColour (defaultTextColourId));
}
g.setFont (getMenuBarFont (menuBar, itemIndex, itemText));
g.drawFittedText (itemText, 0, 0, width, height, Justification::centred, 1);
}
void ProjucerLookAndFeel::drawResizableFrame (Graphics& g, int w, int h, const BorderSize<int>& border)
{
ignoreUnused (g, w, h, border);
}
void ProjucerLookAndFeel::drawComboBox (Graphics& g, int width, int height, bool,
int, int, int, int, ComboBox& box)
{
const auto cornerSize = box.findParentComponentOfClass<ChoicePropertyComponent>() != nullptr ? 0.0f : 1.5f;
Rectangle<int> boxBounds (0, 0, width, height);
auto isChoiceCompChild = (box.findParentComponentOfClass<ChoicePropertyComponent>() != nullptr);
if (isChoiceCompChild)
{
box.setColour (ComboBox::textColourId, findColour (widgetTextColourId));
g.setColour (findColour (widgetBackgroundColourId));
g.fillRect (boxBounds);
auto arrowZone = boxBounds.removeFromRight (boxBounds.getHeight()).reduced (0, 2).toFloat();
g.setColour (Colours::black);
g.fillPath (getChoiceComponentArrowPath (arrowZone));
}
else
{
g.setColour (box.findColour (ComboBox::outlineColourId));
g.drawRoundedRectangle (boxBounds.toFloat().reduced (0.5f, 0.5f), cornerSize, 1.0f);
auto arrowZone = boxBounds.removeFromRight (boxBounds.getHeight()).toFloat();
g.setColour (box.findColour (ComboBox::arrowColourId).withAlpha ((box.isEnabled() ? 0.9f : 0.2f)));
g.fillPath (getArrowPath (arrowZone, 2, true, Justification::centred));
}
}
void ProjucerLookAndFeel::drawTreeviewPlusMinusBox (Graphics& g, const Rectangle<float>& area,
Colour, bool isOpen, bool /**isMouseOver*/)
{
g.strokePath (getArrowPath (area, isOpen ? 2 : 1, false, Justification::centredRight), PathStrokeType (2.0f));
}
ProgressBar::Style ProjucerLookAndFeel::getDefaultProgressBarStyle (const ProgressBar&)
{
return ProgressBar::Style::circular;
}
//==============================================================================
Path ProjucerLookAndFeel::getArrowPath (Rectangle<float> arrowZone, const int direction,
bool filled, const Justification justification)
{
auto w = jmin (arrowZone.getWidth(), (direction == 0 || direction == 2) ? 8.0f : filled ? 5.0f : 8.0f);
auto h = jmin (arrowZone.getHeight(), (direction == 0 || direction == 2) ? 5.0f : filled ? 8.0f : 5.0f);
if (justification == Justification::centred)
{
arrowZone.reduce ((arrowZone.getWidth() - w) / 2, (arrowZone.getHeight() - h) / 2);
}
else if (justification == Justification::centredRight)
{
arrowZone.removeFromLeft (arrowZone.getWidth() - w);
arrowZone.reduce (0, (arrowZone.getHeight() - h) / 2);
}
else if (justification == Justification::centredLeft)
{
arrowZone.removeFromRight (arrowZone.getWidth() - w);
arrowZone.reduce (0, (arrowZone.getHeight() - h) / 2);
}
else
{
jassertfalse; // currently only supports centred justifications
}
Path path;
path.startNewSubPath (arrowZone.getX(), arrowZone.getBottom());
path.lineTo (arrowZone.getCentreX(), arrowZone.getY());
path.lineTo (arrowZone.getRight(), arrowZone.getBottom());
if (filled)
path.closeSubPath();
path.applyTransform (AffineTransform::rotation ((float) direction * MathConstants<float>::halfPi,
arrowZone.getCentreX(), arrowZone.getCentreY()));
return path;
}
Path ProjucerLookAndFeel::getChoiceComponentArrowPath (Rectangle<float> arrowZone)
{
auto topBounds = arrowZone.removeFromTop (arrowZone.getHeight() * 0.5f);
auto bottomBounds = arrowZone;
auto topArrow = getArrowPath (topBounds, 0, true, Justification::centred);
auto bottomArrow = getArrowPath (bottomBounds, 2, true, Justification::centred);
topArrow.addPath (bottomArrow);
return topArrow;
}
//==============================================================================
void ProjucerLookAndFeel::setupColours()
{
auto& colourScheme = getCurrentColourScheme();
if (colourScheme == getDarkColourScheme() || colourScheme == getProjucerDarkColourScheme())
{
setColour (backgroundColourId, Colour (0xff323e44));
setColour (secondaryBackgroundColourId, Colour (0xff263238));
setColour (defaultTextColourId, Colours::white);
setColour (widgetTextColourId, Colours::white);
setColour (defaultButtonBackgroundColourId, Colour (0xffa45c94));
setColour (secondaryButtonBackgroundColourId, Colours::black);
setColour (userButtonBackgroundColourId, Colour (0xffa45c94));
setColour (defaultIconColourId, Colours::white);
setColour (treeIconColourId, Colour (0xffa9a9a9));
setColour (defaultHighlightColourId, Colour (0xffe0ec65));
setColour (defaultHighlightedTextColourId, Colours::black);
setColour (codeEditorLineNumberColourId, Colour (0xffaaaaaa));
setColour (activeTabIconColourId, Colours::white);
setColour (inactiveTabBackgroundColourId, Colour (0xff181f22));
setColour (inactiveTabIconColourId, Colour (0xffa9a9a9));
setColour (contentHeaderBackgroundColourId, Colours::black);
setColour (widgetBackgroundColourId, Colour (0xff495358));
setColour (secondaryWidgetBackgroundColourId, Colour (0xff303b41));
colourScheme = getProjucerDarkColourScheme();
}
else if (colourScheme == getGreyColourScheme())
{
setColour (backgroundColourId, Colour (0xff505050));
setColour (secondaryBackgroundColourId, Colour (0xff424241));
setColour (defaultTextColourId, Colours::white);
setColour (widgetTextColourId, Colours::black);
setColour (defaultButtonBackgroundColourId, Colour (0xff26ba90));
setColour (secondaryButtonBackgroundColourId, Colours::black);
setColour (userButtonBackgroundColourId, Colour (0xff26ba90));
setColour (defaultIconColourId, Colours::white);
setColour (treeIconColourId, Colour (0xffa9a9a9));
setColour (defaultHighlightColourId, Colour (0xffe0ec65));
setColour (defaultHighlightedTextColourId, Colours::black);
setColour (codeEditorLineNumberColourId, Colour (0xffaaaaaa));
setColour (activeTabIconColourId, Colours::white);
setColour (inactiveTabBackgroundColourId, Colour (0xff373737));
setColour (inactiveTabIconColourId, Colour (0xffa9a9a9));
setColour (contentHeaderBackgroundColourId, Colours::black);
setColour (widgetBackgroundColourId, Colours::white);
setColour (secondaryWidgetBackgroundColourId, Colour (0xffdddddd));
}
else if (colourScheme == getLightColourScheme())
{
setColour (backgroundColourId, Colour (0xffefefef));
setColour (secondaryBackgroundColourId, Colour (0xfff9f9f9));
setColour (defaultTextColourId, Colours::black);
setColour (widgetTextColourId, Colours::black);
setColour (defaultButtonBackgroundColourId, Colour (0xff42a2c8));
setColour (secondaryButtonBackgroundColourId, Colour (0xffa1c677));
setColour (userButtonBackgroundColourId, Colour (0xff42a2c8));
setColour (defaultIconColourId, Colours::white);
setColour (treeIconColourId, Colour (0xffa9a9a9));
setColour (defaultHighlightColourId, Colours::orange);
setColour (defaultHighlightedTextColourId, Colour (0xff585656));
setColour (codeEditorLineNumberColourId, Colour (0xff888888));
setColour (activeTabIconColourId, Colour (0xff42a2c8));
setColour (inactiveTabBackgroundColourId, Colour (0xffd5d5d5));
setColour (inactiveTabIconColourId, Colour (0xffa9a9a9));
setColour (contentHeaderBackgroundColourId, Colour (0xff42a2c8));
setColour (widgetBackgroundColourId, Colours::white);
setColour (secondaryWidgetBackgroundColourId, Colour (0xfff4f4f4));
}
setColour (Label::textColourId, findColour (defaultTextColourId));
setColour (Label::textWhenEditingColourId, findColour (widgetTextColourId));
setColour (TextEditor::highlightColourId, findColour (defaultHighlightColourId).withAlpha (0.75f));
setColour (TextEditor::highlightedTextColourId, findColour (defaultHighlightedTextColourId));
setColour (TextEditor::outlineColourId, Colours::transparentBlack);
setColour (TextEditor::focusedOutlineColourId, Colours::transparentBlack);
setColour (TextEditor::backgroundColourId, findColour (widgetBackgroundColourId));
setColour (TextEditor::textColourId, findColour (widgetTextColourId));
setColour (TextButton::buttonColourId, findColour (defaultButtonBackgroundColourId));
setColour (ScrollBar::ColourIds::thumbColourId, Colour (0xffd0d8e0));
setColour (TextPropertyComponent::outlineColourId, Colours::transparentBlack);
setColour (TextPropertyComponent::backgroundColourId, findColour (widgetBackgroundColourId));
setColour (TextPropertyComponent::textColourId, findColour (widgetTextColourId));
setColour (BooleanPropertyComponent::outlineColourId, Colours::transparentBlack);
setColour (BooleanPropertyComponent::backgroundColourId, findColour (widgetBackgroundColourId));
setColour (ToggleButton::tickDisabledColourId, Colour (0xffa9a9a9));
setColour (ToggleButton::tickColourId, findColour (defaultButtonBackgroundColourId).withMultipliedBrightness (1.3f));
setColour (CodeEditorComponent::backgroundColourId, findColour (secondaryBackgroundColourId));
setColour (CodeEditorComponent::lineNumberTextId, findColour (codeEditorLineNumberColourId));
setColour (CodeEditorComponent::lineNumberBackgroundId, findColour (backgroundColourId));
setColour (CodeEditorComponent::highlightColourId, findColour (defaultHighlightColourId).withAlpha (0.5f));
setColour (CaretComponent::caretColourId, findColour (defaultButtonBackgroundColourId));
setColour (TreeView::selectedItemBackgroundColourId, findColour (defaultHighlightColourId));
setColour (PopupMenu::highlightedBackgroundColourId, findColour (defaultHighlightColourId).withAlpha (0.75f));
setColour (PopupMenu::highlightedTextColourId, findColour (defaultHighlightedTextColourId));
setColour (ProgressBar::foregroundColourId, findColour (defaultButtonBackgroundColourId));
setColour (0x1000440, /*LassoComponent::lassoFillColourId*/ findColour (defaultHighlightColourId).withAlpha (0.3f));
}
@@ -0,0 +1,100 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
//==============================================================================
class ProjucerLookAndFeel : public LookAndFeel_V4
{
public:
ProjucerLookAndFeel();
~ProjucerLookAndFeel() override;
void drawTabButton (TabBarButton& button, Graphics&, bool isMouseOver, bool isMouseDown) override;
int getTabButtonBestWidth (TabBarButton&, int tabDepth) override;
void drawTabAreaBehindFrontButton (TabbedButtonBar&, Graphics&, int, int) override {}
void drawPropertyComponentBackground (Graphics&, int, int, PropertyComponent&) override {}
void drawPropertyComponentLabel (Graphics&, int width, int height, PropertyComponent&) override;
Rectangle<int> getPropertyComponentContentPosition (PropertyComponent&) override;
void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour,
bool isMouseOverButton, bool isButtonDown) override;
void drawButtonText (Graphics&, TextButton&, bool isMouseOverButton, bool isButtonDown) override;
void drawToggleButton (Graphics&, ToggleButton&, bool isMouseOverButton, bool isButtonDown) override;
void drawTextEditorOutline (Graphics&, int, int, TextEditor&) override {}
void fillTextEditorBackground (Graphics&, int width, int height, TextEditor&) override;
void layoutFileBrowserComponent (FileBrowserComponent&, DirectoryContentsDisplayComponent*,
FilePreviewComponent*, ComboBox* currentPathBox,
TextEditor* filenameBox,Button* goUpButton) override;
void drawFileBrowserRow (Graphics&, int width, int height, const File&, const String& filename, Image* icon,
const String& fileSizeDescription, const String& fileTimeDescription,
bool isDirectory, bool isItemSelected, int itemIndex, DirectoryContentsDisplayComponent&) override;
void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path&, Image&) override;
void drawMenuBarBackground (Graphics&, int width, int height, bool isMouseOverBar, MenuBarComponent&) override;
void drawMenuBarItem (Graphics&, int width, int height,
int itemIndex, const String& itemText,
bool isMouseOverItem, bool isMenuOpen, bool isMouseOverBar,
MenuBarComponent&) override;
void drawResizableFrame (Graphics&, int w, int h, const BorderSize<int>&) override;
void drawComboBox (Graphics&, int width, int height, bool isButtonDown,
int buttonX, int buttonY, int buttonW, int buttonH,
ComboBox&) override;
void drawTreeviewPlusMinusBox (Graphics&, const Rectangle<float>& area,
Colour backgroundColour, bool isItemOpen, bool isMouseOver) override;
ProgressBar::Style getDefaultProgressBarStyle (const ProgressBar&) override;
//==============================================================================
static Path getArrowPath (Rectangle<float> arrowZone, int direction,
bool filled, Justification justification);
static Path getChoiceComponentArrowPath (Rectangle<float> arrowZone);
static Font getPropertyComponentFont() { return { 14.0f, Font::FontStyleFlags::bold }; }
static int getTextWidthForPropertyComponent (const PropertyComponent& pc) { return jmin (200, pc.getWidth() / 2); }
static ColourScheme getProjucerDarkColourScheme()
{
return { 0xff323e44, 0xff263238, 0xff323e44,
0xff8e989b, 0xffffffff, 0xffa45c94,
0xffffffff, 0xff181f22, 0xffffffff };
}
//==============================================================================
void setupColours();
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjucerLookAndFeel)
};
@@ -0,0 +1,118 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../../Application/jucer_Headers.h"
#include "jucer_SlidingPanelComponent.h"
//==============================================================================
struct SlidingPanelComponent::DotButton final : public Button
{
DotButton (SlidingPanelComponent& sp, int pageIndex)
: Button (String()), owner (sp), index (pageIndex) {}
void paintButton (Graphics& g, bool /*isMouseOverButton*/, bool /*isButtonDown*/) override
{
g.setColour (findColour (defaultButtonBackgroundColourId));
const auto r = getLocalBounds().reduced (getWidth() / 4).toFloat();
if (index == owner.getCurrentTabIndex())
g.fillEllipse (r);
else
g.drawEllipse (r, 1.0f);
}
void clicked() override
{
owner.goToTab (index);
}
using Button::clicked;
SlidingPanelComponent& owner;
int index;
};
//==============================================================================
SlidingPanelComponent::SlidingPanelComponent()
: currentIndex (0), dotSize (20)
{
addAndMakeVisible (pageHolder);
}
SlidingPanelComponent::~SlidingPanelComponent()
{
}
SlidingPanelComponent::PageInfo::~PageInfo()
{
if (shouldDelete)
content.deleteAndZero();
}
void SlidingPanelComponent::addTab (const String& tabName,
Component* const contentComponent,
const bool deleteComponentWhenNotNeeded,
const int insertIndex)
{
PageInfo* page = new PageInfo();
pages.insert (insertIndex, page);
page->content = contentComponent;
page->dotButton.reset (new DotButton (*this, pages.indexOf (page)));
addAndMakeVisible (page->dotButton.get());
page->name = tabName;
page->shouldDelete = deleteComponentWhenNotNeeded;
pageHolder.addAndMakeVisible (contentComponent);
resized();
}
void SlidingPanelComponent::goToTab (int targetTabIndex)
{
currentIndex = targetTabIndex;
Desktop::getInstance().getAnimator()
.animateComponent (&pageHolder, pageHolder.getBounds().withX (-targetTabIndex * getWidth()),
1.0f, 600, false, 0.0, 0.0);
repaint();
}
void SlidingPanelComponent::resized()
{
pageHolder.setBounds (-currentIndex * getWidth(), pageHolder.getPosition().y,
getNumTabs() * getWidth(), getHeight());
Rectangle<int> content (getLocalBounds());
Rectangle<int> dotHolder = content.removeFromBottom (20 + dotSize)
.reduced ((content.getWidth() - dotSize * getNumTabs()) / 2, 10);
for (int i = 0; i < getNumTabs(); ++i)
pages.getUnchecked (i)->dotButton->setBounds (dotHolder.removeFromLeft (dotSize));
for (int i = pages.size(); --i >= 0;)
if (Component* c = pages.getUnchecked (i)->content)
c->setBounds (content.translated (i * content.getWidth(), 0));
}
@@ -0,0 +1,78 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "../../Application/jucer_Application.h"
//==============================================================================
class SlidingPanelComponent final : public Component
{
public:
SlidingPanelComponent();
~SlidingPanelComponent() override;
/** Adds a new tab to the panel slider. */
void addTab (const String& tabName,
Component* contentComponent,
bool deleteComponentWhenNotNeeded,
int insertIndex = -1);
/** Gets rid of one of the tabs. */
void removeTab (int tabIndex);
/** Gets index of current tab. */
int getCurrentTabIndex() const noexcept { return currentIndex; }
/** Returns the number of tabs. */
int getNumTabs() const noexcept { return pages.size(); }
/** Animates the window to the desired tab. */
void goToTab (int targetTabIndex);
//==============================================================================
/** @internal */
void resized() override;
private:
struct DotButton;
struct PageInfo
{
~PageInfo();
Component::SafePointer<Component> content;
std::unique_ptr<DotButton> dotButton;
String name;
bool shouldDelete;
};
OwnedArray<PageInfo> pages;
Component pageHolder;
int currentIndex, dotSize;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SlidingPanelComponent)
};