Copy/paste connected shape in Acrobat Reader

Adobe Acrobat Reader DC has a “shape” called “Connected Lines” in the comments pane. I wanted to copy/paste and move one around. This was a pain in the neck. I wasn’t expecting it to be that hard.

I ran into three problems:

1 – Pasting only works in a certain mode

I select the shape with ctrl-C. If I press ctrl-v to paste, nothing happens. Why? Apparently because I have the comment feature open. If I open the stamp feature or click “close” so nothing is open, it does paste. Ok fine. Except…

2 – It doesn’t paste where I put the mouse cursor

When I get it to paste, it always seems to be the center middle of the screen towards the bottom. This is rarely where I want my pasted item. This would be a minor annoyance except

3. It doesn’t let me drag with the mouse

A text comment box, I can select with my mouse and drag where I want it. A connected shape changes the shape when I try to select it. I can use the arrow keys to move it but that is slow and tedious… Oh wait. I figured it out. If I mouse over very carefully to the center of the connected shape, my mouse turns into a drag icon and I can drag it with my mouse.

New Zoom self-selecting breakout rooms

I live the new Zoom feature to be able to switch between breakout rooms. You have to be on the latest zoom and the feature has to be enabled for your meeting.

After clicking breakout rooms at the bottom, you see the choices along with who is in each room. The trick is mousing over the number. If I mouse over “5”, it turns into the word join.

You can join a breakout from either the main room or another breakout. And you can always go back to the main room by clicking “leave breakout room.”

This is far better than my hack of joining as my computer, iPad and iPhone and switching physical devices. It also lets the team know which session I am actually paying attention too!

Multi statement lambda and for each anti patterns

When I do a code review of lambda/stream code, I am immediately suspicious of two things – block statement lambdas and forEach().

What’s wrong with this? It’s functional programming right?

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
		
AtomicInteger sum = new AtomicInteger();
List<Integer> odds = new ArrayList<>();
List<Integer> evens = new ArrayList<>();
		
list.forEach(n -> {
	sum.addAndGet(n);
	if (n % 2 == 0) {
		evens.add(n);
	} else {
		odds.add(n);
	}
});
		
odds.forEach(System.out::println);
System.out.println();
evens.forEach(System.out::println);
System.out.println();
System.out.println(sum);

Well? Not really. It does have a lambda. It doesn’t have a stream, but that’s easy enough to fix: list.stream().forEach(…).

All better? No. Just because you are using a stream doesn’t mean you are doing functional programming. I would much rather see this code as:

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
		
		
list.stream()
   .filter(x -> x % 2 == 1)
   .forEach(System.out::println);

System.out.println();

list.stream()
   .filter(x -> x % 2 == 0)
   .forEach(System.out::println);

System.out.println();

list.stream()
   .mapToInt(x -> x)
   .sum();

Yes, I’m still using forEach(). But now I’m using it for one purpose (printing) rather than sticking logic in it.

Whenever I see a forEach() or lambda with more than one statement, my first thought is “could this be clearer or more functional.” Often the answer is yes. Filter(), map() and collect() are you friends.

And if I did need that List?

list.stream()
   .filter(x -> x % 2 == 1)
   .collect(Collectors.toList());