Angular Editables is a project thatis designed to fill a particular niche when working with AngularJS projects. Specifically, it's all about turning html elements into editable inputs that are easy to bind to. This is similar in concept to the x-editables project, with a few big exceptions:
contenteditable
under the hood.As with most libraries of this nature, Editables has been designed to scratch my particular itch, and isn't necessarily the best general design possible. Still, it's here in case you find it useful. If you'd like to improve the project, fix an issue you've found, or otherwise make changes, feel free to fork it.
Click on the editable to edit it. As you can see, it works exactly as you'd expect. If you look at the source, you'll notice that the contents of the element are used as placeholder text, when the editable's value is empty. While this might be a little bit confusing, it means that you can have placeholder text, as well as an initial value, by binding to a model that's already populated.
Even though this is the most basic case, it's already as usable as your normal input element.
Editables are designed to work just like input elements, when it comes to binding them to models. Instead
of using ng-model="foo"
, however, you simply pass the value to the editable directive:
editable="foo
. This works just like you'd expect.
Play with both the input field, and the editable, to get a good feel for how the binding works.
By default, editables work like normal content editables, and support multi-line entry. However,
sometimes all you want is a single line entry. Editabled supports that too, by specifying
type="line"
. See for yourself.
Editables also supports toolbars to make specific types of editing easier. As you can see, we have a basic
WYSIWYG editor implemented. All you need to do is specify toolbar="text-edit"
.
The toolbar functionality is central to my concept to Editables. As such, most of my future development will be focused on adding user-defined toolbars, and expanding the list of built-in toolbars. (Currently, the only toolbar is the 'text-edit'.)
While the two-way binding is very useful, it's not desirable in some situations. For those, you want to
specify confirm="true"
, which will cause the editable to only submit when the save method
has been called. This isn't directly useful, without also including toolbar
(no value
required).
With both included, Editables renders a toolbar with Save and Cancel buttons. When you hit Save, the
value of the editable is saved to the model, and the `save` message is emitted up the scope tree. If you
instead hit Cancel, the field is reverted, and the 'cancel' message is emitted up the scope tree. (
Note: The name
property of the element is passed as the only argument to these messages.
)
Here's the WYSIWYG demo again, with confirm:
This also demonstrates support for a custom save callback. Simply specify the onsave
parameter,
setting it to an AngularJS expression. The name
parameter is passed in, and can be referenced
by the expression.


Facebook Pixel Auto Gen
Events
Select an Event
Pixel Params (** = REQUIRED, * = highly recommended)
How to fire
Page Load
Button Click
Where to place
Please add auto-gen "where to place" here...
Get Code
Well done!
- please copy and paste the code below


Undo Framework Example
In the Qt undo framework, all actions that the user performs are implemented in classes that inherit QUndoCommand. An undo command class knows how to both redo() - or just do the first time - and undo() an action. For each action the user performs, a command is placed on a QUndoStack. Since the stack contains all commands executed (stacked in chronological order) on the document, it can roll the state of the document backwards and forwards by undoing and redoing its commands. See the overview document for a high-level introduction to the undo framework.
The undo example implements a simple diagram application. It is possible to add and delete items, which are either box or rectangular shaped, and move the items by dragging them with the mouse. The undo stack is shown in a QUndoView, which is a list in which the commands are shown as list items. Undo and redo are available through the edit menu. The user can also select a command from the undo view.
We use the graphics view framework to implement the diagram. We only treat the related code briefly as the framework has examples of its own (e.g., the Diagram Scene Example).
The example consists of the following classes:
MainWindow
is the main window and arranges the example's widgets. It creates the commands based on user input and keeps them on the command stack.AddCommand
adds an item to the scene.DeleteCommand
deletes an item from the scene.MoveCommand
when an item is moved the MoveCommand keeps record of the start and stop positions of the move, and it moves the item according to these whenredo()
andundo()
is called.DiagramScene
inherits QGraphicsScene and emits signals for theMoveComands
when an item is moved.DiagramItem
inherits QGraphicsPolygonItem and represents an item in the diagram.
MainWindow Class Definition
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); public slots: void itemMoved(DiagramItem *movedDiagram, const QPointF &moveStartPosition); private slots: void deleteItem(); void addBox(); void addTriangle(); void about(); void itemMenuAboutToShow(); void itemMenuAboutToHide(); private: void createActions(); void createMenus(); void createUndoView(); QAction *deleteAction; QAction *addBoxAction; QAction *addTriangleAction; QAction *undoAction; QAction *redoAction; QAction *exitAction; QAction *aboutAction; QMenu *fileMenu; QMenu *editMenu; QMenu *itemMenu; QMenu *helpMenu; DiagramScene *diagramScene; QUndoStack *undoStack; QUndoView *undoView; };
The MainWindow
class maintains the undo stack, i.e., it creates QUndoCommands and pushes and pops them from the stack when it receives the triggered()
signal from undoAction
and redoAction
.
MainWindow Class Implementation
We will start with a look at the constructor:
MainWindow::MainWindow() { undoStack = new QUndoStack(this); createActions(); createMenus(); createUndoView(); diagramScene = new DiagramScene(); QBrush pixmapBrush(QPixmap(":/images/cross.png").scaled(30, 30)); diagramScene->setBackgroundBrush(pixmapBrush); diagramScene->setSceneRect(QRect(0, 0, 500, 500)); connect(diagramScene, SIGNAL(itemMoved(DiagramItem*,QPointF)), this, SLOT(itemMoved(DiagramItem*,QPointF))); setWindowTitle("Undo Framework"); QGraphicsView *view = new QGraphicsView(diagramScene); setCentralWidget(view); resize(700, 500); }
In the constructor, we set up the DiagramScene and QGraphicsView.
Here is the createUndoView()
function:
void MainWindow::createUndoView() { undoView = new QUndoView(undoStack); undoView->setWindowTitle(tr("Command List")); undoView->show(); undoView->setAttribute(Qt::WA_QuitOnClose, false); }
The QUndoView is a widget that display the text, which is set with the setText() function, for each QUndoCommand in the undo stack in a list.
Here is the createActions()
function:
void MainWindow::createActions() { deleteAction = new QAction(tr("&Delete Item"), this); deleteAction->setShortcut(tr("Del")); connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteItem())); ... undoAction = undoStack->createUndoAction(this, tr("&Undo")); undoAction->setShortcuts(QKeySequence::Undo); redoAction = undoStack->createRedoAction(this, tr("&Redo")); redoAction->setShortcuts(QKeySequence::Redo);
The createActions()
function sets up all the examples actions in the manner shown above. The createUndoAction() and createRedoAction() helps us crate actions that are disabled and enabled based on the state of the stack. Also, the text of the action will be updated automatically based on the text() of the undo commands. For the other actions we have implemented slots in the MainWindow
class.
Here is the createMenus()
function:
void MainWindow::createMenus() { ... editMenu = menuBar()->addMenu(tr("&Edit")); editMenu->addAction(undoAction); editMenu->addAction(redoAction); editMenu->addSeparator(); editMenu->addAction(deleteAction); connect(editMenu, SIGNAL(aboutToShow()), this, SLOT(itemMenuAboutToShow())); connect(editMenu, SIGNAL(aboutToHide()), this, SLOT(itemMenuAboutToHide())); ... }
We have to use the QMenu aboutToShow()
and aboutToHide()
signals since we only want deleteAction
to be enabled when we have selected an item.
Here is the itemMoved()
slot:
void MainWindow::itemMoved(DiagramItem *movedItem, const QPointF &oldPosition) { undoStack->push(new MoveCommand(movedItem, oldPosition)); }
We simply push a MoveCommand on the stack, which calls redo()
on it.
Here is the deleteItem()
slot:
void MainWindow::deleteItem() { if (diagramScene->selectedItems().isEmpty()) return; QUndoCommand *deleteCommand = new DeleteCommand(diagramScene); undoStack->push(deleteCommand); }
An item must be selected to be deleted. We need to check if it is selected as the deleteAction
may be enabled even if an item is not selected. This can happen as we do not catch a signal or event when an item is selected.
Here is the itemMenuAboutToShow()
and itemMenuAboutToHide() slots:
void MainWindow::itemMenuAboutToHide() { deleteAction->setEnabled(true); } void MainWindow::itemMenuAboutToShow() { deleteAction->setEnabled(!diagramScene->selectedItems().isEmpty()); }
We implement itemMenuAboutToShow()
and itemMenuAboutToHide()
to get a dynamic item menu. These slots are connected to the aboutToShow() and aboutToHide() signals. We need this to disable or enable the deleteAction
.
Here is the addBox()
slot:
void MainWindow::addBox() { QUndoCommand *addCommand = new AddCommand(DiagramItem::Box, diagramScene); undoStack->push(addCommand); }
The addBox()
function creates an AddCommand and pushes it on the undo stack.
Here is the addTriangle()
sot:
void MainWindow::addTriangle() { QUndoCommand *addCommand = new AddCommand(DiagramItem::Triangle, diagramScene); undoStack->push(addCommand); }
The addTriangle()
function creates an AddCommand and pushes it on the undo stack.
Here is the implementation of about()
:
void MainWindow::about() { QMessageBox::about(this, tr("About Undo"), tr("The <b>Undo</b> example demonstrates how to " "use Qt's undo framework.")); }
The about slot is triggered by the aboutAction
and displays an about box for the example.
AddCommand Class Definition
class AddCommand : public QUndoCommand { public: AddCommand(DiagramItem::DiagramType addType, QGraphicsScene *graphicsScene, QUndoCommand *parent = 0); ~AddCommand(); void undo() override; void redo() override; private: DiagramItem *myDiagramItem; QGraphicsScene *myGraphicsScene; QPointF initialPosition; };
The AddCommand
class adds DiagramItem graphics items to the DiagramScene.
AddCommand Class Implementation
We start with the constructor:
AddCommand::AddCommand(DiagramItem::DiagramType addType, QGraphicsScene *scene, QUndoCommand *parent) : QUndoCommand(parent) { static int itemCount = 0; myGraphicsScene = scene; myDiagramItem = new DiagramItem(addType); initialPosition = QPointF((itemCount * 15) % int(scene->width()), (itemCount * 15) % int(scene->height())); scene->update(); ++itemCount; setText(QObject::tr("Add %1") .arg(createCommandString(myDiagramItem, initialPosition))); }
We first create the DiagramItem to add to the DiagramScene. The setText() function let us set a QString that describes the command. We use this to get custom messages in the QUndoView and in the menu of the main window.
void AddCommand::undo() { myGraphicsScene->removeItem(myDiagramItem); myGraphicsScene->update(); }
undo()
removes the item from the scene.
void AddCommand::redo() { myGraphicsScene->addItem(myDiagramItem); myDiagramItem->setPos(initialPosition); myGraphicsScene->clearSelection(); myGraphicsScene->update(); }
We set the position of the item as we do not do this in the constructor.
DeleteCommand Class Definition
class DeleteCommand : public QUndoCommand { public: explicit DeleteCommand(QGraphicsScene *graphicsScene, QUndoCommand *parent = 0); void undo() override; void redo() override; private: DiagramItem *myDiagramItem; QGraphicsScene *myGraphicsScene; };
The DeleteCommand class implements the functionality to remove an item from the scene.
DeleteCommand Class Implementation
DeleteCommand::DeleteCommand(QGraphicsScene *scene, QUndoCommand *parent) : QUndoCommand(parent) { myGraphicsScene = scene; QList<QGraphicsItem *> list = myGraphicsScene->selectedItems(); list.first()->setSelected(false); myDiagramItem = static_cast<DiagramItem *>(list.first()); setText(QObject::tr("Delete %1") .arg(createCommandString(myDiagramItem, myDiagramItem->pos()))); }
We know that there must be one selected item as it is not possible to create a DeleteCommand unless the item to be deleted is selected and that only one item can be selected at any time. The item must be unselected if it is inserted back into the scene.
void DeleteCommand::undo() { myGraphicsScene->addItem(myDiagramItem); myGraphicsScene->update(); }
The item is simply reinserted into the scene.
void DeleteCommand::redo() { myGraphicsScene->removeItem(myDiagramItem); }
The item is removed from the scene.
MoveCommand Class Definition
class MoveCommand : public QUndoCommand { public: enum { Id = 1234 }; MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos, QUndoCommand *parent = 0); void undo() override; void redo() override; bool mergeWith(const QUndoCommand *command) override; int id() const override { return Id; } private: DiagramItem *myDiagramItem; QPointF myOldPos; QPointF newPos; };
The mergeWith() is reimplemented to make consecutive moves of an item one MoveCommand, i.e, the item will be moved back to the start position of the first move.
MoveCommand Class Implementation
The constructor of MoveCommand looks like this:
MoveCommand::MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos, QUndoCommand *parent) : QUndoCommand(parent) { myDiagramItem = diagramItem; newPos = diagramItem->pos(); myOldPos = oldPos; }
We save both the old and new positions for undo and redo respectively.
void MoveCommand::undo() { myDiagramItem->setPos(myOldPos); myDiagramItem->scene()->update(); setText(QObject::tr("Move %1") .arg(createCommandString(myDiagramItem, newPos))); }
We simply set the items old position and update the scene.
void MoveCommand::redo() { myDiagramItem->setPos(newPos); setText(QObject::tr("Move %1") .arg(createCommandString(myDiagramItem, newPos))); }
We set the item to its new position.
bool MoveCommand::mergeWith(const QUndoCommand *command) { const MoveCommand *moveCommand = static_cast<const MoveCommand *>(command); DiagramItem *item = moveCommand->myDiagramItem; if (myDiagramItem != item) return false; newPos = item->pos(); setText(QObject::tr("Move %1") .arg(createCommandString(myDiagramItem, newPos))); return true; }
Whenever a MoveCommand is created, this function is called to check if it should be merged with the previous command. It is the previous command object that is kept on the stack. The function returns true if the command is merged; otherwise false.
We first check whether it is the same item that has been moved twice, in which case we merge the commands. We update the position of the item so that it will take the last position in the move sequence when undone.
DiagramScene Class Definition
class DiagramScene : public QGraphicsScene { Q_OBJECT public: DiagramScene(QObject *parent = 0); signals: void itemMoved(DiagramItem *movedItem, const QPointF &movedFromPosition); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; private: QGraphicsItem *movingItem; QPointF oldPos; };
The DiagramScene implements the functionality to move a DiagramItem with the mouse. It emits a signal when a move is completed. This is caught by the MainWindow
, which makes MoveCommands. We do not examine the implementation of DiagramScene as it only deals with graphics framework issues.
The main()
Function
The main()
function of the program looks like this:
int main(int argv, char *args[]) { Q_INIT_RESOURCE(undoframework); QApplication app(argv, args); MainWindow mainWindow; mainWindow.show(); return app.exec(); }
We draw a grid in the background of the DiagramScene, so we use a resource file. The rest of the function creates the MainWindow
and shows it as a top level window.
Files:
- tools/undoframework/commands.cpp
- tools/undoframework/commands.h
- tools/undoframework/diagramitem.cpp
- tools/undoframework/diagramitem.h
- tools/undoframework/diagramscene.cpp
- tools/undoframework/diagramscene.h
- tools/undoframework/mainwindow.cpp
- tools/undoframework/mainwindow.h
- tools/undoframework/main.cpp
- tools/undoframework/undoframework.pro
- tools/undoframework/undoframework.qrc
Images:


open class JavaxInjectionConfig : InjectionConfig
An implementation of |
|
open class JavaxInjectMockspressoPlugin : MockspressoPlugin
A Mockspresso Plugin that applies logic to simulate a javax.inject compatible DI framework. |
|
open class ProviderMaker : SpecialObjectMaker
An implementation of SpecialObjectMaker for |
open class MultipleInjectConstructorException : VerifyError
Exception thrown when trying to create an object with multiple @Inject constructors (when using the JavaxInjectionConfig |


A circular lollipop plot with a highly customized layout to explore
password popularity and strengths made with R
and
ggplot2
. This blogpost guides you through a
step-by-step construction of a custom circular lollipop plot that
includes a variety of tricks to make the final result much more
beautiful.
This page showcases the work of Cédric Scherer, built for the TidyTuesday initiative. You can find the original code on his Github repository here.
Thanks to him for accepting sharing his work here! Thanks also to Tomás Capretto who split the original code into this step-by-step guide! 🙏🙏
As a teaser, here is the plot we’re gonna try building:
Let’s start by loading the packages needed to build the figure.
ggtext
, and
patchwork
stand out today. ggtext
makes it very easy to style text
with Markdown or HTML, and patchwork
allows us to compose
ggplot2 figures very smoothly.
library(tidyverse)
library(ggtext)
library(patchwork)
Today, the plot is going to be based on the
Roboto Mono font family. If you are unsure about how
to work with custom fonts in R
,
this post
is for you.
This guide shows how to create a beautiful multipanel circular lollipop plot to visualize password popularity and strengths.
The data for this post comes from Information is Beautiful. This guide uses the dataset released for the TidyTuesday initiative on the week of 2020-01-14. You can find the original announcement and more information about the data here. Thank you all for making this guide possible!
Let’s start by loading the dataset:
<- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-01-14/passwords.csv') %>%
df_pw # Remove rows where the password is missing
filter(!is.na(password))
From all the columns in the data frame, only rank
,
password
, category
, value
, and
time_unit
are going to be used. Let’s see what they mean:
rank
Popularity in the database of released passwords
password
The text of the passwordcategory
The category where the password falls into
value
Time to crack by online guessingtime_unit
Time unit to match with value
The next step is to convert all the time values to a common unit such
as seconds. This task suits very well for the
case_when()
function.
<-
df_pw_time %>%
df_pw mutate(
time = case_when(
== "seconds" ~ value,
time_unit == "minutes" ~ value * 60,
time_unit == "hours" ~ value * 60 * 60,
time_unit == "days" ~ value * 60 * 24,
time_unit == "weeks" ~ value * 60 * 24 * 7,
time_unit == "months" ~ value * 60 * 24 * 30,
time_unit == "years" ~ value * 60 * 24 * 365,
time_unit TRUE ~ NA_real_
) )
Next, a fixed value of 1000 is added to all the times. This is going to leave the extra space needed for the labels within the circle.
<- 1000
plus <-
df_pw_plot %>%
df_pw_time mutate(time = time + plus) %>%
add_row(rank = 501, time = 1)
And finally, create a data frame with all the information required to place labels for passwords that were really hard to crack.
<-
labels %>%
df_pw_plot # Value > 90 selects those above 90 years!
filter(value > 90) %>%
# Create label out of the password and its rank
mutate(label = glue::glue("{password}
Rank: {rank}")) %>%
# These columns give the position of the labels
add_column(
x = c(33, 332, 401, 492),
y = c(75000000, 90000000, 45000000, 48498112)
)
Did you note that HTML within the label string? That is one of the
many ways to tell ggtext
how to customize the text in the
plot. That library is great!
Let’s start by creating the circular plot on the top panel:
<- ggplot(df_pw_plot, aes(rank, time, color = category)) +
main # This segment represents the vertical lines
geom_segment(
aes(x = rank, xend = rank, y = 0, yend = time),
size = 1.2
+
) # This rect is converted into the inner circle where we're going to place text
# when converting the plot to circular coordinates.
geom_rect(
aes(xmin = 1, xmax = 501, ymin = 0, ymax = plus),
fill = "grey97", color = "grey97"
+
)
# Add our custom grid lines for the radial axis.
# These lines indicate one day, one week, one month and one year.
geom_hline(aes(yintercept = (1 * 24 * 60 + plus)), color = "grey88") +
geom_hline(aes(yintercept = (7 * 24 * 60 + plus)), color = "grey85") +
geom_hline(aes(yintercept = (30 * 24 * 60 + plus)), color = "grey82") +
geom_hline(aes(yintercept = (365 * 24 * 60 + plus)), color = "grey79") +
# Add points on the end of each line
geom_point(aes(size = time)) +
# Polar axis (y-axis) is in log10 scale
scale_y_log10(expand = c(0, 0)) +
# Use the Prism color scale for the categories
::scale_color_carto_d(palette = "Prism", guide = "none") +
rcartocolor
# Assign a range for the size of the dots
scale_size(
range = c(1, 8),
limits = c(plus, max(df_pw_plot$time)),
guide = "none"
+
)
# Make it circular!
coord_polar()
main
Converting a plot from cartesian to circular (polar) coordinates in
ggplot2
is as easy as adding a
coord_polar()
call to the plot. So neat!
The plot obtained so far looks quite nice, but it’s not done. It still lacks something that indicates how to read the story this chart is trying to tell and the labels that highlight those very hard to crack passwords. Let’s do it!
<- main +
main # Add labels with `geom_richtext()`
geom_richtext(
data = labels,
aes(x = x, y = y, label = label, color = category),
lineheight = 0.8,
size = 8,
family = "Roboto Mono",
label.color = NA
+
) # Regular text with `geom_text()`
# Note that coordinates are explicitly passed here.
geom_text(
x = 500, y = 1.2,
label = "********\nCracking\nYour Favorite\nPassword",
family = "Roboto Mono Medium",
size = 20,
lineheight = 0.87,
color = "grey60"
+
) geom_text(
x = 250, y = 0.25,
label = "********",
family = "Roboto Mono Medium",
size = 20,
lineheight = 0.87,
color = "grey60"
+
) geom_text(
x = 250, y = 1.1,
label = "Time it takes to crack the 500 most\ncommon passwords by online guessing.\nSorted by rank and colored by category.",
family = "Roboto Mono",
size = 7,
lineheight = 0.87,
color = "grey73"
+
) geom_text(
x = 250, y = 1.95,
label = "Time is displayed on a logarithmic scale\nwith the rings representing one day,\none week, one month, and one year\n(from inner to outer ring).",
family = "Roboto Mono",
size = 6,
lineheight = 0.87,
color = "grey73"
)
main
geom_richtext()
is kind of magical. Just give it got some
text formatted with HTML and it takes care of everything needed to
succesfully protray the formatted label in the figure.
So far, this is enough for the top-panel figure. Further modifications such as a different background color and margin adjustments are going to happen when this plot is composed with the lower-panel figures.
The original plot we’re trying to replicate consists of several panels
and all the work above only replicates the bigger panel on top. The
good news is that ggplot2
makes it really easy to reuse
existing code for a plot and convert it into a plot made of multiple
panels.
First of all, it’s necessary to add line breaks to some existing category names so they fit within the inner circle.
<-
facet_data %>%
df_pw_plot add_row(rank = 501, time = 1, category = unique(df_pw_plot$category)) %>%
# This is where we add line breaks
mutate(
cat_label = case_when(
== "cool-macho" ~ "cool-\nmacho",
category == "nerdy-pop" ~ "nerdy-\npop",
category == "password-related" ~ "password-\nrelated",
category == "rebellious-rude" ~ "rebel-\nlious-\nrude",
category == "simple-alphanumeric" ~ "simple-\nalpha-\nnumeric",
category TRUE ~ category
)%>%
) filter(!is.na(category))
And now let’s make the plot!
# Much of the code is the same than the code above.
<- ggplot(facet_data, aes(rank, time, color = category)) +
facet geom_segment(
aes(x = rank, xend = rank, y = 0, yend = time),
size = 0.6
+
) geom_rect(
aes(xmin = 1, xmax = 501, ymin = 0, ymax = plus),
fill = "grey97", color = "grey97"
+
) geom_hline(aes(yintercept = (1 * 24 * 60 + plus)), color = "grey82", size = 0.2) +
geom_hline(aes(yintercept = (7 * 24 * 60 + plus)), color = "grey79", size = 0.2) +
geom_hline(aes(yintercept = (30 * 24 * 60 + plus)), color = "grey76", size = 0.2) +
geom_hline(aes(yintercept = (365 * 24 * 60 + plus)), color = "grey73", size = 0.2) +
geom_point(aes(size = time)) +
# This is what adds the label within each circle
geom_text(
aes(label = cat_label, color = category),
x = 500, y = 0,
family = "Roboto Mono Medium",
size = 8,
lineheight = 0.87
+
) # This is what wraps the panels for the categories into a layout of 2 rows
facet_wrap(~ category, nrow = 2) +
coord_polar() +
scale_y_log10(expand = c(0, 0)) +
::scale_color_carto_d(palette = "Prism", guide = "none") +
rcartocolorscale_size(
range = c(0.5, 7),
limits = c(plus, max(df_pw_plot$time)),
guide = "none"
+
) theme(
strip.text = element_blank(),
)
facet
Did you spot the difference in the code? Just adding
facet_wrap(~ category, nrow = 2)
tells
ggplot2
to create a plot for each level in the
category
variable and arrange them in a 2-row layout.
The two plots obtained above can be composed very easily into a single
figure thanks to the patchwork
package. At this stage, it
is also important to adjust the margins and the space between the
panels to obtain a better appearece. Are you ready to finish? Let’s
go!
# Customize the main panel (top-panel)
<- main +
main # This 'theme_void' adds a completely empty theme
theme_void() +
# These negative margins are VERY important to obtain a tight layout.
theme(
plot.margin = margin(-50, -180, -70, -180, "lines"),
)
<- facet +
facet # Same theme_void for the lower panels
theme_void() +
theme(
# Negative spacing between panels, which means they overlap
panel.spacing = unit(-8, "lines"),
# Negative margin on top, to decrease blank space between these panels
# and the main plot on top
plot.margin = margin(-40, 50, 10, 50)
+
) # Adjust settings for the caption
theme(
plot.caption = element_text(
family = "Roboto Mono Medium",
size = 20,
color = "grey60",
hjust = 0.5,
margin = margin(-50, 10, 30, 10)
)+
) # Add caption
labs(caption = "Visualization by Cédric Scherer ∙ Data by Knowledge is Beautiful")
# Combine the two plots
# The '+' means to 'add' the two ggplot2 plots together.
<- (main + facet) +
panel plot_layout(
ncol = 1, # Results in one plot on top and another on the bottom.
heights = c(1, 0.28) # Height assigned to each plot
) panel
Awesome, we nailed it!!🥳


Low Income Scheme
If you find it difficult to pay for health costs you may be entitled to some help towards the cost of:
- NHS Prescriptions;
- NHS Dental treatment;
- NHS wigs and fabric supports;
- sight tests, glasses and contact lenses;
- travel to receive NHS treatment if referred by a doctor (GP or hospital doctor) or dentist
You can claim any time. Do not wait until you need treatment.
You cannot get help with health costs if you or your partner (or both) have more than:
- £16,000 in savings, investments & properties (not counting the place where you live); or
- £23,250 in savings, investments & properties if you permanently live in a care home
You are already entitled to full help with health costs if you are:
- getting income support
- getting pension credit guarantee credit
- getting universal credit
- named on, or entitled to, an NHS Tax Credit Exemption certificate
You can claim for:
- yourself;
- your partner; or
- your children;


HOME
DEADLINES
STUDENT PROFILES
WEEKLY REPORTS
COMPANY LIST
SHORTLIST
LOG OUT
{% for business in businesses %}
{{business.bname}}
{% for student in temps[business.businessID] %}
Intern Name : {{ student }}
{% for intern in students_list %} {% if intern.name == student %}
Student ID: {{ intern.uwiid }}
Student GPA: {{ intern.gpa }}
{% endif %} {% endfor %}
{% endfor %}
{% endfor %}


Edax play control - header file. More...
Go to the source code of this file.
Classes | |
| struct | Play |
Macros | |
| #define | PLAY_MESSAGE_MAX_LENGTH 4096 |
Typedefs | |
| typedef struct Play | Play |
Functions | |
| bool | play_is_game_over (Play *) |
| Check if game is over. | |
| bool | play_must_pass (Play *play) |
| Check if player must pass. | |
| void | play_init (Play *, Book *) |
| Initialization. | |
| void | play_free (Play *) |
| Free resources. | |
| void | play_new (Play *) |
| Start a new game. | |
| void | play_ggs_init (Play *, const char *) |
| bool | play_load (Play *, const char *) |
| Load a saved game. | |
| void | play_save (Play *, const char *) |
| Save a played game. | |
| void | play_auto_save (Play *) |
| void | play_go (Play *, const bool) |
| Start thinking. | |
| void | play_hint (Play *, int) |
| Start thinking. | |
| void | play_stop (Play *) |
| Stop thinking. | |
| void * | play_ponder_run (void *) |
| do ponderation. | |
| void | play_ponder (Play *) |
| Ponder. | |
| void * | play_ponder_loop (void *) |
| void | play_stop_pondering (Play *) |
| Stop pondering. | |
| void | play_update (Play *, Move *) |
| Update the game. | |
| void | play_pass (Play *) |
| void | play_undo (Play *) |
| Undo a move. | |
| void | play_redo (Play *) |
| Redo a move. | |
| void | play_set_board (Play *, const char *) |
| Set a new board. | |
| void | play_set_board_from_FEN (Play *, const char *) |
| Set a new board. | |
| void | play_game (Play *, const char *) |
| Play a move sequence. | |
| bool | play_move (Play *, int) |
| Play a move. | |
| bool | play_user_move (Play *, const char *) |
| Play a user move. | |
| Move * | play_get_last_move (Play *) |
| Get the last played move. | |
| void | play_analyze (Play *, int) |
| Analyze a played game. | |
| void | play_book_analyze (Play *, int) |
| Analyze a played game. | |
| void | play_learn (Play *) |
| void | play_store (Play *) |
| store the game into the opening book | |
| void | play_adjust_time (Play *, const int, const int) |
| adjust time. | |
| void | play_print (Play *, FILE *) |
| Print the game state. | |
| void | play_force_init (Play *, const char *) |
| Initialize a forced line. | |
| void | play_force_update (Play *) |
| Update a forced line. | |
| void | play_force_restore (Play *) |
| Restore a forced line. | |
| bool | play_force_go (Play *, Move *) |
| Play a forced move. | |
| void | play_symetry (Play *, const int) |
| Get the symetry of the actual position. | |
| const char * | play_show_opening_name (Play *, const char *(*opening_get_name)(const Board *)) |
| Print the opening name. |
Edax play control - header file.
| #define PLAY_MESSAGE_MAX_LENGTH 4096 |
error message max length
| void play_adjust_time | ( | Play * | play, |
| const int | left, | ||
| const int | extra | ||
| ) |
adjust time.
Set remaining time to play from a server (GGS) or a GUI (Quarry, ...).
| play | Play. |
| left | Time left. |
| extra | Extra time. |
| void play_analyze | ( | Play * | play, |
| int | n | ||
| ) |
Analyze a played game.
| play | Play. |
| n | number of moves to analyze. |
| void play_auto_save | ( | Play * | ) |
| void play_book_analyze | ( | Play * | play, |
| int | n | ||
| ) |
Analyze a played game.
| play | Play. |
| n | number of moves to analyze. |
| void play_force_init | ( | Play * | play, |
| const char * | string | ||
| ) |
Initialize a forced line.
| play | Play. |
| string | A string with a sequence of moves. |
| void play_force_restore | ( | Play * | play | ) |
Restore a forced line.
Check if the actual board is in the forced line, and restore the forced line accordingly.
| play | Play. |
| void play_force_update | ( | Play * | play | ) |
Update a forced line.
Check if the actual board is in the forced line, and update the forced line accordingly.
| play | Play. |
| void play_game | ( | Play * | play, |
| const char * | string | ||
| ) |
| void play_ggs_init | ( | Play * | , |
| const char * | |||
| ) |
| void play_go | ( | Play * | play, |
| const bool | update | ||
| ) |
Start thinking.
| play | Play. |
| update | Flag to tell if edax should update or no its game. |
| void play_hint | ( | Play * | play, |
| int | n | ||
| ) |
Start thinking.
Evaluate first best moves of the position.
| play | Play. |
| n | Number of (best) moves to evaluate. |
| bool play_is_game_over | ( | Play * | play | ) |
| void play_learn | ( | Play * | ) |
| bool play_load | ( | Play * | play, |
| const char * | file | ||
| ) |
Load a saved game.
| play | Play. |
| file | File name of the game. |
| bool play_move | ( | Play * | play, |
| int | x | ||
| ) |
| bool play_must_pass | ( | Play * | play | ) |
| void play_pass | ( | Play * | ) |
| void play_ponder | ( | Play * | play | ) |
Ponder.
Think during opponent time. Activate the thread suspended in play_ponder_loop.
| play | Play. |
| void* play_ponder_loop | ( | void * | ) |
| void* play_ponder_run | ( | void * | v | ) |
do ponderation.
Ponderation (thinking during opponent time) is done within a thread. The thread is launched at startup and immediately suspended, thanks to condition_wait. When edax is required to ponder, the thread is activated by a condition_signal, and the search start. To stop the ponderation, just stop the search and wait for the lock to be release.
| v | the play. |
| void play_print | ( | Play * | play, |
| FILE * | f | ||
| ) |
Print the game state.
Print the game state: board, time, played move, etc.
| play | Play. |
| f | Output stream. |
| void play_save | ( | Play * | play, |
| const char * | file | ||
| ) |
Save a played game.
| play | Play. |
| file | File name of the game. |
| void play_set_board | ( | Play * | play, |
| const char * | board | ||
| ) |
Set a new board.
| play | Play. |
| board | A new board. |
| void play_set_board_from_FEN | ( | Play * | play, |
| const char * | board | ||
| ) |
Set a new board.
| play | Play. |
| board | A new board. |
Print the opening name.
| void play_stop_pondering | ( | Play * | play | ) |
Stop pondering.
If edax is pondering, stop the search, and wait that the pondering thread is suspended.
| play | Play. |
| void play_symetry | ( | Play * | play, |
| const int | sym | ||
| ) |
Get the symetry of the actual position.
| play | Play. |
| sym | Symetry. |


m
CortanaRGB is worlds most affordable Cortana activated RGB ledstrip. With CortanaRGB you will be able to control a RGB ledstrip using your voice.  Because CortanaRGB intergrates Cortana it has excellent voice recogonition and also seamlessly intergrates with Windows 10 using the CortanaRGB app.
CortanaRGB works in
a new way because
CortanaRGB uses a
Windows 10 pc for
the processing
For €21 you
recieve everyting
you need to get
CortanaRGB working
including a RGB ledstrip
CortanaRGB has a lot
of functions like:
build in effects
9 build in colors
costum color creation
CortanaRGB is very
easy to install in 4
simple steps and uses
simple voice commands
for control
DeedeBee
Guest 474202959
Guest<PHONE_NUMBER>
aoife and ryan
Jan Hoek
Kevin van Manen
Richard Schaper www.r2r.nl
Thomas Bremer
Lawrence Loy LT
Marjolein van Elteren
Marco
Luit Elferink
Guest 453986640
Guest 346376030
W.h Groeneweg
Peter Law
Micheal


| Overview | Namespace | Class | Index | Help |
| PUBLIC MEMBERS: | CLASSES | STRUCTS | UNIONS | ENUMS | TYPEDEFS | METHODS | STATIC METHODS | DATA | STATIC DATA |
| PROTECTED MEMBERS: | CLASSES | STRUCTS | UNIONS | ENUMS | TYPEDEFS | METHODS | STATIC METHODS | DATA | STATIC DATA |
| virtual | abstract | interface | template |
| NO | NO | NO | NO |
Methods |
|
| XInterface * get( ) const throw( ); |
Gets interface pointer. This call does not acquire the interface. |
| sal_Bool is( ) const throw( ); |
Checks if reference is null. |
| sal_Bool operator==( XInterface * pInterface ) const throw( ); |
Equality operator: compares two interfaces Checks if both references are null or refer to the same object. |
| sal_Bool operator!=( XInterface * pInterface ) const throw( ); |
Unequality operator: compares two interfaces Checks if both references are null or refer to the same object. |
| sal_Bool operator==( const BaseReference & rRef ) const throw( ); |
Equality operator: compares two interfaces Checks if both references are null or refer to the same object. |
| sal_Bool operator!=( const BaseReference & rRef ) const throw( ); |
Unequality operator: compares two interfaces Checks if both references are null or refer to the same object. |
| sal_Bool operator<( const BaseReference & rRef ) const throw( ); |
Needed by some STL containers. |
Static Methods |
|
| static XInterface * iquery( XInterface * pInterface, const Type & rType ) throw( RuntimeException ); |
Queries given interface for type rType. |
| static XInterface * iquery_throw( XInterface * pInterface, const Type & rType ) throw( RuntimeException ); |
Queries given interface for type rType. Throws a RuntimeException if the demanded interface cannot be queried. |
Data |
|
| XInterface * _pInterface; | the interface pointer |
Copyright © 2012, The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache, the Apache feather logo, Apache OpenOffice and OpenOffice.org are trademarks of The Apache Software Foundation. Other names may be trademarks of their respective owners.


Arnaud Dellinger, 21 years old
LinkedIn
Github
Medium
Twitter
Angel
I always loved creating web applications, starting with the 1st one when I was 8 — I'm 21 now.
Today, I usually do this using React.js which I started using ~ 3 years ago. What else do I know?
More of my projects are listed on my LinkedIn.
I recently released a Udemy course about React 👈 and another one about modern JavaScript syntax (both are in french).
I love sharing my knowledge and keeping it simple. This year I teached JavaScript to a 40yo+ mother.
Isn't it great? I mean, she was amazing.
I speak English, French and I've been learning Spanish at school and German on my free-time.
I also learn Chinese 🇨🇳🇹🇼 on my own since slightly more than 2 years. This is how my bedroom looked after the first week.
Earlier this year I had fun translating a Silicon Valley S4 episode.
Joyful & keen to become a better developer,
I sure believe in teamwork and great people.
Looking for an intern? reach me outYou're doing the right thing


Connect to KOREAN-PLC in the Course Register.
KOREAN
KORN-312 CURRENT KOREAN MEDIA II 1 CU 680 LEC MW 3:30-5PM WILL 741 CHUNG E MAX: 15 KORN-381 BUSINESS KOREAN I 1 CU 680 LEC TR 4:30-6PM WILL 302 CHO H MAX: 15 KORN-482 ADV BUSINESS KOREAN II 1 CU 680 LEC MW 5-6:30PM WILL 305 KIM D MAX: 16
Return to Course & Room Roster
Comments to:
Office of the University Registrar
University of Pennsylvania
Room 221 Franklin Building
3451 Walnut Street
Philadelphia, PA 19104-6291
Phone:<PHONE_NUMBER> Fax:<PHONE_NUMBER>
<EMAIL_ADDRESS>Updated: Sat Jan 17 08:30:02 2015


| Selected date: {{aDate}} | Selected date: {{aDate2}} |
Pitchfork Cosby sweater kale chips art party plaid, irony dreamcatcher freegan. Truffaut artisan blog, direct trade sriracha XOXO squid vinyl Marfa small batch single-origin coffee Bushwick church-key slow-carb. Paleo master cleanse selvage, Odd Future farm-to-table artisan Pitchfork ethnic American Apparel bitters High Life narwhal. Chillwave mixtape cornhole, post-ironic pickled 3 wolf moon ethnic deep v Banksy bespoke put a bird on it synth plaid organic four loko. Pickled Marfa squid next level. Seitan keffiyeh pug PBR locavore, Austin try-hard Williamsburg tousled. Beard sustainable jean shorts, banh mi hashtag chillwave twee lo-fi DIY retro Odd Future single-origin coffee post-ironic.
Paleo mlkshk fingerstache Pitchfork. Raw denim photo booth Portland polaroid viral, fixie yr flannel post-ironic dreamcatcher selvage. IPhone sustainable shabby chic hella viral XOXO. Synth bitters organic, trust fund locavore plaid selfies High Life Intelligentsia meh. Williamsburg tattooed +1 cred, readymade Cosby sweater forage Echo Park wayfarers brunch sartorial VHS hoodie. 8-bit synth cred, High Life polaroid Godard Cosby sweater cardigan. Vegan cardigan VHS organic, put a bird on it gluten-free authentic pickled stumptown DIY dreamcatcher cliche beard deep v farm-to-table.
Do you need some dummy text? *sigh* Of course you do.
I bet you still use Helvetica too…
Pitchfork Cosby sweater kale chips art party plaid, irony dreamcatcher freegan. Truffaut artisan blog, direct trade sriracha XOXO squid vinyl Marfa small batch single-origin coffee Bushwick church-key slow-carb. Paleo master cleanse selvage, Odd Future farm-to-table artisan Pitchfork ethnic American Apparel bitters High Life narwhal. Chillwave mixtape cornhole, post-ironic pickled 3 wolf moon ethnic deep v Banksy bespoke put a bird on it synth plaid organic four loko. Pickled Marfa squid next level. Seitan keffiyeh pug PBR locavore, Austin try-hard Williamsburg tousled. Beard sustainable jean shorts, banh mi hashtag chillwave twee lo-fi DIY retro Odd Future single-origin coffee post-ironic.
Paleo mlkshk fingerstache Pitchfork. Raw denim photo booth Portland polaroid viral, fixie yr flannel post-ironic dreamcatcher selvage. IPhone sustainable shabby chic hella viral XOXO. Synth bitters organic, trust fund locavore plaid selfies High Life Intelligentsia meh. Williamsburg tattooed +1 cred, readymade Cosby sweater forage Echo Park wayfarers brunch sartorial VHS hoodie. 8-bit synth cred, High Life polaroid Godard Cosby sweater cardigan. Vegan cardigan VHS organic, put a bird on it gluten-free authentic pickled stumptown DIY dreamcatcher cliche beard deep v farm-to-table.
Do you need some dummy text? *sigh* Of course you do.
I bet you still use Helvetica too…


Public Member Functions | |
| def | __init__ |
| def | addResource |
| def | addMyResource |
| def | uploadApp |
| def | getStatus |
| def | getResourceNames |
| def | iterResources |
| def | getResource |
| def | getHostMax |
| def | getMaxJobs |
| def | getResults |
| def | disconnect |
| def | disconnect_all |
Public Attributes | |
| config | |
| resources | |
| resourcemax | |
| maxJobs | |
| cwenv |
This class is the core back end of the gateway. The web service and WSDL will plug into this class
| def cyberweb.lib.jodis.resource_manager.Manager.__init__ | ( | self, | |
config = None |
|||
| ) |
| def cyberweb.lib.jodis.resource_manager.Manager.addMyResource | ( | self, | |
| account_id, | |||
maxjobs = 0 , |
|||
myglobals = None |
|||
| ) |
| def cyberweb.lib.jodis.resource_manager.Manager.addResource | ( | self, | |
| name, | |||
| host, | |||
| user, | |||
| queuesystem, | |||
| max, | |||
config = None , |
|||
keyfile = None , |
|||
gsissh = False , |
|||
account = None |
|||
| ) |
| def cyberweb.lib.jodis.resource_manager.Manager.disconnect | ( | self, | |
| host | |||
| ) |
| def cyberweb.lib.jodis.resource_manager.Manager.getHostMax | ( | self, | |
| host | |||
| ) |
| def cyberweb.lib.jodis.resource_manager.Manager.getResource | ( | self, | |
| host | |||
| ) |
| def cyberweb.lib.jodis.resource_manager.Manager.uploadApp | ( | self, | |
| srcPath, | |||
| md5, | |||
srcHost = None , |
|||
srcUser = None |
|||
| ) |
Upload a file from the web server machine to the target resource.


| Job Vacancy |
Number of Personnel to be Hired |
Number of Applicants you want to be Endorsed |
Duties and Functions |
Qualifications |
Closing Date of Position |
Date for Examination Interview |
Venue for Interview (Complete Address) |
Date/Month Expected to Hire Requested Workers |
Documents Required from Applicants |
Company Id |
|